diff --git a/awx/ui/client/src/job-results/job-results.controller.js b/awx/ui/client/src/job-results/job-results.controller.js index a11e7cf7be..56aed6ce5b 100644 --- a/awx/ui/client/src/job-results/job-results.controller.js +++ b/awx/ui/client/src/job-results/job-results.controller.js @@ -1,4 +1,5 @@ -export default ['jobData', 'jobDataOptions', 'jobLabels', 'jobFinished', 'count', '$scope', 'ParseTypeChange', 'ParseVariableString', 'jobResultsService', 'eventQueue', '$compile', '$log', 'Dataset', '$q', 'Rest', '$state', 'QuerySet', '$rootScope', function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTypeChange, ParseVariableString, jobResultsService, eventQueue, $compile, $log, Dataset, $q, Rest, $state, QuerySet, $rootScope) { +export default ['jobData', 'jobDataOptions', 'jobLabels', 'jobFinished', 'count', '$scope', 'ParseTypeChange', 'ParseVariableString', 'jobResultsService', 'eventQueue', '$compile', '$log', 'Dataset', '$q', 'Rest', '$state', 'QuerySet', '$rootScope', 'moment', +function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTypeChange, ParseVariableString, jobResultsService, eventQueue, $compile, $log, Dataset, $q, Rest, $state, QuerySet, $rootScope, moment) { // used for tag search $scope.job_event_dataset = Dataset.data; @@ -169,6 +170,17 @@ export default ['jobData', 'jobDataOptions', 'jobLabels', 'jobFinished', 'count' $scope.events = {}; + // For elapsed time while a job is running, compute the differnce in seconds, + // from the time the job started until now. Moment() returns the current + // time as a moment object. + var start = ($scope.job.started === null) ? moment() : moment($scope.job.started); + if(jobFinished === false){ + var elapsedInterval = setInterval(function(){ + let now = moment(); + $scope.job.elapsed = now.diff(start, 'seconds'); + }, 1000); + } + // EVENT STUFF BELOW // This is where the async updates to the UI actually happen. @@ -442,6 +454,17 @@ export default ['jobData', 'jobDataOptions', 'jobLabels', 'jobFinished', 'count' parseInt($scope.job.id,10)) { // controller is defined, so set the job_status $scope.job_status = data.status; + if (data.status === "successful" || + data.status === "failed" || + data.status === "error" || + data.status === "canceled") { + clearInterval(elapsedInterval); + // When the fob is finished retrieve the job data to + // correct anything that was out of sync from the job run + jobResultsService.getJobData($scope.job.id).then(function(data){ + $scope.job = data; + }); + } } else if (parseInt(data.project_id, 10) === parseInt($scope.job.project,10)) { // this is a project status update message, so set the diff --git a/awx/ui/client/src/job-results/job-results.route.js b/awx/ui/client/src/job-results/job-results.route.js index 161f8db587..88154d3114 100644 --- a/awx/ui/client/src/job-results/job-results.route.js +++ b/awx/ui/client/src/job-results/job-results.route.js @@ -34,26 +34,8 @@ export default { }, resolve: { // the GET for the particular job - jobData: ['Rest', 'GetBasePath', '$stateParams', '$q', '$state', 'Alert', function(Rest, GetBasePath, $stateParams, $q, $state, Alert) { - var val = $q.defer(); - - Rest.setUrl(GetBasePath('jobs') + $stateParams.id); - Rest.get() - .then(function(data) { - val.resolve(data.data); - }, function(data) { - val.reject(data); - - if (data.status === 404) { - Alert('Job Not Found', 'Cannot find job.', 'alert-info'); - } else if (data.status === 403) { - Alert('Insufficient Permissions', 'You do not have permission to view this job.', 'alert-info'); - } - - $state.go('jobs'); - }); - - return val.promise; + jobData: ['Rest', 'GetBasePath', '$stateParams', '$q', '$state', 'Alert', 'jobResultsService', function(Rest, GetBasePath, $stateParams, $q, $state, Alert, jobResultsService) { + return jobResultsService.getJobData($stateParams.id); }], Dataset: ['QuerySet', '$stateParams', 'jobData', function(qs, $stateParams, jobData) { diff --git a/awx/ui/client/src/job-results/job-results.service.js b/awx/ui/client/src/job-results/job-results.service.js index 07d442f3d7..02f4a31548 100644 --- a/awx/ui/client/src/job-results/job-results.service.js +++ b/awx/ui/client/src/job-results/job-results.service.js @@ -5,7 +5,8 @@ *************************************************/ -export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErrors', 'InitiatePlaybookRun', function ($q, Prompt, $filter, Wait, Rest, $state, ProcessErrors, InitiatePlaybookRun) { +export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErrors', 'InitiatePlaybookRun', 'GetBasePath', 'Alert', +function ($q, Prompt, $filter, Wait, Rest, $state, ProcessErrors, InitiatePlaybookRun, GetBasePath, Alert) { var val = { // the playbook_on_stats event returns the count data in a weird format. // format to what we need! @@ -191,6 +192,27 @@ export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErr relaunchJob: function(scope) { InitiatePlaybookRun({ scope: scope, id: scope.job.id, relaunch: true }); + }, + getJobData: function(id){ + var val = $q.defer(); + + Rest.setUrl(GetBasePath('jobs') + id ); + Rest.get() + .then(function(data) { + val.resolve(data.data); + }, function(data) { + val.reject(data); + + if (data.status === 404) { + Alert('Job Not Found', 'Cannot find job.', 'alert-info'); + } else if (data.status === 403) { + Alert('Insufficient Permissions', 'You do not have permission to view this job.', 'alert-info'); + } + + $state.go('jobs'); + }); + + return val.promise; } }; return val; diff --git a/awx/ui/client/src/job-results/main.js b/awx/ui/client/src/job-results/main.js index 3747da4158..f0aedc7c43 100644 --- a/awx/ui/client/src/job-results/main.js +++ b/awx/ui/client/src/job-results/main.js @@ -17,7 +17,7 @@ import eventQueueService from './event-queue.service'; import parseStdoutService from './parse-stdout.service'; export default - angular.module('jobResults', [hostStatusBar.name, jobResultsStdOut.name, hostEvent.name]) + angular.module('jobResults', [hostStatusBar.name, jobResultsStdOut.name, hostEvent.name, 'angularMoment']) .run(['$stateExtender', function($stateExtender) { $stateExtender.addState(route); }])