diff --git a/awx/ui/static/js/controllers/Projects.js b/awx/ui/static/js/controllers/Projects.js index ae8b02a3c9..919b7a5b07 100644 --- a/awx/ui/static/js/controllers/Projects.js +++ b/awx/ui/static/js/controllers/Projects.js @@ -44,50 +44,55 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, $scope.removePostRefresh(); } $scope.removePostRefresh = $scope.$on('PostRefresh', function () { - // Cleanup after a delete - var j, i; Wait('stop'); - $('#prompt-modal').modal('hide'); - + if ($scope.projects) { - for (i = 0; i < $scope.projects.length; i++) { - if ($scope.projects[i].status === 'ok') { + $scope.projects.forEach(function(project, i) { + if (project.status === 'ok') { $scope.projects[i].status = 'n/a'; } - switch ($scope.projects[i].status) { - case 'n/a': - $scope.projects[i].badge = 'none'; - break; - case 'updating': - case 'successful': - case 'ok': - $scope.projects[i].badge = 'false'; - break; - case 'never updated': - case 'failed': - case 'missing': - $scope.projects[i].badge = 'true'; - break; + switch (project.status) { + case 'n/a': + case 'never updated': + $scope.projects[i].statusIcon = 'none'; + $scope.projects[i].statusTip = 'No SCM updates have run for this project'; + break; + case 'updating': + $scope.projects[i].statusIcon = 'running pulsate'; + $scope.projects[i].statusTip = 'Running! Click for details'; + break; + case 'successful': + $scope.projects[i].statusIcon = 'success'; + $scope.projects[i].statusTip = 'Success! Click for details'; + break; + case 'failed': + case 'missing': + $scope.projects[i].statusTip = 'Failed. Click for details'; + $scope.projects[i].statusIcon = 'error'; + break; } - $scope.projects[i].last_updated = ($scope.projects[i].last_updated !== null) ? - FormatDate(new Date($scope.projects[i].last_updated)) : null; - for (j = 0; j < $scope.project_scm_type_options.length; j++) { - if ($scope.project_scm_type_options[j].value === $scope.projects[i].scm_type) { - $scope.projects[i].scm_type = $scope.project_scm_type_options[j].label; - if ($scope.projects[i].scm_type === 'Manual') { + if (project.summary_fields.last_update && project.summary_fields.last_update.status === 'canceled') { + $scope.projects[i].statusTip = 'Canceled. Click for details'; + } + + $scope.project_scm_type_options.forEach(function(type) { + if (type.value === project.scm_type) { + $scope.projects[i].scm_type = type.label; + if (type.label === 'Manual') { $scope.projects[i].scm_update_tooltip = 'Manaul projects do not require an SCM update'; $scope.projects[i].scm_schedule_tooltip = 'Manual projects do not require a schedule'; $scope.projects[i].scm_type_class = 'btn-disabled'; + $scope.projects[i].statusTip = 'Not configured for SCM'; + $scope.projects[i].statusIcon = 'none'; } else { $scope.projects[i].scm_update_tooltip = "Start an SCM update"; $scope.projects[i].scm_schedule_tooltip = "Schedule future SCM updates"; $scope.projects[i].scm_type_class = ""; } - break; } - } - } + }); + }); } }); @@ -98,7 +103,7 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, var opt; list.fields.scm_type.searchOptions = $scope.project_scm_type_options; - list.fields.status.searchOptions = $scope.project_status_options; + //list.fields.status.searchOptions = $scope.project_status_options; if ($routeParams.scm_type && $routeParams.status) { // Request coming from home page. User wants all errors for an scm_type @@ -188,40 +193,28 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, $scope.showSCMStatus = function (id) { // Refresh the project list - var i, statusCheckRemove = $scope.$on('PostRefresh', function () { - var project; - for (i= 0; i < $scope.projects.length; i++) { - if ($scope.projects[i].id === id) { - project = $scope.projects[i]; - break; - } - } - if (project.scm_type !== null) { - if (project.related.current_update) { - Wait('start'); - ProjectStatus({ - project_id: id, - last_update: project.related.current_update - }); - } else if (project.related.last_update) { - Wait('start'); - ProjectStatus({ - project_id: id, - last_update: project.related.last_update - }); - } else { - Alert('No Updates Available', 'There is no SCM update information available for this project. An update has not yet been ' + - ' completed. If you have not already done so, start an update for this project.', 'alert-info'); - } + var project = Find({ list: $scope.projects, key: 'id', val: id }); + if (Empty(project.scm_type) || project.scm_type === 'Manual') { + Alert('No SCM Configuration', 'The selected project is not configured for SCM. To configure for SCM, edit the project and provide SCM settings, ' + + 'and then run an update.', 'alert-info'); + } else { + if (project.related.current_update) { + Wait('start'); + ProjectStatus({ + project_id: id, + last_update: project.related.current_update + }); + } else if (project.related.last_update) { + Wait('start'); + ProjectStatus({ + project_id: id, + last_update: project.related.last_update + }); } else { - Alert('Missing SCM Configuration', 'The selected project is not configured for SCM. You must first edit the project, provide SCM settings, ' + - 'and then run an update.', 'alert-info'); + Alert('No Updates Available', 'There is no SCM update information available for this project. An update has not yet been ' + + ' completed. If you have not already done so, start an update for this project.', 'alert-info'); } - statusCheckRemove(); - }); - - // Refresh the project list so we're looking at the latest data - $scope.search(list.iterator, null, false, true); + } }; $scope.deleteProject = function (id, name) { @@ -324,22 +317,28 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, }); }; - $scope.SCMUpdate = function (project_id) { - var i; - for (i = 0; i < $scope.projects.length; i++) { - if ($scope.projects[i].id === project_id) { - if ($scope.projects[i].scm_type === "Manual" || Empty($scope.projects[i].scm_type)) { + $scope.SCMUpdate = function (project_id, event) { + try { + $(event.target).tooltip('hide'); + } + catch(e) { + // ignore + } + $scope.projects.every(function(project) { + if (project.id === project_id) { + if (project.scm_type === "Manual" || Empty(project.scm_type)) { // Do not respond. Button appears greyed out as if it is disabled. Not disabled though, because we need mouse over event // to work. So user can click, but we just won't do anything. //Alert('Missing SCM Setup', 'Before running an SCM update, edit the project and provide the SCM access information.', 'alert-info'); - break; - } else if ($scope.projects[i].status === 'updating') { + } else if (project.status === 'updating') { Alert('Update in Progress', 'The SCM update process is running. Use the Refresh button to monitor the status.', 'alert-info'); } else { - ProjectUpdate({ scope: $scope, project_id: project_id }); + ProjectUpdate({ scope: $scope, project_id: project.id }); } + return false; } - } + return true; + }); }; $scope.editSchedules = function(id) { diff --git a/awx/ui/static/js/helpers/Projects.js b/awx/ui/static/js/helpers/Projects.js index 8b3edaed9a..37ee28038f 100644 --- a/awx/ui/static/js/helpers/Projects.js +++ b/awx/ui/static/js/helpers/Projects.js @@ -27,7 +27,6 @@ angular.module('ProjectsHelper', ['RestServices', 'Utilities', 'ProjectStatusDef Wait('start'); - // Using jquery dialog for its expandable property html = "
\n"; $('#projects-modal-container').empty().append(html); @@ -74,10 +73,13 @@ angular.module('ProjectsHelper', ['RestServices', 'Utilities', 'ProjectStatusDef }); }, resizeStop: function () { - // for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100% var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]'), + titleHeight = dialog.find('.ui-dialog-titlebar').outerHeight(), + buttonHeight = dialog.find('.ui-dialog-buttonpane').outerHeight(), content = dialog.find('#status-modal-dialog'); content.width(dialog.width() - 28); + content.css({ height: (dialog.height() - titleHeight - buttonHeight - 10) }); + }, close: function () { // Destroy on close @@ -124,10 +126,8 @@ angular.module('ProjectsHelper', ['RestServices', 'Utilities', 'ProjectStatusDef }) .error(function (data, status) { - $('#form-modal').modal("hide"); - ProcessErrors(scope, data, status, form, { - hdr: 'Error!', - msg: 'Failed to retrieve status of project: ' + project_id + '. GET status: ' + status + ProcessErrors(scope, data, status, form, { hdr: 'Error!', + msg: 'Failed to retrieve project: ' + project_id + '. GET returned: ' + status }); }); }; diff --git a/awx/ui/static/js/lists/CompletedJobs.js b/awx/ui/static/js/lists/CompletedJobs.js index fd61197ebc..221096b18f 100644 --- a/awx/ui/static/js/lists/CompletedJobs.js +++ b/awx/ui/static/js/lists/CompletedJobs.js @@ -40,12 +40,6 @@ angular.module('CompletedJobsDefinition', []) filter: "date:'MM/dd/yy HH:mm:ss'", columnClass: "col-md-2 hidden-xs" }, - next_job_run: { - label: 'Next Run', - searchable: false, - filter: "date:'MM/dd/yy HH:mm:ss'", - columnClass: "col-md-2 hidden-sm hidden-xs" - }, type: { label: 'Type', ngBind: 'completed_job.type_label', diff --git a/awx/ui/static/js/lists/Organizations.js b/awx/ui/static/js/lists/Organizations.js index b34faaea30..872e4b7d91 100644 --- a/awx/ui/static/js/lists/Organizations.js +++ b/awx/ui/static/js/lists/Organizations.js @@ -17,7 +17,7 @@ angular.module('OrganizationListDefinition', []) selectTitle: 'Add Organizations', editTitle: 'Organizations', hover: true, - index: false, + index: true, fields: { name: { diff --git a/awx/ui/static/js/lists/Projects.js b/awx/ui/static/js/lists/Projects.js index 642c85fa78..8e4ad2808a 100644 --- a/awx/ui/static/js/lists/Projects.js +++ b/awx/ui/static/js/lists/Projects.js @@ -22,39 +22,35 @@ angular.module('ProjectsListDefinition', []) hover: true, fields: { + status: { + label: 'Status', + iconOnly: true, + ngClick: 'showSCMStatus(project.id)', + awToolTip: '{{ project.statusTip }}', + dataPlacement: 'top', + icon: "icon-job-{{ project.statusIcon }}", + columnClass: "col-md-1 col-sm-2 col-xs-3", + nosort: true + }, name: { key: true, - label: 'Name' + label: 'Name', + columnClass: "col-md-4 col-sm-3 col-xs-3" }, - description: { - label: 'Description', + last_updated: { + label: 'Last Updated', + filter: "date:'MM/dd/yy HH:mm:ss'", + columnClass: "col-md-2 hidden-sm hidden-xs", excludeModal: true, - columnClass: 'hidden-sm hidden-xs' + searchable: false, + nosort: true }, scm_type: { label: 'Type', searchType: 'select', searchOptions: [], // will be set by Options call to projects resource excludeModal: true, - columnClass: 'hidden-sm hidden-xs', - nosort: true - }, - status: { - label: 'Status', - ngClick: 'showSCMStatus(project.id)', - awToolTip: 'View details of last SCM Update', - dataPlacement: 'top', - badgeIcon: "{{ 'fa icon-failures-' + project.badge }}", - badgePlacement: 'left', - searchType: 'select', - searchOptions: [], // will be set by Options call to projects resource - excludeModal: true - }, - last_updated: { - label: 'Last Updated', - type: 'date', - excludeModal: true, - searchable: false + columnClass: 'col-md-2 hidden-sm hidden-xs' } }, @@ -93,7 +89,7 @@ angular.module('ProjectsListDefinition', []) fieldActions: { scm_update: { - ngClick: 'SCMUpdate(project.id)', + ngClick: 'SCMUpdate(project.id, $event)', awToolTip: "{{ project.scm_update_tooltip }}", ngClass: "project.scm_type_class", dataPlacement: 'top' diff --git a/awx/ui/static/js/lists/QueuedJobs.js b/awx/ui/static/js/lists/QueuedJobs.js index 39d4394263..7a4c5cd6db 100644 --- a/awx/ui/static/js/lists/QueuedJobs.js +++ b/awx/ui/static/js/lists/QueuedJobs.js @@ -39,12 +39,6 @@ angular.module('QueuedJobsDefinition', []) filter: "date:'MM/dd/yy HH:mm:ss'", columnClass: 'col-md-2 hidden-xs' }, - next_job_run: { - label: 'Next Run', - searchable: false, - filter: "date:'MM/dd/yy HH:mm:ss'", - columnClass: "col-md-2 hidden-sm hidden-xs" - }, type: { label: 'Type', ngBind: 'queued_job.type_label', diff --git a/awx/ui/static/js/lists/RunningJobs.js b/awx/ui/static/js/lists/RunningJobs.js index bbc8c43071..811afaefd9 100644 --- a/awx/ui/static/js/lists/RunningJobs.js +++ b/awx/ui/static/js/lists/RunningJobs.js @@ -39,12 +39,6 @@ angular.module('RunningJobsDefinition', []) filter: "date:'MM/dd/yy HH:mm:ss'", columnClass: "col-md-2 hidden-xs" }, - next_job_run: { - label: 'Next Run', - searchable: false, - filter: "date:'MM/dd/yy HH:mm:ss'", - columnClass: "col-md-2 hidden-sm hidden-xs" - }, type: { label: 'Type', ngBind: 'running_job.type_label', diff --git a/awx/ui/static/js/lists/ScheduledJobs.js b/awx/ui/static/js/lists/ScheduledJobs.js index c0663213c9..6b0d77b0f2 100644 --- a/awx/ui/static/js/lists/ScheduledJobs.js +++ b/awx/ui/static/js/lists/ScheduledJobs.js @@ -15,7 +15,7 @@ angular.module('ScheduledJobsDefinition', []) iterator: 'scheduled_job', editTitle: 'Scheduled Jobs', 'class': 'table-condensed', - index: false, + index: true, hover: true, well: false, @@ -24,27 +24,28 @@ angular.module('ScheduledJobsDefinition', []) label: 'Next Run', link: false, searchable: false, - columnClass: "col-md-2", + columnClass: "col-md-2 hidden-xs", key: true, desc: true }, - dtend: { - label: 'Ends On', - searchable: false, - filter: "date:'MM/dd/yy HH:mm:ss'", - columnClass: "col-md-2 hidden-xs" - }, - template_name: { - label: 'Name', - columnClass: "col-md-4 col-xs-5", - sourceModel: "template", - sourceField: "name" - }, type: { label: 'Type', link: false, columnClass: "col-md-2 hidden-sm hidden-xs" + }, + template_name: { + label: 'Name', + columnClass: "col-md-3 col-xs-5", + sourceModel: "template", + sourceField: "name" } + /*, + dtend: { + label: 'Ends On', + searchable: false, + filter: "date:'MM/dd/yy HH:mm:ss'", + columnClass: "col-md-2 hidden-xs" + }*/ }, actions: { diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index dcaa18a9c3..993d848478 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -979,15 +979,10 @@ input[type="checkbox"].checkbox-no-label { .job-new, - .job-canceled { - color: #778899; - } - - .icon-failures-false, .license-valid, .job-success, .job-successful { - color: @green; + color: @green; } .icon-job-pending:before, @@ -996,14 +991,13 @@ input[type="checkbox"].checkbox-no-label { .icon-job-successful:before, .icon-job-waiting:before, .icon-job-new:before, - .icon-job-canceled:before, .icon-job-changed:before { - content: "\f111"; + content: "\f111"; } .icon-job-error:before, .icon-job-failed:before { - content: "\f06a"; + content: "\f06a"; } .icon-job-pending, @@ -1012,36 +1006,32 @@ input[type="checkbox"].checkbox-no-label { .icon-job-successful, .icon-job-waiting, .icon-job-new { - color: @green; + color: @green; } - .icon-job-canceled { - color: @grey; + .icon-job-running { + .pulsate(); } - + .icon-job-changed, .job-changed { - color: @warning; + color: @warning; } .icon-job-error, .icon-job-failed { - color: @red; + color: @red; } - .icon-failures-none, - .icon-failures-na { - color: @grey; + .icon-job-none, + .icon-job-canceled { + color: @grey; + opacity: 0.45; } - .icon-failures-true:before { - content: "\f06a"; - } - - .icon-failures-none:before, - .icon-failures-na:before, - .icon-failures-false:before { - content: "\f111"; + .icon-job-canceled, + .icon-job-none:before { + content: "\f10c"; } .icon-schedule-enabled-true:before { diff --git a/awx/ui/static/lib/ansible/generator-helpers.js b/awx/ui/static/lib/ansible/generator-helpers.js index 8c8b3af128..8f9b6e6e51 100644 --- a/awx/ui/static/lib/ansible/generator-helpers.js +++ b/awx/ui/static/lib/ansible/generator-helpers.js @@ -358,7 +358,7 @@ angular.module('GeneratorHelpers', []) } html += ""; if (field.badgeToolTip) { @@ -454,6 +454,8 @@ angular.module('GeneratorHelpers', []) html = DropDown(params); } else if (field.type === 'badgeCount') { html = BadgeCount(params); + } else if (field.type === 'badgeOnly') { + html = Badge(field); } else { html += "#\n"; + html += "#\n"; } for (fld in list.fields) { if ((list.fields[fld].searchOnly === undefined || list.fields[fld].searchOnly === false) &&