From 1f9b325f380a618cc946b090ddef6cd37fb3d822 Mon Sep 17 00:00:00 2001 From: Jake McDermott Date: Mon, 2 Apr 2018 22:48:42 -0400 Subject: [PATCH] use status service in details and stats components --- .../features/output/details.directive.js | 61 +++++------- .../client/features/output/engine.service.js | 2 +- .../features/output/index.controller.js | 98 +++++-------------- awx/ui/client/features/output/index.js | 6 +- awx/ui/client/features/output/index.view.html | 18 +--- .../client/features/output/stats.directive.js | 88 ++++++----------- .../client/features/output/stats.partial.html | 5 + 7 files changed, 90 insertions(+), 188 deletions(-) diff --git a/awx/ui/client/features/output/details.directive.js b/awx/ui/client/features/output/details.directive.js index b34a80982f..3c0e677d9b 100644 --- a/awx/ui/client/features/output/details.directive.js +++ b/awx/ui/client/features/output/details.directive.js @@ -10,6 +10,7 @@ let parse; let prompt; let resource; let strings; +let status; let wait; let vm; @@ -19,8 +20,8 @@ function mapChoices (choices) { return Object.assign(...choices.map(([k, v]) => ({ [k]: v }))); } -function getStatusDetails (status) { - const unmapped = status || resource.model.get('status'); +function getStatusDetails (jobStatus) { + const unmapped = jobStatus || resource.model.get('status'); if (!unmapped) { return null; @@ -373,11 +374,11 @@ function getLabelDetails () { } function createErrorHandler (path, action) { - return ({ data, status }) => { + return res => { const hdr = strings.get('error.HEADER'); - const msg = strings.get('error.CALL', { path, action, status }); + const msg = strings.get('error.CALL', { path, action, status: res.status }); - error($scope, data, status, null, { hdr, msg }); + error($scope, res.data, res.status, null, { hdr, msg }); }; } @@ -454,24 +455,14 @@ function deleteJob () { prompt({ hdr, resourceName, body, actionText, action }); } -function handleSocketEvent (data) { - const project = resource.model.get('project'); - - if (resource.model.get('id') === data.unified_job_id) { - vm.status = getStatusDetails(data.status); - } else if (project && (project === data.project_id)) { - vm.project.update = vm.project.update || {}; - vm.project.update.status = data.status; - } -} - -function AtDetailsController ( +function AtJobDetailsController ( _$http_, _$filter_, _$state_, _error_, _prompt_, _strings_, + _status_, _wait_, ParseTypeChange, ParseVariableString, @@ -486,6 +477,7 @@ function AtDetailsController ( parse = ParseVariableString; prompt = _prompt_; strings = _strings_; + status = _status_; wait = _wait_; vm.init = _$scope_ => { @@ -538,47 +530,48 @@ function AtDetailsController ( vm.deleteJob = deleteJob; vm.toggleLabels = toggleLabels; - $scope.$watch('started', value => { vm.started = getStartDetails(value); }); - $scope.$watch('status', value => { vm.status = getStatusDetails(value); }); - $scope.$watch('finished', value => { vm.finished = getFinishDetails(value); }); + $scope.$watch(status.getStarted, value => { vm.started = getStartDetails(value); }); + $scope.$watch(status.getJobStatus, value => { vm.status = getStatusDetails(value); }); + $scope.$watch(status.getFinished, value => { vm.finished = getFinishDetails(value); }); - $scope.$on(resource.ws.status, (e, data) => handleSocketEvent(data)); + $scope.$watch(status.getProjectStatus, value => { + if (!value) return; + + vm.project.update = vm.project.update || {}; + vm.project.update.status = value; + }); }; } -AtDetailsController.$inject = [ +AtJobDetailsController.$inject = [ '$http', '$filter', '$state', 'ProcessErrors', 'Prompt', 'JobStrings', + 'JobStatusService', 'Wait', 'ParseTypeChange', 'ParseVariableString', ]; -function atDetailsLink (scope, el, attrs, controllers) { +function atJobDetailsLink (scope, el, attrs, controllers) { const [atDetailsController] = controllers; atDetailsController.init(scope); } -function atDetails () { +function atJobDetails () { return { templateUrl, restrict: 'E', - require: ['atDetails'], + require: ['atJobDetails'], controllerAs: 'vm', - link: atDetailsLink, - controller: AtDetailsController, - scope: { - finished: '=', - started: '=', - resource: '=', - status: '=', - }, + link: atJobDetailsLink, + controller: AtJobDetailsController, + scope: { resource: '=', }, }; } -export default atDetails; +export default atJobDetails; diff --git a/awx/ui/client/features/output/engine.service.js b/awx/ui/client/features/output/engine.service.js index c8b0fd662a..1f74a90c59 100644 --- a/awx/ui/client/features/output/engine.service.js +++ b/awx/ui/client/features/output/engine.service.js @@ -105,7 +105,7 @@ function JobEventEngine ($q) { } }; - this.pushEvent = data => { + this.pushJobEvent = data => { this.lag++; this.chain = this.chain diff --git a/awx/ui/client/features/output/index.controller.js b/awx/ui/client/features/output/index.controller.js index 51cfdeaea7..0c3a149679 100644 --- a/awx/ui/client/features/output/index.controller.js +++ b/awx/ui/client/features/output/index.controller.js @@ -1,25 +1,17 @@ -const JOB_START = 'playbook_on_start'; -const JOB_END = 'playbook_on_stats'; -const PLAY_START = 'playbook_on_play_start'; -const TASK_START = 'playbook_on_task_start'; - let $compile; let $q; let $scope; let $state; -let moment; let page; let qs; let render; let resource; let scroll; let engine; +let status; let vm; -let eventCounter; -let statsEvent; - function JobsIndexController ( _resource_, _page_, @@ -31,7 +23,7 @@ function JobsIndexController ( _$q_, _$state_, _qs_, - _moment_, + _status_, ) { vm = this || {}; @@ -44,8 +36,7 @@ function JobsIndexController ( scroll = _scroll_; render = _render_; engine = _engine_; - - moment = _moment_; + status = _status_; // Development helper(s) vm.clear = devClear; @@ -55,31 +46,10 @@ function JobsIndexController ( vm.expand = expand; vm.isExpanded = true; - // Events - eventCounter = null; - statsEvent = resource.stats; - // Panel + vm.resource = resource; vm.title = resource.model.get('name'); - // Stats - vm.stats = { - event: statsEvent, - elapsed: resource.model.get('elapsed'), - download: resource.model.get('related.stdout'), - running: Boolean(resource.model.get('started')) && !resource.model.get('finished'), - plays: null, - tasks: null, - }; - - // Details - vm.details = { - resource, - status: resource.model.get('status'), - started: resource.model.get('started'), - finished: resource.model.get('finished'), - }; - // Search $state = _$state_; qs = _qs_; @@ -107,10 +77,14 @@ function JobsIndexController ( up: scrollPageUp }; - render.requestAnimationFrame(() => init(!vm.stats.running)); + render.requestAnimationFrame(() => init()); } -function init (pageMode) { +function init () { + status.init({ + resource, + }); + page.init({ resource, }); @@ -118,7 +92,7 @@ function init (pageMode) { render.init({ get: () => resource.model.get(`related.${resource.related}.results`), compile: html => $compile(html)($scope), - isStreamActive: engine.isActive + isStreamActive: engine.isActive, }); scroll.init({ @@ -135,60 +109,34 @@ function init (pageMode) { return shift().then(() => append(events, true)); }, onStart () { - vm.stats.plays = 0; - vm.stats.tasks = 0; - vm.stats.running = true; + status.resetCounts(); + status.setJobStatus('running'); vm.search.disabled = true; - vm.details.status = 'running'; }, onStop () { - vm.stats.event = statsEvent; - vm.stats.running = false; + status.updateStats(); vm.search.disabled = false; - - vm.details.status = statsEvent.failed ? 'failed' : 'successful'; - vm.details.finished = statsEvent.created; } }); $scope.$on(resource.ws.events, handleSocketEvent); + $scope.$on(resource.ws.status, handleStatusEvent); - if (pageMode) { + if (!status.isRunning()) { next(); } } +function handleStatusEvent (scope, data) { + status.pushStatusEvent(data); +} + function handleSocketEvent (scope, data) { - const isLatest = ((!eventCounter) || (data.counter > eventCounter)); + engine.pushJobEvent(data); - if (isLatest) { - eventCounter = data.counter; - - vm.details.status = _.get(data, 'summary_fields.job.status'); - - vm.stats.elapsed = moment(data.created) - .diff(resource.model.get('created'), 'seconds'); - } - - if (data.event === JOB_START) { - vm.details.started = data.created; - } - - if (data.event === PLAY_START) { - vm.stats.plays++; - } - - if (data.event === TASK_START) { - vm.stats.tasks++; - } - - if (data.event === JOB_END) { - statsEvent = data; - } - - engine.pushEvent(data); + status.pushJobEvent(data); } function devClear (pageMode) { @@ -466,7 +414,7 @@ JobsIndexController.$inject = [ '$q', '$state', 'QuerySet', - 'moment', + 'JobStatusService', ]; module.exports = JobsIndexController; diff --git a/awx/ui/client/features/output/index.js b/awx/ui/client/features/output/index.js index 33c67d6f11..d9cc3a140d 100644 --- a/awx/ui/client/features/output/index.js +++ b/awx/ui/client/features/output/index.js @@ -7,6 +7,7 @@ import PageService from '~features/output/page.service'; import RenderService from '~features/output/render.service'; import ScrollService from '~features/output/scroll.service'; import EngineService from '~features/output/engine.service'; +import StatusService from '~features/output/status.service'; import DetailsDirective from '~features/output/details.directive'; import SearchKeyDirective from '~features/output/search-key.directive'; @@ -217,9 +218,10 @@ angular .service('JobScrollService', ScrollService) .service('JobRenderService', RenderService) .service('JobEventEngine', EngineService) - .directive('atDetails', DetailsDirective) + .service('JobStatusService', StatusService) + .directive('atJobDetails', DetailsDirective) .directive('atSearchKey', SearchKeyDirective) - .directive('atStats', StatsDirective) + .directive('atJobStats', StatsDirective) .run(JobsRun); export default MODULE_NAME; diff --git a/awx/ui/client/features/output/index.view.html b/awx/ui/client/features/output/index.view.html index 1cac800a7d..089fcd1ce5 100644 --- a/awx/ui/client/features/output/index.view.html +++ b/awx/ui/client/features/output/index.view.html @@ -1,28 +1,14 @@
- - - +
{{ vm.title }}
- - +
diff --git a/awx/ui/client/features/output/stats.directive.js b/awx/ui/client/features/output/stats.directive.js index 06b100a646..51fbd89afb 100644 --- a/awx/ui/client/features/output/stats.directive.js +++ b/awx/ui/client/features/output/stats.directive.js @@ -1,30 +1,7 @@ const templateUrl = require('~features/output/stats.partial.html'); -const HOST_STATUS_KEYS = ['dark', 'failures', 'changed', 'ok', 'skipped']; - -function getHostStatusCounts (statsEvent) { - const countedHostNames = []; - - const counts = Object.assign(...HOST_STATUS_KEYS.map(key => ({ [key]: 0 }))); - - HOST_STATUS_KEYS.forEach(key => { - const hostData = _.get(statsEvent, ['event_data', key], {}); - - Object.keys(hostData).forEach(hostName => { - const isAlreadyCounted = (countedHostNames.indexOf(hostName) > -1); - const shouldBeCounted = ((!isAlreadyCounted) && hostData[hostName] > 0); - - if (shouldBeCounted) { - countedHostNames.push(hostName); - counts[key]++; - } - }); - }); - - counts.hosts = countedHostNames.length; - - return counts; -} +let status; +let strings; function createStatsBarTooltip (key, count) { const label = `${key}`; @@ -33,13 +10,16 @@ function createStatsBarTooltip (key, count) { return `${label}${badge}`; } -function atStatsLink (scope, el, attrs, controllers) { - const [atStatsController] = controllers; +function atJobStatsLink (scope, el, attrs, controllers) { + const [atJobStatsController] = controllers; - atStatsController.init(scope); + atJobStatsController.init(scope); } -function AtStatsController (strings) { +function AtJobStatsController (_strings_, _status_) { + status = _status_; + strings = _strings_; + const vm = this || {}; vm.tooltips = { @@ -48,28 +28,23 @@ function AtStatsController (strings) { }; vm.init = scope => { - const { download, elapsed, running, event, plays, tasks } = scope; + const { resource } = scope; - vm.download = download; - vm.plays = plays; - vm.tasks = tasks; - vm.elapsed = elapsed; - vm.running = running || false; + vm.download = resource.model.get('related.stdout'); - vm.setStats(event); + vm.setHostStatusCounts(status.getHostStatusCounts()); - scope.$watch('elapsed', value => { vm.elapsed = value; }); - scope.$watch('running', value => { vm.running = value; }); - scope.$watch('plays', value => { vm.plays = value; }); - scope.$watch('tasks', value => { vm.tasks = value; }); + scope.$watch(status.getPlayCount, value => { vm.plays = value; }); + scope.$watch(status.getTaskCount, value => { vm.tasks = value; }); + scope.$watch(status.getElapsed, value => { vm.elapsed = value; }); + scope.$watch(status.getHostCount, value => { vm.hosts = value; }); + scope.$watch(status.isRunning, value => { vm.running = value; }); - scope.$watch('event', vm.setStats); + scope.$watchCollection(status.getHostStatusCounts, vm.setHostStatusCounts); }; - vm.setStats = statsEvent => { - const counts = getHostStatusCounts(statsEvent); - - HOST_STATUS_KEYS.forEach(key => { + vm.setHostStatusCounts = counts => { + Object.keys(counts).forEach(key => { const count = counts[key]; const statusBarElement = $(`.HostStatusBar-${key}`); @@ -78,31 +53,24 @@ function AtStatsController (strings) { vm.tooltips[key] = createStatsBarTooltip(key, count); }); - vm.hosts = counts.hosts; - vm.statsAreAvailable = Boolean(statsEvent); + vm.statsAreAvailable = Boolean(status.getStatsEvent()); }; } -function atStats () { +function atJobStats () { return { templateUrl, restrict: 'E', - require: ['atStats'], + require: ['atJobStats'], controllerAs: 'vm', - link: atStatsLink, + link: atJobStatsLink, controller: [ 'JobStrings', - AtStatsController + 'JobStatusService', + AtJobStatsController ], - scope: { - download: '=', - elapsed: '=', - running: '=', - event: '=', - plays: '=', - tasks: '=', - }, + scope: { resource: '=', }, }; } -export default atStats; +export default atJobStats; diff --git a/awx/ui/client/features/output/stats.partial.html b/awx/ui/client/features/output/stats.partial.html index 80e05ece29..73e6afc224 100644 --- a/awx/ui/client/features/output/stats.partial.html +++ b/awx/ui/client/features/output/stats.partial.html @@ -40,26 +40,31 @@