use status service in details and stats components

This commit is contained in:
Jake McDermott 2018-04-02 22:48:42 -04:00
parent bdd36341ae
commit 1f9b325f38
No known key found for this signature in database
GPG Key ID: 3B02CAD476EECB35
7 changed files with 90 additions and 188 deletions

View File

@ -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;

View File

@ -105,7 +105,7 @@ function JobEventEngine ($q) {
}
};
this.pushEvent = data => {
this.pushJobEvent = data => {
this.lag++;
this.chain = this.chain

View File

@ -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;

View File

@ -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;

View File

@ -1,28 +1,14 @@
<div class="container-fluid">
<div class="col-md-4">
<at-panel>
<at-details
resource="vm.details.resource"
started="vm.details.started"
finished="vm.details.finished"
status="vm.details.status">
</at-details>
<!-- <p><button class="btn" ng-click="vm.clear(true)">Page Mode</button></p> -->
<at-job-details resource="vm.resource"></at-job-details>
</at-panel>
</div>
<div class="col-md-8">
<at-panel class="at-Stdout">
<div class="at-Panel-headingTitle">{{ vm.title }}</div>
<at-stats
download="vm.stats.download"
elapsed="vm.stats.elapsed"
running="vm.stats.running"
event="vm.stats.event"
title="vm.stats.title"
plays="vm.stats.plays"
tasks="vm.stats.tasks">
</at-stats>
<at-job-stats resource="vm.resource"></at-job-stats>
<!-- search ===================================================================================== -->
<form ng-submit="vm.search.submitSearch()">
<div class="input-group">

View File

@ -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 = `<span class='HostStatusBar-tooltipLabel'>${key}</span>`;
@ -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;

View File

@ -40,26 +40,31 @@
<div class="HostStatusBar">
<div class="HostStatusBar-ok"
ng-show="!vm.running"
data-placement="top"
aw-tool-tip="{{ vm.tooltips.ok }}"
data-tip-watch="vm.tooltips.ok">
</div>
<div class="HostStatusBar-skipped"
ng-show="!vm.running"
data-placement="top"
aw-tool-tip="{{ vm.tooltips.skipped }}"
data-tip-watch="vm.tooltips.skipped">
</div>
<div class="HostStatusBar-changed"
ng-show="!vm.running"
data-placement="top"
aw-tool-tip="{{ vm.tooltips.changed }}"
data-tip-watch="vm.tooltips.changed">
</div>
<div class="HostStatusBar-failures"
ng-show="!vm.running"
data-placement="top"
aw-tool-tip="{{ vm.tooltips.failures }}"
data-tip-watch="vm.tooltips.failures">
</div>
<div class="HostStatusBar-dark"
ng-show="!vm.running"
data-placement="top"
aw-tool-tip="{{ vm.tooltips.dark }}"
data-tip-watch="vm.tooltips.dark">