diff --git a/awx/ui/client/legacy-styles/ansible-ui.less b/awx/ui/client/legacy-styles/ansible-ui.less
index 4cc306cb36..763abab7f2 100644
--- a/awx/ui/client/legacy-styles/ansible-ui.less
+++ b/awx/ui/client/legacy-styles/ansible-ui.less
@@ -1671,7 +1671,7 @@ tr td button i {
.modal-body {
min-height: 120px;
padding: 20px 0;
-
+
.alert {
padding: 10px;
margin: 0;
@@ -1984,10 +1984,6 @@ tr td button i {
width: 73px;
}
-.JobDetails-status {
- margin-bottom: 12px;
-}
-
.red-text {
color: @red;
}
diff --git a/awx/ui/client/src/app.js b/awx/ui/client/src/app.js
index 7289c1af85..f17df84b89 100644
--- a/awx/ui/client/src/app.js
+++ b/awx/ui/client/src/app.js
@@ -46,7 +46,6 @@ import inventories from './inventories/main';
import inventoryScripts from './inventory-scripts/main';
import organizations from './organizations/main';
import managementJobs from './management-jobs/main';
-import jobDetail from './job-detail/main';
import workflowResults from './workflow-results/main';
import jobResults from './job-results/main';
import jobSubmission from './job-submission/main';
@@ -119,7 +118,6 @@ var tower = angular.module('Tower', [
login.name,
activityStream.name,
footer.name,
- jobDetail.name,
workflowResults.name,
jobResults.name,
jobSubmission.name,
@@ -191,7 +189,6 @@ var tower = angular.module('Tower', [
'LogViewerStatusDefinition',
'StandardOutHelper',
'LogViewerOptionsDefinition',
- 'JobDetailHelper',
'lrInfiniteScroll',
'LoadConfigHelper',
'PortalJobsListDefinition',
@@ -350,19 +347,19 @@ var tower = angular.module('Tower', [
$rootScope.$on("$stateChangeStart", function (event, next) {
// Remove any lingering intervals
- // except on jobDetails.* states
- var jobDetailStates = [
- 'jobDetail',
- 'jobDetail.host-summary',
- 'jobDetail.host-event.details',
- 'jobDetail.host-event.json',
- 'jobDetail.host-events',
- 'jobDetail.host-event.stdout'
+ // except on jobResults.* states
+ var jobResultStates = [
+ 'jobResult',
+ 'jobResult.host-summary',
+ 'jobResult.host-event.details',
+ 'jobResult.host-event.json',
+ 'jobResult.host-events',
+ 'jobResult.host-event.stdout'
];
- if ($rootScope.jobDetailInterval && !_.includes(jobDetailStates, next.name) ) {
- window.clearInterval($rootScope.jobDetailInterval);
+ if ($rootScope.jobResultInterval && !_.includes(jobResultStates, next.name) ) {
+ window.clearInterval($rootScope.jobResultInterval);
}
- if ($rootScope.jobStdOutInterval && !_.includes(jobDetailStates, next.name) ) {
+ if ($rootScope.jobStdOutInterval && !_.includes(jobResultStates, next.name) ) {
window.clearInterval($rootScope.jobStdOutInterval);
}
diff --git a/awx/ui/client/src/helpers.js b/awx/ui/client/src/helpers.js
index b22938443d..765b81be5f 100644
--- a/awx/ui/client/src/helpers.js
+++ b/awx/ui/client/src/helpers.js
@@ -12,7 +12,6 @@ import Credentials from "./helpers/Credentials";
import Events from "./helpers/Events";
import Groups from "./helpers/Groups";
import Hosts from "./helpers/Hosts";
-import JobDetail from "./helpers/JobDetail";
import JobSubmission from "./helpers/JobSubmission";
import JobTemplates from "./helpers/JobTemplates";
import Jobs from "./helpers/Jobs";
@@ -38,7 +37,6 @@ export
Events,
Groups,
Hosts,
- JobDetail,
JobSubmission,
JobTemplates,
Jobs,
diff --git a/awx/ui/client/src/helpers/JobDetail.js b/awx/ui/client/src/helpers/JobDetail.js
deleted file mode 100644
index ad049ed481..0000000000
--- a/awx/ui/client/src/helpers/JobDetail.js
+++ /dev/null
@@ -1,1198 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- /**
- * @ngdoc function
- * @name helpers.function:JobDetail
- * @description helper moduler for jobdetails controller
- # Playbook events will be structured to form the following hierarchy:
- # - playbook_on_start (once for each playbook file)
- # - playbook_on_vars_prompt (for each play, but before play starts, we
- # currently don't handle responding to these prompts)
- # - playbook_on_play_start (once for each play)
- # - playbook_on_import_for_host
- # - playbook_on_not_import_for_host
- # - playbook_on_no_hosts_matched
- # - playbook_on_no_hosts_remaining
- # - playbook_on_setup
- # - runner_on*
- # - playbook_on_task_start (once for each task within a play)
- # - runner_on_failed
- # - runner_on_ok
- # - runner_on_error
- # - runner_on_skipped
- # - runner_on_unreachable
- # - runner_on_no_hosts
- # - runner_on_async_poll
- # - runner_on_async_ok
- # - runner_on_async_failed
- # - runner_on_file_diff
- # - playbook_on_notify (once for each notification from the play)
- # - playbook_on_stats
-
-*/
-
-
-export default
- angular.module('JobDetailHelper', ['Utilities', 'RestServices', 'ModalDialog'])
-
- .factory('DigestEvent', ['$rootScope', '$log', 'UpdatePlayStatus', 'UpdateHostStatus', 'AddHostResult',
- 'GetElapsed', 'UpdateTaskStatus', 'JobIsFinished', 'AddNewTask', 'AddNewPlay',
- function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, GetElapsed,
- UpdateTaskStatus, JobIsFinished, AddNewTask, AddNewPlay) {
- return function(params) {
-
- var scope = params.scope,
- event = params.event,
- msg;
-
- $log.debug('processing event: ' + event.id);
- $log.debug(event);
-
- function getMsg(event) {
- var msg = '';
- if (event.event_data && event.event_data.res) {
- if (typeof event.event_data.res === 'object') {
- msg = event.event_data.res.msg;
- } else {
- msg = event.event_data.res;
- }
- }
- return msg;
- }
-
- switch (event.event) {
- case 'playbook_on_start':
- if (!JobIsFinished(scope)) {
- scope.job_status.started = event.created;
- scope.job_status.status = 'running';
- }
- break;
-
- case 'playbook_on_play_start':
- AddNewPlay({ scope: scope, event: event });
- break;
-
- case 'playbook_on_setup':
- AddNewTask({ scope: scope, event: event });
- break;
-
- case 'playbook_on_task_start':
- AddNewTask({ scope: scope, event: event });
- break;
-
- case 'runner_on_ok':
- case 'runner_on_async_ok':
- msg = getMsg(event);
- UpdateHostStatus({
- scope: scope,
- name: event.host_name,
- host_id: event.host,
- task_id: event.parent,
- status: ( (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful' ),
- id: event.id,
- created: event.created,
- modified: event.modified,
- message: msg,
- counter: event.counter,
- item: (event.event_data && event.event_data.res) ? event.event_data.res.item : ''
- });
- break;
-
- case 'playbook_on_no_hosts_matched':
- UpdatePlayStatus({
- scope: scope,
- play_id: event.parent,
- failed: false,
- changed: false,
- modified: event.modified,
- no_hosts: true
- });
- break;
-
- case 'runner_on_unreachable':
- msg = getMsg(event);
- UpdateHostStatus({
- scope: scope,
- name: event.host_name,
- host_id: event.host,
- task_id: event.parent,
- status: 'unreachable',
- id: event.id,
- created: event.created,
- modified: event.modified,
- message: msg,
- counter: event.counter,
- item: (event.event_data && event.event_data.res) ? event.event_data.res.item : ''
- });
- break;
-
- case 'runner_on_error':
- case 'runner_on_async_failed':
- msg = getMsg(event);
- UpdateHostStatus({
- scope: scope,
- name: event.host_name,
- host_id: event.host,
- task_id: event.parent,
- status: 'failed',
- id: event.id,
- created: event.created,
- modified: event.modified,
- message: msg,
- counter: event.counter,
- item: (event.event_data && event.event_data.res) ? event.event_data.res.item : ''
- });
- break;
-
- case 'runner_on_no_hosts':
- UpdateTaskStatus({
- scope: scope,
- failed: event.failed,
- changed: event.changed,
- task_id: event.parent,
- modified: event.modified,
- no_hosts: true
- });
- break;
-
- case 'runner_on_skipped':
- msg = getMsg(event);
- UpdateHostStatus({
- scope: scope,
- name: event.host_name,
- host_id: event.host,
- task_id: event.parent,
- status: 'skipped',
- id: event.id,
- created: event.created,
- modified: event.modified,
- message: msg,
- counter: event.counter,
- item: (event.event_data && event.event_data.res) ? event.event_data.res.item : ''
- });
- }
- };
- }])
-
- .factory('JobIsFinished', [ function() {
- return function(scope) {
- return (scope.job_status.status === 'failed' || scope.job_status.status === 'canceled' ||
- scope.job_status.status === 'error' || scope.job_status.status === 'successful');
- };
- }])
-
- .factory('GetElapsed', [function() {
- return function(params) {
- var start = params.start,
- end = params.end,
- dt1, dt2, sec, hours, min;
- dt1 = new Date(start);
- dt2 = new Date(end);
- if ( dt2.getTime() !== dt1.getTime() ) {
- sec = Math.floor( (dt2.getTime() - dt1.getTime()) / 1000 );
- hours = Math.floor(sec / 3600);
- sec = sec - (hours * 3600);
- if (('' + hours).length < 2) {
- hours = ('00' + hours).substr(-2, 2);
- }
- min = Math.floor(sec / 60);
- sec = sec - (min * 60);
- min = ('00' + min).substr(-2,2);
- sec = ('00' + sec).substr(-2,2);
- return hours + ':' + min + ':' + sec;
- }
- else {
- return '00:00:00';
- }
- };
- }])
-
- .factory('SetActivePlay', [ function() {
- return function(params) {
- //find the most recent task in the list of 'active' tasks
-
- var scope = params.scope,
- activeList = [],
- newActivePlay,
- key;
-
- for (key in scope.jobData.plays) {
- if (scope.jobData.plays[key].taskCount > 0) {
- activeList.push(key);
- }
- }
-
- if (activeList.length > 0) {
- newActivePlay = scope.jobData.plays[activeList[activeList.length - 1]].id;
- if (newActivePlay && scope.activePlay && newActivePlay !== scope.activePlay) {
- scope.jobData.plays[scope.activePlay].tasks = {};
- scope.jobData.plays[scope.activePlay].playActiveClass = '';
- scope.activeTask = null;
- }
- if (newActivePlay) {
- scope.activePlay = newActivePlay;
- scope.jobData.plays[scope.activePlay].playActiveClass = 'JobDetail-tableRow--selected';
- }
- }
- };
- }])
-
- .factory('SetActiveTask', [ function() {
- return function(params) {
- //find the most recent task in the list of 'active' tasks
- var scope = params.scope,
- key,
- newActiveTask,
- activeList = [];
-
- for (key in scope.jobData.plays[scope.activePlay].tasks) {
- if (scope.jobData.plays[scope.activePlay].tasks[key].reportedHosts > 0 || scope.jobData.plays[scope.activePlay].tasks[key].status === 'no-matching-hosts') {
- activeList.push(key);
- }
- }
-
- if (activeList.length > 0) {
- newActiveTask = scope.jobData.plays[scope.activePlay].tasks[activeList[activeList.length - 1]].id;
- if (newActiveTask && scope.activeTask && newActiveTask !== scope.activeTask) {
- if (scope.activeTask && scope.jobData.plays[scope.activePlay].tasks[scope.activeTask] !== undefined) {
- scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].taskActiveClass = '';
- scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].hostResults = {};
- }
- }
- if (newActiveTask) {
- scope.activeTask = newActiveTask;
- scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].taskActiveClass = 'JobDetail-tableRow--selected';
- }
- }
- };
- }])
-
- .factory('AddNewPlay', ['SetActivePlay', function(SetActivePlay) {
- return function(params) {
- var scope = params.scope,
- event = params.event,
- status, status_text;
-
- status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful';
- status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK';
-
- scope.jobData.plays[event.id] = {
- id: event.id,
- name: event.play,
- created: event.created,
- status: status,
- status_text: status_text,
- elapsed: '00:00:00',
- hostCount: 0,
- taskCount: 0,
- fistTask: null,
- unreachableCount: 0,
- status_tip: "Event ID: " + event.id + "
Status: " + status_text,
- tasks: {}
- };
-
- SetActivePlay({ scope: scope });
- };
- }])
-
- .factory('AddNewTask', ['UpdatePlayStatus', 'SetActivePlay', 'SetActiveTask', function(UpdatePlayStatus, SetActivePlay, SetActiveTask) {
- return function(params) {
- var scope = params.scope,
- event = params.event,
- status, status_text;
-
- status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful';
- status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK';
-
- scope.jobData.plays[event.parent].tasks[event.id] = {
- id: event.id,
- play_id: event.parent,
- name: (event.task) ? event.task : event.event_display,
- status: status,
- status_text: status_text,
- status_tip: "Event ID: " + event.id + "
Status: " + status_text,
- created: event.created,
- modified: event.modified,
- hostCount: (scope.jobData.plays[event.parent]) ? scope.jobData.plays[event.parent].hostCount : 0,
- reportedHosts: 0,
- successfulCount: 0,
- failedCount: 0,
- changedCount: 0,
- skippedCount: 0,
- unreachableCount: 0,
- successfulStyle: { display: 'none'},
- failedStyle: { display: 'none' },
- changedStyle: { display: 'none' },
- skippedStyle: { display: 'none' },
- unreachableStyle: { display: 'none' },
- hostResults: {}
- };
-
- if (scope.jobData.plays[event.parent].firstTask === undefined || scope.jobData.plays[event.parent].firstTask === null) {
- scope.jobData.plays[event.parent].firstTask = event.id;
- }
- scope.jobData.plays[event.parent].taskCount++;
-
- SetActivePlay({ scope: scope });
-
- SetActiveTask({ scope: scope });
-
- UpdatePlayStatus({
- scope: scope,
- play_id: event.parent,
- failed: event.failed,
- changed: event.changed,
- modified: event.modified
- });
- };
- }])
-
- .factory('UpdateJobStatus', ['GetElapsed', 'Empty', 'JobIsFinished', 'longDateFilter', function(GetElapsed, Empty, JobIsFinished, longDateFilter) {
- return function(params) {
- var scope = params.scope,
- failed = params.failed,
- modified = params.modified,
- started = params.started,
- finished = params.finished;
-
- if (failed && scope.job_status.status !== 'failed' && scope.job_status.status !== 'error' &&
- scope.job_status.status !== 'canceled') {
- scope.job_status.status = 'failed';
- }
- if (JobIsFinished(scope) && !Empty(modified)) {
- scope.job_status.finished = longDateFilter(modified);
- }
- if (!Empty(started) && Empty(scope.job_status.started)) {
- scope.job_status.started = longDateFilter(modified);
- }
- if (!Empty(scope.job_status.finished) && !Empty(scope.job_status.started)) {
- scope.job_status.elapsed = GetElapsed({
- start: started,
- end: finished
- });
- }
- };
- }])
-
- // Update the status of a play
- .factory('UpdatePlayStatus', ['GetElapsed', 'UpdateJobStatus', function(GetElapsed, UpdateJobStatus) {
- return function(params) {
- var scope = params.scope,
- failed = params.failed,
- changed = params.changed,
- id = params.play_id,
- modified = params.modified,
- no_hosts = params.no_hosts,
- play;
-
- if (scope.jobData.plays[id] !== undefined) {
- play = scope.jobData.plays[id];
- if (failed) {
- play.status = 'failed';
- play.status_text = 'Failed';
- }
- else if (play.status !== 'changed' && play.status !== 'failed') {
- // once the status becomes 'changed' or 'failed' don't modify it
- if (no_hosts) {
- play.status = 'no-matching-hosts';
- play.status_text = 'No matching hosts';
- } else {
- play.status = (changed) ? 'changed' : (failed) ? 'failed' : 'successful';
- play.status_text = (changed) ? 'Changed' : (failed) ? 'Failed' : 'OK';
- }
- }
- play.taskCount = (play.taskCount > 0) ? play.taskCount : 1; // set to a minimum of 1 to force drawing
- play.status_tip = "Event ID: " + play.id + "
Status: " + play.status_text;
- play.finished = modified;
- play.elapsed = GetElapsed({
- start: play.created,
- end: modified
- });
- //play.status_text = (status_text) ? status_text : play.status;
- }
-
- UpdateJobStatus({
- scope: scope,
- failed: null,
- modified: modified
- });
- };
- }])
-
- .factory('UpdateTaskStatus', ['UpdatePlayStatus', 'GetElapsed', function(UpdatePlayStatus, GetElapsed) {
- return function(params) {
- var scope = params.scope,
- failed = params.failed,
- changed = params.changed,
- id = params.task_id,
- modified = params.modified,
- no_hosts = params.no_hosts,
- play, task;
-
- // find the task in our hierarchy
- for (play in scope.jobData.plays) {
- if (scope.jobData.plays[play].tasks[id]) {
- task = scope.jobData.plays[play].tasks[id];
- }
- }
-
- if (task) {
- if (no_hosts){
- task.status = 'no-matching-hosts';
- task.status_text = 'No matching hosts';
- }
- else if (failed) {
- task.status = 'failed';
- task.status_text = 'Failed';
- }
- else if (task.status !== 'changed' && task.status !== 'failed') {
- // once the status becomes 'changed' or 'failed' don't modify it
- task.status = (failed) ? 'failed' : (changed) ? 'changed' : 'successful';
- task.status_text = (failed) ? 'Failed' : (changed) ? 'Changed' : 'OK';
- }
- task.status_tip = "Event ID: " + task.id + "
Status: " + task.status_text;
- task.finished = params.modified;
- task.elapsed = GetElapsed({
- start: task.created,
- end: modified
- });
-
- UpdatePlayStatus({
- scope: scope,
- failed: failed,
- changed: changed,
- play_id: task.play_id,
- modified: modified,
- no_hosts: no_hosts
- });
- }
- };
- }])
-
- // Each time a runner event is received update host summary totals and the parent task
- .factory('UpdateHostStatus', ['UpdateTaskStatus', 'AddHostResult', function(UpdateTaskStatus, AddHostResult) {
- return function(params) {
- var scope = params.scope,
- status = params.status, // successful, changed, unreachable, failed, skipped
- name = params.name,
- event_id = params.id,
- host_id = params.host_id,
- task_id = params.task_id,
- modified = params.modified,
- created = params.created,
- msg = params.message,
- item = params.item,
- counter = params.counter;
-
- if (scope.jobData.hostSummaries[host_id] !== undefined) {
- scope.jobData.hostSummaries[host_id].ok += (status === 'successful') ? 1 : 0;
- scope.jobData.hostSummaries[host_id].changed += (status === 'changed') ? 1 : 0;
- scope.jobData.hostSummaries[host_id].unreachable += (status === 'unreachable') ? 1 : 0;
- scope.jobData.hostSummaries[host_id].failed += (status === 'failed') ? 1 : 0;
- if (status === 'failed' || status === 'unreachable') {
- scope.jobData.hostSummaries[host_id].status = 'failed';
- }
- }
- else {
- scope.jobData.hostSummaries[host_id] = {
- id: host_id,
- name: name,
- ok: (status === 'successful') ? 1 : 0,
- changed: (status === 'changed') ? 1 : 0,
- unreachable: (status === 'unreachable') ? 1 : 0,
- failed: (status === 'failed') ? 1 : 0,
- status: (status === 'failed' || status === 'unreachable') ? 'failed' : 'successful'
- };
- }
- UpdateTaskStatus({
- scope: scope,
- task_id: task_id,
- failed: ((status === 'failed' || status === 'unreachable') ? true :false),
- changed: ((status === 'changed') ? true : false),
- modified: modified
- });
-
- AddHostResult({
- scope: scope,
- task_id: task_id,
- host_id: host_id,
- event_id: event_id,
- status: status,
- name: name,
- created: created,
- counter: counter,
- message: msg,
- item: item
- });
- };
- }])
-
- // Add a new host result
- .factory('AddHostResult', ['SetTaskStyles', 'SetActivePlay', 'SetActiveTask', function(SetTaskStyles, SetActivePlay, SetActiveTask) {
- return function(params) {
- var scope = params.scope,
- task_id = params.task_id,
- host_id = params.host_id,
- event_id = params.event_id,
- status = params.status,
- created = params.created,
- counter = params.counter,
- name = params.name,
- msg = params.message,
- item = params.item,
- status_text = '',
- task, play, play_id;
-
- switch(status) {
- case "successful":
- status_text = 'OK';
- break;
- case "changed":
- status_text = "Changed";
- break;
- case "failed":
- status_text = "Failed";
- break;
- case "unreachable":
- status_text = "Unreachable";
- break;
- case "skipped":
- status_text = "Skipped";
- }
-
- if (typeof item === "object") {
- item = JSON.stringify(item);
- }
-
- for (play in scope.jobData.plays) {
- for (task in scope.jobData.plays[play].tasks) {
- if (parseInt(task,10) === parseInt(task_id,10)) {
- play_id = parseInt(play,10);
- }
- }
- }
-
- if (play_id) {
- scope.jobData.plays[play_id].tasks[task_id].hostResults[event_id] = {
- id: event_id,
- status: status,
- status_text: status_text,
- host_id: host_id,
- task_id: task_id,
- name: name,
- created: created,
- counter: counter,
- msg: msg,
- item: item
- };
-
- // increment the unreachable count on the play
- if (status === 'unreachable') {
- scope.jobData.plays[play_id].unreachableCount++;
- }
-
- // update the task status bar
- task = scope.jobData.plays[play_id].tasks[task_id];
-
- if (task_id === scope.jobData.plays[play_id].firstTask) {
- scope.jobData.plays[play_id].hostCount++;
- task.hostCount++;
- }
-
- task.reportedHosts += 1;
- task.failedCount += (status === 'failed') ? 1 : 0;
- task.changedCount += (status === 'changed') ? 1 : 0;
- task.successfulCount += (status === 'successful') ? 1 : 0;
- task.skippedCount += (status === 'skipped') ? 1 : 0;
- task.unreachableCount += (status === 'unreachable') ? 1 : 0;
-
- SetTaskStyles({
- task: task
- });
-
- SetActivePlay({ scope: scope });
-
- SetActiveTask({ scope: scope });
- }
- };
- }])
-
- .factory('SetTaskStyles', [ function() {
- return function(params) {
- var task = params.task,
- diff;
-
- task.missingCount = task.hostCount - (task.failedCount + task.changedCount + task.skippedCount + task.successfulCount +
- task.unreachableCount);
- if(task.missingCount<0){
- task.hostCount = (task.failedCount + task.changedCount + task.skippedCount + task.successfulCount +
- task.unreachableCount);
- }
- task.missingPct = (task.hostCount > 0) ? Math.ceil((100 * (task.missingCount / task.hostCount))) : 0;
- task.failedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.failedCount / task.hostCount))) : 0;
- task.changedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.changedCount / task.hostCount))) : 0;
- task.skippedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.skippedCount / task.hostCount))) : 0;
- task.successfulPct = (task.hostCount > 0) ? Math.ceil((100 * (task.successfulCount / task.hostCount))) : 0;
- task.unreachablePct = (task.hostCount > 0) ? Math.ceil((100 * (task.unreachableCount / task.hostCount))) : 0;
-
- // cap % at 100
- task.missingPct = (task.missingPct > 100) ? 100 : task.missingPct;
- task.failedPct = (task.failedPct > 100) ? 100 : task.failedPct;
- task.changedPct = (task.changedPct > 100) ? 100 : task.changedPct;
- task.skippedPct = (task.skippedPct > 100) ? 100 : task.skippedPct;
- task.successfulPct = ( task.successfulPct > 100) ? 100 : task.successfulPct;
- task.unreachablePct = (task.unreachablePct > 100) ? 100 : task.unreachablePct;
-
- diff = (task.failedPct + task.changedPct + task.skippedPct + task.successfulPct + task.unreachablePct + task.missingPct) - 100;
- if (diff > 0) {
- if (task.failedPct > diff) {
- task.failedPct = task.failedPct - diff;
- }
- else if (task.changedPct > diff) {
- task.changedPct = task.changedPct - diff;
- }
- else if (task.skippedPct > diff) {
- task.skippedPct = task.skippedPct - diff;
- }
- else if (task.successfulPct > diff) {
- task.successfulPct = task.successfulPct - diff;
- }
- else if (task.unreachablePct > diff) {
- task.unreachablePct = task.unreachablePct - diff;
- }
- else if (task.missingPct > diff) {
- task.missingPct = task.missingPct - diff;
- }
- }
- task.successfulStyle = (task.successfulPct > 0) ? { 'display': 'inline-block' }: { 'display': 'none' };
- task.changedStyle = (task.changedPct > 0) ? { 'display': 'inline-block'} : { 'display': 'none' };
- task.skippedStyle = (task.skippedPct > 0) ? { 'display': 'inline-block' } : { 'display': 'none' };
- task.failedStyle = (task.failedPct > 0) ? { 'display': 'inline-block' } : { 'display': 'none' };
- task.unreachableStyle = (task.unreachablePct > 0) ? { 'display': 'inline-block' } : { 'display': 'none' };
- task.missingStyle = (task.missingPct > 0) ? { 'display': 'inline-block' } : { 'display': 'none' };
- };
- }])
-
- .factory('LoadPlays', ['Rest', 'ProcessErrors', 'GetElapsed', 'SelectPlay', 'JobIsFinished',
- function(Rest, ProcessErrors, GetElapsed, SelectPlay, JobIsFinished) {
- return function(params) {
- var scope = params.scope,
- callback = params.callback,
- url;
-
- scope.plays = [];
-
- scope.playsLoading = true;
- Rest.setUrl(url);
- Rest.get()
- .success(function(data) {
- scope.next_plays = data.next;
- scope.plays = [];
- data.results.forEach(function(event, idx) {
- var status, status_text, start, end, elapsed;
-
- status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful';
- status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK';
- start = event.started;
-
- if (idx < data.results.length - 1) {
- // end date = starting date of the next event
- end = data.results[idx + 1].started;
- }
- else if (JobIsFinished(scope)) {
- // this is the last play and the job already finished
- end = scope.job_status.finished;
- }
- if (end) {
- elapsed = GetElapsed({
- start: start,
- end: end
- });
- }
- else {
- elapsed = '00:00:00';
- }
-
- scope.plays.push({
- id: event.id,
- name: event.play,
- created: start,
- finished: end,
- status: status,
- status_text: status_text,
- status_tip: "Event ID: " + event.id + "
Status: " + status_text,
- elapsed: elapsed,
- hostCount: 0,
- fistTask: null,
- playActiveClass: '',
- unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0,
- });
- });
-
- // set the active task
- SelectPlay({
- scope: scope,
- id: (scope.plays.length > 0) ? scope.plays[0].id : null,
- callback: callback
- });
- scope.playsLoading = false;
- })
- .error(function(data) {
- ProcessErrors(scope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + url + '. GET returned: ' + status });
- });
- };
- }])
-
- // Call when the selected Play needs to change
- .factory('SelectPlay', ['LoadTasks', function(LoadTasks) {
- return function(params) {
- var scope = params.scope,
- id = params.id,
- callback = params.callback;
-
- scope.selectedPlay = id;
- scope.plays.forEach(function(play, idx) {
- if (play.id === scope.selectedPlay) {
- scope.plays[idx].playActiveClass = 'JobDetail-tableRow--selected';
- }
- else {
- scope.plays[idx].playActiveClass = '';
- }
- });
-
- LoadTasks({
- scope: scope,
- callback: callback,
- clear: true
- });
-
- };
- }])
-
- .factory('LoadTasks', ['Rest', 'ProcessErrors', 'GetElapsed', 'SelectTask', 'SetTaskStyles', function(Rest, ProcessErrors, GetElapsed, SelectTask, SetTaskStyles) {
- return function(params) {
- var scope = params.scope,
- callback = params.callback,
- url, play;
-
- scope.tasks = [];
- if (scope.selectedPlay) {
- url = scope.job.url + 'job_tasks/?event_id=' + scope.selectedPlay;
-
- scope.plays.every(function(p, idx) {
- if (p.id === scope.selectedPlay) {
- play = scope.plays[idx];
- return false;
- }
- return true;
- });
-
- scope.tasksLoading = true;
-
- Rest.setUrl(url);
- Rest.get()
- .success(function(data) {
- scope.next_tasks = data.next;
- scope.tasks = [];
- data.results.forEach(function(event, idx) {
- var end, elapsed, status, status_text;
-
- if (play.firstTask === undefined || play.firstTask === null) {
- play.firstTask = event.id;
- play.hostCount = (event.host_count) ? event.host_count : 0;
- }
-
- if (idx < data.results.length - 1) {
- // end date = starting date of the next event
- end = data.results[idx + 1].created;
- }
- else {
- // no next event (task), get the end time of the play
- scope.plays.every(function(play) {
- if (play.id === scope.selectedPlay) {
- end = play.finished;
- return false;
- }
- return true;
- });
- }
-
- if (end) {
- elapsed = GetElapsed({
- start: event.created,
- end: end
- });
- }
- else {
- elapsed = '00:00:00';
- }
-
- status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful';
- status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK';
-
- scope.tasks.push({
- id: event.id,
- play_id: scope.selectedPlay,
- name: event.name,
- status: status,
- status_text: status_text,
- status_tip: "Event ID: " + event.id + "
Status: " + status_text,
- created: event.created,
- modified: event.modified,
- finished: end,
- elapsed: elapsed,
- hostCount: (event.host_count) ? event.host_count : 0,
- reportedHosts: (event.reported_hosts) ? event.reported_hosts : 0,
- successfulCount: (event.successful_count) ? event.successful_count : 0,
- failedCount: (event.failed_count) ? event.failed_count : 0,
- changedCount: (event.changed_count) ? event.changed_count : 0,
- skippedCount: (event.skipped_count) ? event.skipped_count : 0,
- unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0,
- taskActiveClass: ''
- });
-
- if (play.firstTask !== event.id) {
- // this is not the first task
- scope.tasks[scope.tasks.length - 1].hostCount = play.hostCount;
- }
-
- SetTaskStyles({
- task: scope.tasks[scope.tasks.length - 1]
- });
- });
-
- // set the active task
- SelectTask({
- scope: scope,
- id: (scope.tasks.length > 0) ? scope.tasks[0].id : null,
- callback: callback
- });
-
- scope.tasksLoading = false;
-
- })
- .error(function(data) {
- ProcessErrors(scope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + url + '. GET returned: ' + status });
- });
- }
- else {
- SelectTask({
- scope: scope,
- id: null,
- callback: callback
- });
- }
- };
- }])
-
- // Call when the selected task needs to change
- .factory('SelectTask', ['JobDetailService', function(JobDetailService) {
- return function(params) {
- var scope = params.scope,
- id = params.id;
-
- scope.selectedTask = id;
- scope.tasks.forEach(function(task, idx) {
- if (task.id === scope.selectedTask) {
- scope.tasks[idx].taskActiveClass = 'JobDetail-tableRow--selected';
- }
- else {
- scope.tasks[idx].taskActiveClass = '';
- }
- });
- if (scope.selectedTask !== null){
- params = {
- parent: scope.selectedTask,
- event__startswith: 'runner',
- page_size: scope.hostResultsMaxRows,
- order: 'host_name,counter',
- };
-
- JobDetailService.getRelatedJobEvents(scope.job.id, params).success(function(res){
- scope.hostResults = JobDetailService.processHostEvents(res.results);
- scope.hostResultsLoading = false;
- });
- }
- else{
- scope.hostResults = [];
- scope.hostResultsLoading = false;
- }
- };
- }])
-
- .factory('DrawGraph', ['DonutChart', function(DonutChart) {
- return function(params) {
- var count = params.count,
- graph_data = [];
- // Ready the data
- if (count.ok.length > 0) {
- graph_data.push({
- label: 'OK',
- value: count.ok.length,
- color: '#5CB85C'
- });
- }
- if (count.changed.length > 0) {
- graph_data.push({
- label: 'CHANGED',
- value: count.changed.length,
- color: '#FF9900'
- });
- }
- if (count.unreachable.length > 0) {
- graph_data.push({
- label: 'UNREACHABLE',
- value: count.unreachable.length,
- color: '#FF0000'
- });
- }
- if (count.failures.length > 0) {
- graph_data.push({
- label: 'FAILED',
- value: count.failures.length,
- color: '#D9534F'
- });
- }
- DonutChart({
- data: graph_data
- });
- };
- }])
-
- .factory('DonutChart', [function() {
- return function(params) {
- var dataset = params.data,
- element = $("#graph-section"),
- colors, total,job_detail_chart;
-
- colors = _.map(dataset, function(d){
- return d.color;
- });
- total = d3.sum(dataset.map(function(d) {
- return d.value;
- }));
- job_detail_chart = nv.models.pieChart()
- .margin({bottom: 15})
- .x(function(d) {
- return d.label +': '+ Math.floor((d.value/total)*100) + "%";
- })
- .y(function(d) { return d.value; })
- .showLabels(false)
- .showLegend(true)
- .growOnHover(false)
- .labelThreshold(0.01)
- .tooltipContent(function(x, y) {
- return '
'+x+'
'+ '' + Math.floor(y.replace(',','')) + ' HOSTS ' + '
';
- })
- .color(colors);
- job_detail_chart.legend.rightAlign(false);
- job_detail_chart.legend.margin({top: 5, right: 450, left:0, bottom: 0});
- d3.select(element.find('svg')[0])
- .datum(dataset)
- .transition().duration(350)
- .call(job_detail_chart)
- .style({
- "font-family": 'Open Sans',
- "font-style": "normal",
- "font-weight":400,
- "src": "url(/static/assets/OpenSans-Regular.ttf)",
- "width": 600,
- "height": 300,
- "color": '#848992'
- });
- d3.select(element.find(".nv-noData")[0])
- .style({
- "text-anchor": 'start'
- });
- return job_detail_chart;
- };
- }])
-
-
- .factory('DrawPlays', [function() {
- return function(params) {
- var scope = params.scope,
- idx = 0,
- result = [],
- newKeys = [],
- //plays = JSON.parse(JSON.stringify(scope.jobData.plays)),
- plays = scope.jobData.plays,
- filteredListX = [],
- filteredListB = [],
- key,
- keys;
-
- function listSort(a,b) {
- if (parseInt(a,10) < parseInt(b,10)) {
- return -1;
- }
- if (parseInt(a,10) > parseInt(b,10)) {
- return 1;
- }
- return 0;
- }
-
- // Only draw plays that are in the 'active' list
- for (key in plays) {
- if (plays[key].taskCount > 0) {
- filteredListX[key] = plays[key];
- }
- }
-
- keys = Object.keys(filteredListB);
- keys.sort(function(a,b) { return listSort(a,b); }).reverse();
- for (idx=0; idx < scope.playsMaxRows && idx < keys.length; idx++) {
- newKeys.push(keys[idx]);
- }
- newKeys.sort(function(a,b) { return listSort(a,b); });
- idx = 0;
- while (idx < newKeys.length) {
- result.push(filteredListB[newKeys[idx]]);
- idx++;
- }
- setTimeout( function() {
- scope.$apply( function() {
- scope.plays = result;
- scope.selectedPlay = scope.activePlay;
- if (scope.liveEventProcessing) {
- $('#plays-table-detail').scrollTop($('#plays-table-detail').prop("scrollHeight"));
- }
- });
- });
- };
- }])
-
- .factory('DrawTasks', [ function() {
- return function(params) {
- var scope = params.scope,
- result = [],
- filteredListX = [],
- filteredListB = [],
- idx, key, keys, newKeys, tasks, t;
-
- function listSort(a,b) {
- if (parseInt(a,10) < parseInt(b,10)) {
- return -1;
- }
- if (parseInt(a,10) > parseInt(b,10)) {
- return 1;
- }
- return 0;
- }
-
- if (scope.activePlay && scope.jobData.plays[scope.activePlay]) {
-
- //tasks = JSON.parse(JSON.stringify(scope.jobData.plays[scope.activePlay].tasks));
- tasks = scope.jobData.plays[scope.activePlay].tasks;
-
- // Only draw tasks that are in the 'active' list
- for (key in tasks) {
- t = tasks[key];
- if (t.reportedHosts > 0 || t.hostCount > 0 || t.successfulCount >0 || t.failedCount > 0 ||
- t.changedCount > 0 || t.skippedCount > 0 || t.unreachableCount > 0) {
- filteredListX[key] = tasks[key];
- }
- }
-
- keys = Object.keys(filteredListB);
- keys.sort(function(a,b) { return listSort(a,b); }).reverse();
- newKeys = [];
- for (idx=0; result.length < scope.tasksMaxRows && idx < keys.length; idx++) {
- newKeys.push(keys[idx]);
- }
- newKeys.sort(function(a,b) { return listSort(a,b); });
- idx = 0;
- while (idx < newKeys.length) {
- result.push(filteredListB[newKeys[idx]]);
- idx++;
- }
- }
-
- setTimeout( function() {
- scope.$apply( function() {
- scope.tasks = result;
- scope.selectedTask = scope.activeTask;
- if (scope.liveEventProcessing) {
- $('#tasks-table-detail').scrollTop($('#tasks-table-detail').prop("scrollHeight"));
- }
- });
- });
-
- };
- }])
-
- .factory('DrawHostResults', [ function() {
- return function(params) {
- var scope = params.scope,
- result = [],
- filteredListB = [],
- idx = 0,
- hostResults,
- keys;
-
- if (scope.activePlay && scope.activeTask && scope.jobData.plays[scope.activePlay] &&
- scope.jobData.plays[scope.activePlay].tasks[scope.activeTask]) {
-
- hostResults = scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].hostResults;
-
- keys = Object.keys(filteredListB);
- keys.sort(function compare(a, b) {
- if (filteredListB[a].name === filteredListB[b].name) {
- if (filteredListB[a].counter < filteredListB[b].counter) {
- return -1;
- }
- if (filteredListB[a].counter >filteredListB[b].counter) {
- return 1;
- }
- } else {
- if (filteredListB[a].name < filteredListB[b].name) {
- return -1;
- }
- if (filteredListB[a].name > filteredListB[b].name) {
- return 1;
- }
- }
- // a must be equal to b
- return 0;
- });
- while (idx < keys.length && result.length < scope.hostResultsMaxRows) {
- result.push(filteredListB[keys[idx]]);
- idx++;
- }
- }
-
- setTimeout( function() {
- scope.$apply( function() {
- scope.hostResults = result;
- if (scope.liveEventProcessing) {
- $('#hosts-table-detail').scrollTop($('#hosts-table-detail').prop("scrollHeight"));
- }
- });
- });
-
- };
- }])
-
- .factory('UpdateDOM', ['DrawPlays', 'DrawTasks', 'DrawHostResults',
- function(DrawPlays, DrawTasks, DrawHostResults) {
- return function(params) {
- var scope = params.scope;
- if (!scope.pauseLiveEvents) {
- DrawPlays({ scope: scope });
- DrawTasks({ scope: scope });
- DrawHostResults({ scope: scope });
- }
-
- setTimeout(function() {
- scope.playsLoading = false;
- scope.tasksLoading = false;
- scope.hostResultsLoading = false;
- },100);
- };
- }]);
diff --git a/awx/ui/client/src/job-detail/host-event/host-event-codemirror.partial.html b/awx/ui/client/src/job-detail/host-event/host-event-codemirror.partial.html
deleted file mode 100644
index 7c744d2169..0000000000
--- a/awx/ui/client/src/job-detail/host-event/host-event-codemirror.partial.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
diff --git a/awx/ui/client/src/job-detail/host-event/host-event-details.partial.html b/awx/ui/client/src/job-detail/host-event/host-event-details.partial.html
deleted file mode 100644
index c287788f19..0000000000
--- a/awx/ui/client/src/job-detail/host-event/host-event-details.partial.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
EVENT
-
-
-
STATUS
-
-
-
-
- {{processEventStatus(event).status || "No result found"}}
-
-
-
- ID
- {{event.id || "No result found"}}
-
-
- CREATED
- {{(event.created | longDate) || "No result found"}}
-
-
- PLAY
- {{event.play || "No result found"}}
-
-
- TASK
- {{event.task || "No result found"}}
-
-
- MODULE
- {{event.event_data.res.invocation.module_name || "No result found"}}
-
-
-
-
RESULTS
-
-
- {{key}}
- {{value}}
-
-
diff --git a/awx/ui/client/src/job-detail/host-event/host-event-modal.partial.html b/awx/ui/client/src/job-detail/host-event/host-event-modal.partial.html
deleted file mode 100644
index db236894e8..0000000000
--- a/awx/ui/client/src/job-detail/host-event/host-event-modal.partial.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/job-detail/host-event/host-event-timing.partial.html b/awx/ui/client/src/job-detail/host-event/host-event-timing.partial.html
deleted file mode 100644
index 06171bd1c5..0000000000
--- a/awx/ui/client/src/job-detail/host-event/host-event-timing.partial.html
+++ /dev/null
@@ -1 +0,0 @@
-timing
\ No newline at end of file
diff --git a/awx/ui/client/src/job-detail/host-event/host-event.block.less b/awx/ui/client/src/job-detail/host-event/host-event.block.less
deleted file mode 100644
index 9b31b74e87..0000000000
--- a/awx/ui/client/src/job-detail/host-event/host-event.block.less
+++ /dev/null
@@ -1,150 +0,0 @@
-// @import "./client/src/shared/branding/colors.less";
-// @import "./client/src/shared/branding/colors.default.less";
-// @import "./client/src/shared/layouts/one-plus-two.less";
-//
-// .noselect {
-// -webkit-touch-callout: none; /* iOS Safari */
-// -webkit-user-select: none; /* Chrome/Safari/Opera */
-// -khtml-user-select: none; /* Konqueror */
-// -moz-user-select: none; /* Firefox */
-// -ms-user-select: none; /* Internet Explorer/Edge */
-// user-select: none; /* Non-prefixed version, currently
-// not supported by any browser */
-// }
-//
-// @media screen and (min-width: 768px){
-// .HostEvent .modal-dialog{
-// width: 700px;
-// }
-// }
-// .HostEvent .CodeMirror{
-// overflow-x: hidden;
-// }
-// .HostEvent-controls button.HostEvent-close{
-// color: #FFFFFF;
-// text-transform: uppercase;
-// padding-left: 15px;
-// padding-right: 15px;
-// background-color: @default-link;
-// border-color: @default-link;
-// &:hover{
-// background-color: @default-link-hov;
-// border-color: @default-link-hov;
-// }
-// }
-// .HostEvent-body{
-// margin-bottom: 10px;
-// }
-// .HostEvent-tab {
-// color: @btn-txt;
-// background-color: @btn-bg;
-// font-size: 12px;
-// border: 1px solid @btn-bord;
-// height: 30px;
-// border-radius: 5px;
-// margin-right: 20px;
-// padding-left: 10px;
-// padding-right: 10px;
-// padding-bottom: 5px;
-// padding-top: 5px;
-// transition: background-color 0.2s;
-// text-transform: uppercase;
-// text-align: center;
-// white-space: nowrap;
-// .noselect;
-// }
-// .HostEvent-tab:hover {
-// color: @btn-txt;
-// background-color: @btn-bg-hov;
-// cursor: pointer;
-// }
-// .HostEvent-tab--selected{
-// color: @btn-txt-sel!important;
-// background-color: @default-icon!important;
-// border-color: @default-icon!important;
-// }
-// .HostEvent-view--container{
-// width: 100%;
-// display: flex;
-// flex-direction: row;
-// flex-wrap: nowrap;
-// justify-content: space-between;
-// }
-// .HostEvent .modal-footer{
-// border: 0;
-// margin-top: 0px;
-// padding-top: 5px;
-// }
-// .HostEvent-controls{
-// float: right;
-// button {
-// margin-left: 10px;
-// }
-// }
-// .HostEvent-status--ok{
-// color: @green;
-// }
-// .HostEvent-status--unreachable{
-// color: @unreachable;
-// }
-// .HostEvent-status--changed{
-// color: @changed;
-// }
-// .HostEvent-status--failed{
-// color: @default-err;
-// }
-// .HostEvent-status--skipped{
-// color: @skipped;
-// }
-// .HostEvent-title{
-// color: @default-interface-txt;
-// font-weight: 600;
-// margin-bottom: 8px;
-// }
-// // .HostEvent .modal-body{
-// // max-height: 500px;
-// // overflow-y: auto;
-// // padding: 20px;
-// // }
-// .HostEvent-nav{
-// padding-top: 12px;
-// padding-bottom: 12px;
-// }
-// .HostEvent-field{
-// margin-bottom: 8px;
-// flex: 0 1 12em;
-// }
-// .HostEvent-field--label{
-// text-transform: uppercase;
-// flex: 0 1 80px;
-// max-width: 80px;
-// font-size: 12px;
-// word-wrap: break-word;
-// }
-// .HostEvent-field{
-// .OnePlusTwo-left--detailsRow;
-// }
-// .HostEvent-field--content{
-// word-wrap: break-word;
-// max-width: 13em;
-// flex: 0 1 13em;
-// }
-// .HostEvent-details--left, .HostEvent-details--right{
-// flex: 1 1 47%;
-// }
-// .HostEvent-details--left{
-// margin-right: 40px;
-// }
-// .HostEvent-details--right{
-// .HostEvent-field--label{
-// flex: 0 1 25em;
-// }
-// .HostEvent-field--content{
-// max-width: 15em;
-// flex: 0 1 15em;
-// align-self: flex-end;
-// }
-// }
-// .HostEvent-button:disabled {
-// pointer-events: all!important;
-// }
diff --git a/awx/ui/client/src/job-detail/host-event/host-event.controller.js b/awx/ui/client/src/job-detail/host-event/host-event.controller.js
deleted file mode 100644
index f86452b005..0000000000
--- a/awx/ui/client/src/job-detail/host-event/host-event.controller.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-
- export default
- ['$stateParams', '$scope', '$state', 'Wait', 'JobDetailService', 'hostEvent', 'hostResults',
- function($stateParams, $scope, $state, Wait, JobDetailService, hostEvent, hostResults){
-
- $scope.processEventStatus = JobDetailService.processEventStatus;
- $scope.hostResults = [];
- // Avoid rendering objects in the details fieldset
- // ng-if="processResults(value)" via host-event-details.partial.html
- $scope.processResults = function(value){
- if (typeof value === 'object'){return false;}
- else {return true;}
- };
- $scope.isStdOut = function(){
- if ($state.current.name === 'jobDetails.host-event.stdout' || $state.current.name === 'jobDetaisl.histe-event.stderr'){
- return 'StandardOut-preContainer StandardOut-preContent';
- }
- };
- /*ignore jslint start*/
- var initCodeMirror = function(el, data, mode){
- var container = document.getElementById(el);
- var editor = CodeMirror.fromTextArea(container, { // jshint ignore:line
- lineNumbers: true,
- mode: mode
- });
- editor.setSize("100%", 300);
- editor.getDoc().setValue(data);
- };
- /*ignore jslint end*/
- $scope.isActiveState = function(name){
- return $state.current.name === name;
- };
-
- $scope.getActiveHostIndex = function(){
- var result = $scope.hostResults.filter(function( obj ) {
- return obj.id === $scope.event.id;
- });
- return $scope.hostResults.indexOf(result[0]);
- };
-
- $scope.showPrev = function(){
- return $scope.getActiveHostIndex() !== 0;
- };
-
- $scope.showNext = function(){
- return $scope.getActiveHostIndex() < $scope.hostResults.indexOf($scope.hostResults[$scope.hostResults.length - 1]);
- };
-
- $scope.goNext = function(){
- var index = $scope.getActiveHostIndex() + 1;
- var id = $scope.hostResults[index].id;
- $state.go('jobDetail.host-event.details', {eventId: id});
- };
-
- $scope.goPrev = function(){
- var index = $scope.getActiveHostIndex() - 1;
- var id = $scope.hostResults[index].id;
- $state.go('jobDetail.host-event.details', {eventId: id});
- };
-
- var init = function(){
- $scope.event = _.cloneDeep(hostEvent);
- $scope.hostResults = hostResults;
- $scope.json = JobDetailService.processJson(hostEvent);
-
- // grab standard out & standard error if present, and remove from the results displayed in the details panel
- if (hostEvent.event_data.res.stdout){
- $scope.stdout = hostEvent.event_data.res.stdout;
- delete $scope.event.event_data.res.stdout;
- }
- if (hostEvent.event_data.res.stderr){
- $scope.stderr = hostEvent.event_data.res.stderr;
- delete $scope.event.event_data.res.stderr;
- }
- // instantiate Codemirror
- // try/catch pattern prevents the abstract-state controller from complaining about element being null
- if ($state.current.name === 'jobDetail.host-event.json'){
- try{
- initCodeMirror('HostEvent-codemirror', JSON.stringify($scope.json, null, 4), {name: "javascript", json: true});
- }
- catch(err){
- // element with id HostEvent-codemirror is not the view controlled by this instance of HostEventController
- }
- }
- else if ($state.current.name === 'jobDetail.host-event.stdout'){
- try{
- initCodeMirror('HostEvent-codemirror', $scope.stdout, 'shell');
- }
- catch(err){
- // element with id HostEvent-codemirror is not the view controlled by this instance of HostEventController
- }
- }
- else if ($state.current.name === 'jobDetail.host-event.stderr'){
- try{
- initCodeMirror('HostEvent-codemirror', $scope.stderr, 'shell');
- }
- catch(err){
- // element with id HostEvent-codemirror is not the view controlled by this instance of HostEventController
- }
- }
- $('#HostEvent').modal('show');
- };
- init();
- }];
diff --git a/awx/ui/client/src/job-detail/host-event/host-event.route.js b/awx/ui/client/src/job-detail/host-event/host-event.route.js
deleted file mode 100644
index 86e499c2b0..0000000000
--- a/awx/ui/client/src/job-detail/host-event/host-event.route.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import { templateUrl } from '../../shared/template-url/template-url.factory';
-
-var hostEventModal = {
- name: 'jobDetail.host-event',
- url: '/task/:taskId/host-event/:eventId',
- controller: 'HostEventController',
- templateUrl: templateUrl('job-detail/host-event/host-event-modal'),
- 'abstract': true,
- resolve: {
- hostEvent: ['JobDetailService', '$stateParams', function(JobDetailService, $stateParams) {
- return JobDetailService.getRelatedJobEvents($stateParams.id, {
- id: $stateParams.eventId
- }).then(function(res) {
- return res.data.results[0]; });
- }],
- hostResults: ['JobDetailService', '$stateParams', function(JobDetailService, $stateParams) {
- return JobDetailService.getJobEventChildren($stateParams.taskUuid).then(res => res.data.results);
- }]
- },
- onExit: function() {
- // close the modal
- // using an onExit event to handle cases where the user navs away using the url bar / back and not modal "X"
- $('#HostEvent').modal('hide');
- // hacky way to handle user browsing away via URL bar
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
-};
-
-var hostEventDetails = {
- name: 'jobDetail.host-event.details',
- url: '/details',
- controller: 'HostEventController',
- templateUrl: templateUrl('job-detail/host-event/host-event-details'),
-};
-
-var hostEventJson = {
- name: 'jobDetail.host-event.json',
- url: '/json',
- controller: 'HostEventController',
- templateUrl: templateUrl('job-detail/host-event/host-event-codemirror')
-};
-
-var hostEventStdout = {
- name: 'jobDetail.host-event.stdout',
- url: '/stdout',
- controller: 'HostEventController',
- templateUrl: templateUrl('job-detail/host-event/host-event-codemirror')
-};
-
-var hostEventStderr = {
- name: 'jobDetail.host-event.stderr',
- url: '/stderr',
- controller: 'HostEventController',
- templateUrl: templateUrl('job-detail/host-event/host-event-codemirror')
-};
-
-
-export { hostEventDetails, hostEventJson, hostEventModal, hostEventStdout, hostEventStderr };
diff --git a/awx/ui/client/src/job-detail/host-event/main.js b/awx/ui/client/src/job-detail/host-event/main.js
deleted file mode 100644
index 4379427ff8..0000000000
--- a/awx/ui/client/src/job-detail/host-event/main.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- import {hostEventModal, hostEventDetails,
- hostEventJson, hostEventStdout, hostEventStderr} from './host-event.route';
- import controller from './host-event.controller';
-
- export default
- angular.module('jobDetail.hostEvent', [])
- .controller('HostEventController', controller)
-
- .run(['$stateExtender', function($stateExtender){
- $stateExtender.addState(hostEventModal);
- $stateExtender.addState(hostEventDetails);
- $stateExtender.addState(hostEventJson);
- $stateExtender.addState(hostEventStdout);
- $stateExtender.addState(hostEventStderr);
- }]);
diff --git a/awx/ui/client/src/job-detail/host-events/host-events.block.less b/awx/ui/client/src/job-detail/host-events/host-events.block.less
deleted file mode 100644
index df52944cf0..0000000000
--- a/awx/ui/client/src/job-detail/host-events/host-events.block.less
+++ /dev/null
@@ -1,93 +0,0 @@
-@import "./client/src/shared/branding/colors.less";
-@import "./client/src/shared/branding/colors.default.less";
-
-.HostEvents .CodeMirror{
- border: none;
-}
-.HostEvents .modal-footer{
- border: 0;
- margin-top: 0px;
- padding: 0px 20px 20px 20px;
-}
-button.HostEvents-close{
- width: 70px;
- color: #FFFFFF!important;
- text-transform: uppercase;
- padding-left: 15px;
- padding-right: 15px;
- background-color: @default-link;
- border-color: @default-link;
- &:hover{
- background-color: @default-link-hov;
- border-color: @default-link-hov;
- }
-}
-.HostEvents-status--ok{
- color: @green;
-}
-.HostEvents-status--unreachable{
- color: @unreachable;
-}
-.HostEvents-status--changed{
- color: @changed;
-}
-.HostEvents-status--failed{
- color: @default-err;
-}
-.HostEvents-status--skipped{
- color: @skipped;
-}
-
-.HostEvents-filter--form{
- padding-top: 15px;
- padding-bottom: 15px;
- float: right;
- display: inline-block;
-}
-.HostEvents .modal-body{
- padding: 20px;
-}
-.HostEvents .select2-container{
- text-transform: capitalize;
- max-width: 220px;
- float: right;
-}
-.HostEvents-form--container{
- padding-top: 15px;
- padding-bottom: 15px;
-}
-.HostEvents-title{
- text-transform: uppercase;
- color: @default-interface-txt;
- font-weight: 600;
-}
-.HostEvents-status i {
- padding-right: 10px;
-}
-.HostEvents-table--header {
- height: 30px;
- font-size: 14px;
- font-weight: normal;
- text-transform: uppercase;
- color: @default-interface-txt;
- background-color: @default-list-header-bg;
- padding-left: 15px;
- padding-right: 15px;
- border-bottom-width: 0px;
-}
-.HostEvents-table--header:first-of-type{
- border-top-left-radius: 5px;
-}
-.HostEvents-table--header:last-of-type{
- border-top-right-radius: 5px;
-}
-.HostEvents-table--row{
- color: @default-data-txt;
- border: 0 !important;
-}
-.HostEvents-table--row:nth-child(odd){
- background: @default-tertiary-bg;
-}
-.HostEvents-table--cell{
- border: 0 !important;
-}
diff --git a/awx/ui/client/src/job-detail/host-events/host-events.controller.js b/awx/ui/client/src/job-detail/host-events/host-events.controller.js
deleted file mode 100644
index 5664c89877..0000000000
--- a/awx/ui/client/src/job-detail/host-events/host-events.controller.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- export default
- ['$stateParams', '$scope', '$rootScope', '$state', 'Wait',
- 'JobDetailService', 'CreateSelect2', 'hosts',
- function($stateParams, $scope, $rootScope, $state, Wait,
- JobDetailService, CreateSelect2, hosts){
-
- // pagination not implemented yet, but it'll depend on this
- $scope.page_size = $stateParams.page_size;
-
- $scope.processEventStatus = JobDetailService.processEventStatus;
- $scope.activeFilter = $stateParams.filter || null;
-
- $scope.filters = ['all', 'changed', 'failed', 'ok', 'unreachable', 'skipped'];
-
- // watch select2 for changes
- $('.HostEvents-select').on("select2:select", function () {
- $scope.activeFilter = $('.HostEvents-select').val();
- });
-
- var init = function(){
- $scope.hostName = $stateParams.hostName;
- // create filter dropdown
- CreateSelect2({
- element: '.HostEvents-select',
- multiple: false
- });
- // process the filter if one was passed
- if ($stateParams.filter){
- $scope.activeFilter = $stateParams.filter;
-
- $('#HostEvents').modal('show');
- }
- else{
- $scope.results = hosts.data.results;
- $('#HostEvents').modal('show');
- }
- };
-
-
- init();
-
- }];
diff --git a/awx/ui/client/src/job-detail/host-events/host-events.partial.html b/awx/ui/client/src/job-detail/host-events/host-events.partial.html
deleted file mode 100644
index 00bacf066c..0000000000
--- a/awx/ui/client/src/job-detail/host-events/host-events.partial.html
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- |
-
-
-
-
- {{processEventStatus(event).status}}
- |
- {{event.play}} |
- {{event.task}} |
-
-
- |
- No results were found.
- |
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/job-detail/host-events/host-events.route.js b/awx/ui/client/src/job-detail/host-events/host-events.route.js
deleted file mode 100644
index 835d17b2b9..0000000000
--- a/awx/ui/client/src/job-detail/host-events/host-events.route.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import {templateUrl} from '../../shared/template-url/template-url.factory';
-
-export default {
- name: 'jobDetail.host-events',
- url: '/host-events/{hostName:any}?:filter',
- controller: 'HostEventsController',
- params: {
- page_size: 10
- },
- templateUrl: templateUrl('job-detail/host-events/host-events'),
- onExit: function(){
- // close the modal
- // using an onExit event to handle cases where the user navs away using the url bar / back and not modal "X"
- $('#HostEvents').modal('hide');
- // hacky way to handle user browsing away via URL bar
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- },
- resolve: {
- hosts: ['JobDetailService','$stateParams', function(JobDetailService, $stateParams) {
- return JobDetailService.getRelatedJobEvents($stateParams.id, {
- host_name: $stateParams.hostName
- }).success(function(res){ return res.results[0];});
- }]
- }
-};
diff --git a/awx/ui/client/src/job-detail/host-events/main.js b/awx/ui/client/src/job-detail/host-events/main.js
deleted file mode 100644
index 766dd92ca4..0000000000
--- a/awx/ui/client/src/job-detail/host-events/main.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import route from './host-events.route';
-import controller from './host-events.controller';
-
-export default
- angular.module('jobDetail.hostEvents', [])
- .controller('HostEventsController', controller)
- .run(['$stateExtender', function($stateExtender){
- $stateExtender.addState(route);
- }]);
diff --git a/awx/ui/client/src/job-detail/host-summary/host-summary.block.less b/awx/ui/client/src/job-detail/host-summary/host-summary.block.less
deleted file mode 100644
index 00af0d30ea..0000000000
--- a/awx/ui/client/src/job-detail/host-summary/host-summary.block.less
+++ /dev/null
@@ -1,17 +0,0 @@
-@import '../../shared/branding/colors.default.less';
-.HostSummary-graph--successful{
- text-anchor: start !important;
-}
-.HostSummary-graph--failed{
- text-anchor: end !important;
-}
-.HostSummary-graph--changed{
- text-anchor: start !important;
-}
-.HostSummary-loading{
- border: none;
-}
-.HostSummary-loading{
- padding-left: 0px !important;
- color: @default-interface-txt;
-}
diff --git a/awx/ui/client/src/job-detail/host-summary/host-summary.controller.js b/awx/ui/client/src/job-detail/host-summary/host-summary.controller.js
deleted file mode 100644
index cd5a241622..0000000000
--- a/awx/ui/client/src/job-detail/host-summary/host-summary.controller.js
+++ /dev/null
@@ -1,131 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- export default
- ['$scope', '$rootScope', '$stateParams', 'Wait', 'JobDetailService', 'DrawGraph', function($scope, $rootScope, $stateParams, Wait, JobDetailService, DrawGraph){
-
- var page_size = 200;
- $scope.loading = $scope.hosts.length > 0 ? false : true;
- $scope.filter = 'all';
-
- var buildGraph = function(hosts){
- // status waterfall: unreachable > failed > changed > ok > skipped
- var count;
- count = {
- ok : _.filter(hosts, function(o){
- return o.failures === 0 && o.changed === 0 && o.ok > 0;
- }),
- skipped : _.filter(hosts, function(o){
- return o.skipped > 0;
- }),
- unreachable : _.filter(hosts, function(o){
- return o.dark > 0;
- }),
- failures : _.filter(hosts, function(o){
- return o.failed === true;
- }),
- changed : _.filter(hosts, function(o){
- return o.changed > 0;
- })
- };
- return count;
- };
- var init = function(){
- Wait('start');
- JobDetailService.getJobHostSummaries($stateParams.id, {page_size: page_size, order_by: 'host_name'})
- .success(function(res){
- $scope.hosts = res.results;
- $scope.next = res.next;
- $scope.count = buildGraph(res.results);
- Wait('stop');
- DrawGraph({count: $scope.count, resize:true});
- });
- JobDetailService.getJob({id: $stateParams.id})
- .success(function(res){
- $scope.status = res.results[0].status;
- });
- };
- if ($rootScope.removeJobSummaryComplete) {
- $rootScope.removeJobSummaryComplete();
- }
- // emitted by the API in the same function used to persist host summary data
- // JobEvent.update_host_summary_from_stats() from /awx/main.models.jobs.py
- $scope.$on('ws-jobs-summary', function(e, data) {
- // discard socket msgs we don't care about in this context
- if (parseInt($stateParams.id) === data.unified_job_id){
- init();
- }
- });
-
- $scope.$on('ws-jobs', function(e, data) {
- if (parseInt($stateParams.id) === data.unified_job_id){
- $scope.status = data.status;
- }
- });
-
-
- $scope.buildTooltip = function(n, status){
- var grammar = function(n, status){
- var dict = {
- 0: 'No host events were ',
- 1: ' host event was ',
- 2: ' host events were '
- };
- if (n >= 2){
- return n + dict[2] + status;
- }
- else{
- return n !== 0 ? n + dict[n] + status : dict[n] + status;
- }
- };
- return grammar(n, status);
- };
- $scope.getNextPage = function(){
- if ($scope.next){
- JobDetailService.getNextPage($scope.next).success(function(res){
- res.results.forEach(function(key, index){
- $scope.hosts.push(res.results[index]);
- });
- $scope.hosts.push(res.results);
- $scope.next = res.next;
- });
- }
- };
-
- $scope.setFilter = function(filter){
- $scope.filter = filter;
- var getAll = function(){
- Wait('start');
- JobDetailService.getJobHostSummaries($stateParams.id, {
- page_size: page_size,
- order_by: 'host_name'
- }).success(function(res){
- Wait('stop');
- $scope.hosts = res.results;
- $scope.next = res.next;
- });
- };
- var getFailed = function(){
- Wait('start');
- JobDetailService.getJobHostSummaries($stateParams.id, {
- page_size: page_size,
- failed: true,
- order_by: 'host_name'
- }).success(function(res){
- Wait('stop');
- $scope.hosts = res.results;
- $scope.next = res.next;
- });
- };
- $scope.get = filter === 'all' ? getAll() : getFailed();
- };
-
- init();
- // calling the init routine twice will size the d3 chart correctly - no idea why
- // instantiating the graph inside a setTimeout() SHOULD have the same effect, but it doesn't
- // instantiating the graph further down the promise chain e.g. .then() or .finally() also does not work
- init();
- }];
diff --git a/awx/ui/client/src/job-detail/host-summary/host-summary.partial.html b/awx/ui/client/src/job-detail/host-summary/host-summary.partial.html
deleted file mode 100644
index 5452990e76..0000000000
--- a/awx/ui/client/src/job-detail/host-summary/host-summary.partial.html
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-
4 Please select a host below to view a summary of all associated tasks.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/job-detail/host-summary/host-summary.route.js b/awx/ui/client/src/job-detail/host-summary/host-summary.route.js
deleted file mode 100644
index a2de70e5d4..0000000000
--- a/awx/ui/client/src/job-detail/host-summary/host-summary.route.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import {templateUrl} from '../../shared/template-url/template-url.factory';
-
-export default {
- name: 'jobDetail.host-summary',
- url: '/event-summary',
- views:{
- 'host-summary': {
- controller: 'HostSummaryController',
- templateUrl: templateUrl('job-detail/host-summary/host-summary'),
- }
- },
- ncyBreadcrumb: {
- skip: true // Never display this state in breadcrumb.
- }
-};
diff --git a/awx/ui/client/src/job-detail/host-summary/main.js b/awx/ui/client/src/job-detail/host-summary/main.js
deleted file mode 100644
index fad85ffaf3..0000000000
--- a/awx/ui/client/src/job-detail/host-summary/main.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-import route from './host-summary.route';
-import controller from './host-summary.controller';
-
-export default
- angular.module('jobDetail.hostSummary', [])
- .controller('HostSummaryController', controller)
- .run(['$stateExtender', function($stateExtender){
- $stateExtender.addState(route);
- }]);
\ No newline at end of file
diff --git a/awx/ui/client/src/job-detail/job-detail.block.less b/awx/ui/client/src/job-detail/job-detail.block.less
deleted file mode 100644
index c23b8d321d..0000000000
--- a/awx/ui/client/src/job-detail/job-detail.block.less
+++ /dev/null
@@ -1,240 +0,0 @@
-/** @define SetupItem */
-
-@import '../shared/branding/colors.less';
-@import '../shared/branding/colors.default.less';
-@import '../shared/layouts/one-plus-two.less';
-
-@breakpoint-md: 1200px;
-@breakpoint-sm: 623px;
-
-.JobDetail-tasks.section{
- margin-top:40px;
-}
-.JobDetail-instructions{
- color: @default-interface-txt;
- margin: 10px 0 10px 0;
-
- .badge {
- background-color: @default-list-header-bg;
- color: @default-interface-txt;
- padding: 5px 7px;
- }
-}
-.JobDetail{
- .OnePlusTwo-container(100%, @breakpoint-md);
-
- &.fullscreen {
- .JobDetail-rightSide {
- max-width: 100%;
- }
- }
-}
-
-.JobDetail-leftSide{
- .OnePlusTwo-left--panel(100%, @breakpoint-md);
-}
-
-.JobDetail-rightSide{
- .OnePlusTwo-right--panel(100%, @breakpoint-md);
- @media (max-width: @breakpoint-md - 1px) {
- padding-right: 15px;
- }
-}
-.JobDetail-panelHeader{
- display: flex;
- height: 30px;
-}
-.JobDetail-expandContainer{
- flex: 1;
- margin: 0px;
- line-height: 30px;
- white-space: nowrap;
-}
-
-.JobDetail-panelHeaderText{
- color: @default-interface-txt;
- flex: 1 0 auto;
- font-size: 14px;
- font-weight: bold;
- margin-right: 10px;
- text-transform: uppercase;
-}
-
-.JobDetail-panelHeaderText:hover{
- color: @default-interface-txt;
- font-size: 14px;
- font-weight: bold;
- margin-right: 10px;
- text-transform: uppercase;
-}
-
-.JobDetail-expandArrow{
- color: @default-icon-hov;
- font-size: 14px;
- font-weight: bold;
- margin-right: 10px;
- text-transform: uppercase;
- margin-left: 10px;
-}
-
-.JobDetail-resultsDetails{
- display: flex;
- flex-wrap: wrap;
- flex-direction: row;
- padding-top: 25px;
- @media screen and(max-width: @breakpoint-sm){
- flex-direction: column;
- }
-}
-
-.JobDetail-resultRow{
- width: 100%;
- display: flex;
- padding-bottom: 10px;
- flex-wrap: wrap;
-}
-
-.JobDetail-resultRow--variables {
- flex-direction: column;
-}
-
-.JobDetail-resultRowLabel{
- text-transform: uppercase;
- color: @default-interface-txt;
- font-size: 14px;
- font-weight: normal!important;
- width: 30%;
- margin-right: 20px;
- @media screen and(max-width: @breakpoint-md){
- flex: 2.5 0 auto;
- }
-}
-
-.JobDetail-resultRowLabel--fullWidth {
- width: 100%;
- margin-right: 0px;
-}
-
-.JobDetail-resultRowText{
- width: ~"calc(70% - 20px)";
- flex: 1 0 auto;
- text-transform: none;
- word-wrap: break-word;
-}
-
-.JobDetail-resultRowText--fullWidth {
- width: 100%;
-}
-
-.JobDetail-searchHeaderRow{
- display: flex;
- flex-wrap: wrap;
- flex-direction: row;
- height: 50px;
- margin-top: 20px;
- @media screen and(max-width: @breakpoint-sm){
- height: auto;
- }
-}
-
-.JobDetail-searchContainer{
- flex: 2 0 auto;
- @media screen and(max-width: @breakpoint-sm){
- margin-bottom: 0px;
- }
-}
-
-.JobDetail-tableToggleContainer{
- flex: 1 0 auto;
- display: flex;
- justify-content: flex-end;
-}
-
-.JobDetail-tableToggle{
- padding-left:10px;
- padding-right: 10px;
- border: 1px solid @d7grey;
-}
-
-.JobDetail-tableToggle.active{
- background-color: @default-link;
- border: 1px solid @default-link;
- color: @default-bg;
-
- &:hover {
- background-color: @default-link-hov;
- }
-}
-.JobDetail .nvd3.nv-noData{
- color: @default-interface-txt;
- font-size: 12px;
- text-transform: uppercase;
- font-family: 'Open Sans', sans-serif;
-}
-.JobDetail .nv-series{
- padding-right: 30px;
- display: block;
-}
-.JobDetail-instructions .badge{
- background-color: @default-list-header-bg;
- color: @default-interface-txt;
-}
-.JobDetail-tableToggle--left{
- border-top-left-radius: 5px;
- border-bottom-left-radius: 5px;
-}
-
-.JobDetail-tableToggle--right{
- border-top-right-radius: 5px;
- border-bottom-right-radius: 5px;
-}
-
-.JobDetail-searchInput{
- border-radius: 5px !important;
-}
-
-.JobDetail-tableHeader:last-of-type{
- text-align:justify;
-}
-
-.JobDetail-statusIcon{
- padding-right: 10px;
- padding-left: 10px;
-}
-
-.JobDetail-tableRow--selected,
-.JobDetail-tableRow--selected > :first-child{
- border-left: 5px solid @list-row-select-bord;
-}
-
-.JobDetail-tableRow--selected > :first-child > .JobDetail-statusIcon{
- margin-left: -5px;
-}
-
-.JobDetails-table--noResults {
- tr > td {
- border-top: none !important;
- }
-}
-
-.JobDetail-statusIcon--results{
- padding-left: 0px;
- padding-right: 10px;
-}
-
-.JobDetail-graphSection{
- height: 320px;
- width:100%;
-}
-
-.JobDetail-stdoutActionButton--active{
- display: none;
- visibility: hidden;
- flex:none;
- width:0px;
- padding-right: 0px;
-}
-
-.JobDetail-leftSide.JobDetail-stdoutActionButton--active {
- margin-right: 0px;
-}
diff --git a/awx/ui/client/src/job-detail/job-detail.controller.js b/awx/ui/client/src/job-detail/job-detail.controller.js
deleted file mode 100644
index c3479e397b..0000000000
--- a/awx/ui/client/src/job-detail/job-detail.controller.js
+++ /dev/null
@@ -1,1027 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-/**
- * @ngdoc function
- * @name controllers.function:JobDetail
- * @description This controller's for the Job Detail Page
-*/
-
-export default
- [ '$location', '$rootScope', '$filter', '$scope', '$compile', '$state', '$stateParams', '$log', 'ClearScope',
- 'GetBasePath', 'Wait', 'ProcessErrors', 'SelectPlay', 'SelectTask', 'GetElapsed', 'JobIsFinished',
- 'SetTaskStyles', 'DigestEvent', 'UpdateDOM', 'DeleteJob', 'RelaunchPlaybook', 'LoadPlays', 'LoadTasks',
- 'ParseVariableString', 'GetChoices', 'fieldChoices', 'fieldLabels', 'EditSchedule',
- 'ParseTypeChange', 'JobDetailService',
- function(
- $location, $rootScope, $filter, $scope, $compile, $state, $stateParams, $log, ClearScope,
- GetBasePath, Wait, ProcessErrors, SelectPlay, SelectTask, GetElapsed, JobIsFinished,
- SetTaskStyles, DigestEvent, UpdateDOM, DeleteJob, RelaunchPlaybook, LoadPlays, LoadTasks,
- ParseVariableString, GetChoices, fieldChoices, fieldLabels, EditSchedule,
- ParseTypeChange, JobDetailService
- ) {
- ClearScope();
-
- var job_id = $stateParams.id,
- scope = $scope,
- api_complete = false,
- refresh_count = 0,
- lastEventId = 0,
- verbosity_options,
- job_type_options;
-
- scope.plays = [];
- scope.parseType = 'yaml';
- scope.previousTaskFailed = false;
- $scope.stdoutFullScreen = false;
-
- scope.$watch('job_status', function(job_status) {
- if (job_status && job_status.explanation && job_status.explanation.split(":")[0] === "Previous Task Failed") {
- scope.previousTaskFailed = true;
- var taskObj = JSON.parse(job_status.explanation.substring(job_status.explanation.split(":")[0].length + 1));
- // return a promise from the options request with the permission type choices (including adhoc) as a param
- var fieldChoice = fieldChoices({
- scope: $scope,
- url: 'api/v1/unified_jobs/',
- field: 'type'
- });
-
- // manipulate the choices from the options request to be set on
- // scope and be usable by the list form
- fieldChoice.then(function (choices) {
- choices =
- fieldLabels({
- choices: choices
- });
- scope.explanation_fail_type = choices[taskObj.job_type];
- scope.explanation_fail_name = taskObj.job_name;
- scope.explanation_fail_id = taskObj.job_id;
- scope.task_detail = scope.explanation_fail_type + " failed for " + scope.explanation_fail_name + " with ID " + scope.explanation_fail_id + ".";
- });
- } else {
- scope.previousTaskFailed = false;
- }
- }, true);
-
- scope.$watch('plays', function(plays) {
- for (var play in plays) {
- if (plays[play].elapsed) {
- plays[play].finishedTip = "Play completed at " + $filter("longDate")(plays[play].finished) + ".";
- } else {
- plays[play].finishedTip = "Play not completed.";
- }
- }
- });
- scope.hosts = [];
- scope.tasks = [];
- scope.$watch('tasks', function(tasks) {
- for (var task in tasks) {
- if (tasks[task].elapsed) {
- tasks[task].finishedTip = "Task completed at " + $filter("longDate")(tasks[task].finished) + ".";
- } else {
- tasks[task].finishedTip = "Task not completed.";
- }
- if (tasks[task].successfulCount) {
- tasks[task].successfulCountTip = tasks[task].successfulCount;
- tasks[task].successfulCountTip += (tasks[task].successfulCount === 1) ? " host event was" : " host events were";
- tasks[task].successfulCountTip += " ok.";
- } else {
- tasks[task].successfulCountTip = "No host events were ok.";
- }
- if (tasks[task].changedCount) {
- tasks[task].changedCountTip = tasks[task].changedCount;
- tasks[task].changedCountTip += (tasks[task].changedCount === 1) ? " host event" : " host events";
- tasks[task].changedCountTip += " changed.";
- } else {
- tasks[task].changedCountTip = "No host events changed.";
- }
- if (tasks[task].skippedCount) {
- tasks[task].skippedCountTip = tasks[task].skippedCount;
- tasks[task].skippedCountTip += (tasks[task].skippedCount === 1) ? " host event was" : " hosts events were";
- tasks[task].skippedCountTip += " skipped.";
- } else {
- tasks[task].skippedCountTip = "No host events were skipped.";
- }
- if (tasks[task].failedCount) {
- tasks[task].failedCountTip = tasks[task].failedCount;
- tasks[task].failedCountTip += (tasks[task].failedCount === 1) ? " host event" : " host events";
- tasks[task].failedCountTip += " failed.";
- } else {
- tasks[task].failedCountTip = "No host events failed.";
- }
- if (tasks[task].unreachableCount) {
- tasks[task].unreachableCountTip = tasks[task].unreachableCount;
- tasks[task].unreachableCountTip += (tasks[task].unreachableCount === 1) ? " host event was" : " hosts events were";
- tasks[task].unreachableCountTip += " unreachable.";
- } else {
- tasks[task].unreachableCountTip = "No host events were unreachable.";
- }
- if (tasks[task].missingCount) {
- tasks[task].missingCountTip = tasks[task].missingCount;
- tasks[task].missingCountTip += (tasks[task].missingCount === 1) ? " host event was" : " host events were";
- tasks[task].missingCountTip += " missing.";
- } else {
- tasks[task].missingCountTip = "No host events were missing.";
- }
- }
- });
- scope.hostResults = [];
-
- scope.hostResultsMaxRows = 200;
- scope.tasksMaxRows = 200;
- scope.playsMaxRows = 200;
-
- // Set the following to true when 'Loading...' message desired
- scope.playsLoading = true;
- scope.tasksLoading = true;
- scope.hostResultsLoading = true;
-
- // Turn on the 'Waiting...' message until events begin arriving
- scope.waiting = true;
-
- scope.liveEventProcessing = true; // true while job is active and live events are arriving
- scope.pauseLiveEvents = false; // control play/pause state of event processing
-
- scope.job_status = {};
- scope.job_id = job_id;
- scope.auto_scroll = false;
-
- scope.haltEventQueue = false;
- scope.processing = false;
- scope.lessStatus = false;
- scope.lessDetail = false;
- // pops the event summary panel open if we're in the host summary child state
- //scope.lessEvents = ($state.current.name === 'jobDetail.host-summary' || $state.current.name === 'jobDetail.host-events') ? false : true;
- if ($state.current.name === 'jobDetail.host-summary' ){
- scope.lessEvents = false;
- }
- else{
- scope.lessEvents = true;
- }
- scope.jobData = {};
- scope.jobData.hostSummaries = {};
-
- verbosity_options = [
- { value: 0, label: 'Default' },
- { value: 1, label: 'Verbose' },
- { value: 3, label: 'Debug' }
- ];
-
- job_type_options = [
- { value: 'run', label: 'Run' },
- { value: 'check', label: 'Check' }
- ];
-
- GetChoices({
- scope: scope,
- url: GetBasePath('unified_jobs'),
- field: 'status',
- variable: 'status_choices',
- });
-
- scope.eventsHelpText = " Successful
\n" +
- " Changed
\n" +
- " Unreachable
\n" +
- " Failed
\n";
-
- scope.$on(`ws-job_events-${job_id}`, function(e, data) {
- // update elapsed time on each event received
- scope.job_status.elapsed = GetElapsed({
- start: scope.job.created,
- end: Date.now()
- });
- if (api_complete && data.id > lastEventId) {
- scope.waiting = false;
- data.event = data.event_name;
- DigestEvent({ scope: scope, event: data });
- }
- UpdateDOM({ scope: scope });
- });
-
- scope.$on(`ws-jobs`, function(e, data) {
- // if we receive a status change event for the current job indicating the job
- // is finished, stop event queue processing and reload
- if (parseInt(data.unified_job_id, 10) === parseInt(job_id,10)) {
- if (data.status === 'failed' || data.status === 'canceled' ||
- data.status === 'error' || data.status === 'successful' || data.status === 'running') {
- $scope.liveEventProcessing = false;
- if (!scope.pauseLiveEvents) {
- $scope.$emit('LoadJob'); //this is what is used for the refresh
- }
- }
- }
- });
-
- scope.$on('ws-jobs-summary', function() {
- // the job host summary should now be available from the API
- $log.debug('Trigging reload of job_host_summaries');
- scope.$emit('InitialLoadComplete');
- });
-
- if (scope.removeInitialLoadComplete) {
- scope.removeInitialLoadComplete();
- }
- scope.removeInitialLoadComplete = scope.$on('InitialLoadComplete', function() {
- Wait('stop');
-
- if (JobIsFinished(scope)) {
- scope.liveEventProcessing = false; // signal that event processing is over and endless scroll
- scope.pauseLiveEvents = false; // should be enabled
- var params = {
- event: 'playbook_on_stats'
- };
- JobDetailService.getRelatedJobEvents(scope.job.id, params)
- .success(function() {
- UpdateDOM({ scope: scope });
- })
- .error(function(data, status) {
- ProcessErrors(scope, data, status, null, { hdr: 'Error!',
- msg: 'Call failed. GET returned: ' + status });
- });
- $log.debug('Job completed!');
- $log.debug(scope.jobData);
- }
- else {
- api_complete = true; //trigger events to start processing
- UpdateDOM({ scope: scope});
- }
- });
-
- if (scope.removeLoadHosts) {
- scope.removeLoadHosts();
- }
- scope.removeLoadHosts = scope.$on('LoadHosts', function() {
- if (scope.activeTask) {
-
- var play = scope.jobData.plays[scope.activePlay],
- task;
- if(play){
- task = play.tasks[scope.activeTask];
- }
- if (play && task) {
- var params = {
- parent: task.id,
- event__startswith: 'runner',
- page_size: scope.hostResultsMaxRows
- };
- JobDetailService.getRelatedJobEvents(scope.job.id, params)
- .success(function(data) {
- if (data.results.length > 0) {
- lastEventId = data.results[0].id;
- }
- scope.next_host_results = data.next;
- task.hostResults = JobDetailService.processHostEvents(data.results);
- scope.$emit('InitialLoadComplete');
- });
- } else {
- scope.$emit('InitialLoadComplete');
- }
- } else {
- scope.$emit('InitialLoadComplete');
- }
- });
-
- if (scope.removeLoadTasks) {
- scope.removeLoadTasks();
- }
- scope.removeLoadTasks = scope.$on('LoadTasks', function() {
- if (scope.activePlay) {
- var play = scope.jobData.plays[scope.activePlay];
-
- if (play) {
- var params = {
- event_id: play.id,
- page_size: scope.tasksMaxRows,
- order: 'id'
- };
- JobDetailService.getJobTasks(scope.job.id, params)
- .success(function(data) {
- scope.next_tasks = data.next;
- if (data.results.length > 0) {
- lastEventId = data.results[data.results.length - 1].id;
- if (scope.liveEventProcessing) {
- scope.activeTask = data.results[data.results.length - 1].id;
- }
- else {
- scope.activeTask = data.results[0].id;
- }
- scope.selectedTask = scope.activeTask;
- }
- data.results.forEach(function(event, idx) {
- var end, elapsed, status, status_text;
-
- if (play.firstTask === undefined || play.firstTask === null) {
- play.firstTask = event.id;
- play.hostCount = (event.host_count) ? event.host_count : 0;
- }
-
- if (idx < data.results.length - 1) {
- // end date = starting date of the next event
- end = data.results[idx + 1].created;
- }
- else {
- // no next event (task), get the end time of the play
- if(scope.jobData.plays[scope.activePlay]){
- end = scope.jobData.plays[scope.activePlay].finished;
- }
- }
-
- if (end) {
- elapsed = GetElapsed({
- start: event.created,
- end: end
- });
- }
- else {
- elapsed = '00:00:00';
- }
-
- status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful';
- status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK';
-
- play.tasks[event.id] = {
- id: event.id,
- play_id: scope.activePlay,
- name: event.name,
- status: status,
- status_text: status_text,
- status_tip: "Event ID: " + event.id + "
Status: " + status_text,
- created: event.created,
- modified: event.modified,
- finished: end,
- elapsed: elapsed,
- hostCount: (event.host_count) ? event.host_count : 0,
- reportedHosts: (event.reported_hosts) ? event.reported_hosts : 0,
- successfulCount: (event.successful_count) ? event.successful_count : 0,
- failedCount: (event.failed_count) ? event.failed_count : 0,
- changedCount: (event.changed_count) ? event.changed_count : 0,
- skippedCount: (event.skipped_count) ? event.skipped_count : 0,
- unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0,
- taskActiveClass: '',
- hostResults: {}
- };
- if (play.firstTask !== event.id) {
- // this is not the first task
- play.tasks[event.id].hostCount = play.tasks[play.firstTask].hostCount;
- }
- if (play.tasks[event.id].reportedHosts === 0 && play.tasks[event.id].successfulCount === 0 &&
- play.tasks[event.id].failedCount === 0 && play.tasks[event.id].changedCount === 0 &&
- play.tasks[event.id].skippedCount === 0 && play.tasks[event.id].unreachableCount === 0) {
- play.tasks[event.id].status = 'no-matching-hosts';
- play.tasks[event.id].status_text = 'No matching hosts';
- play.tasks[event.id].status_tip = "Event ID: " + event.id + "
Status: No matching hosts";
- }
- play.taskCount++;
- SetTaskStyles({
- task: play.tasks[event.id]
- });
- });
- if (scope.activeTask && scope.jobData.plays[scope.activePlay] && scope.jobData.plays[scope.activePlay].tasks[scope.activeTask]) {
- scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].taskActiveClass = 'JobDetail-tableRow--selected';
- }
- scope.$emit('LoadHosts');
- })
- .error(function(data) {
- ProcessErrors(scope, data, status, null, { hdr: 'Error!',
- msg: 'Call failed. GET returned: ' + status });
- });
- } else {
- scope.$emit('InitialLoadComplete');
- }
- } else {
- scope.$emit('InitialLoadComplete');
- }
- });
-
- if (scope.removeLoadPlays) {
- scope.removeLoadPlays();
- }
- scope.removeLoadPlays = scope.$on('LoadPlays', function(e, events_url) {
- scope.jobData.plays = {};
- var params = {
- order_by: 'id'
- };
-
- JobDetailService.getJobPlays(scope.job.id, params)
- .success( function(data) {
- scope.next_plays = data.next;
- if (data.results.length > 0) {
- lastEventId = data.results[data.results.length - 1].id;
- if (scope.liveEventProcessing) {
- scope.activePlay = data.results[data.results.length - 1].id;
- }
- else {
- scope.activePlay = data.results[0].id;
- }
- scope.selectedPlay = scope.activePlay;
- } else {
- // if we are here, there are no plays and the job has failed, let the user know they may want to consult stdout
- if ( (scope.job_status.status === 'failed' || scope.job_status.status === 'error') &&
- (!scope.job_status.explanation)) {
- scope.job_status.explanation = "See standard out for more details";
- }
- }
- data.results.forEach(function(event, idx) {
- var status, status_text, start, end, elapsed, ok, changed, failed, skipped;
-
- status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful';
- status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK';
- start = event.started;
-
- if (idx < data.results.length - 1) {
- // end date = starting date of the next event
- end = data.results[idx + 1].started;
- }
- else if (JobIsFinished(scope)) {
- // this is the last play and the job already finished
- end = scope.job_status.finished;
- }
- if (end) {
- elapsed = GetElapsed({
- start: start,
- end: end
- });
- }
- else {
- elapsed = '00:00:00';
- }
-
- scope.jobData.plays[event.id] = {
- id: event.id,
- name: event.play,
- created: start,
- finished: end,
- status: status,
- status_text: status_text,
- status_tip: "Event ID: " + event.id + "
Status: " + status_text,
- elapsed: elapsed,
- hostCount: 0,
- fistTask: null,
- taskCount: 0,
- playActiveClass: '',
- unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0,
- tasks: {}
- };
-
- ok = (event.ok_count) ? event.ok_count : 0;
- changed = (event.changed_count) ? event.changed_count : 0;
- failed = (event.failed_count) ? event.failed_count : 0;
- skipped = (event.skipped_count) ? event.skipped_count : 0;
-
- scope.jobData.plays[event.id].hostCount = ok + changed + failed + skipped;
-
- if (scope.jobData.plays[event.id].hostCount > 0 || event.unreachable_count > 0 || scope.job_status.status === 'successful' ||
- scope.job_status.status === 'failed' || scope.job_status.status === 'error' || scope.job_status.status === 'canceled') {
- // force the play to be on the 'active' list
- scope.jobData.plays[event.id].taskCount = 1;
- }
-
- if (scope.jobData.plays[event.id].hostCount === 0 && event.unreachable_count === 0) {
- scope.jobData.plays[event.id].status = 'no-matching-hosts';
- scope.jobData.plays[event.id].status_text = 'No matching hosts';
- scope.jobData.plays[event.id].status_tip = "Event ID: " + event.id + "
Status: No matching hosts";
- }
- });
- if (scope.activePlay && scope.jobData.plays[scope.activePlay]) {
- scope.jobData.plays[scope.activePlay].playActiveClass = 'JobDetail-tableRow--selected';
- }
- scope.$emit('LoadTasks', events_url);
- });
- });
-
-
- if (scope.removeLoadJob) {
- scope.removeLoadJob();
- }
- scope.removeLoadJobRow = scope.$on('LoadJob', function() {
- Wait('start');
- scope.job_status = {};
-
- scope.playsLoading = true;
- scope.tasksLoading = true;
- scope.hostResultsLoading = true;
-
- // Load the job record
- JobDetailService.getJob({id: job_id})
- .success(function(res) {
- var i,
- data = res.results[0];
- scope.job = data;
- scope.job_template_name = data.name;
- scope.project_name = (data.summary_fields.project) ? data.summary_fields.project.name : '';
- scope.inventory_name = (data.summary_fields.inventory) ? data.summary_fields.inventory.name : '';
- scope.job_template_url = '/#/templates/' + data.unified_job_template;
- scope.inventory_url = (scope.inventory_name && data.inventory) ? '/#/inventories/' + data.inventory : '';
- scope.project_url = (scope.project_name && data.project) ? '/#/projects/' + data.project : '';
- scope.credential_url = (data.credential) ? '/#/credentials/' + data.credential : '';
- scope.cloud_credential_url = (data.cloud_credential) ? '/#/credentials/' + data.cloud_credential : '';
- scope.playbook = data.playbook;
- scope.credential = data.credential;
- scope.cloud_credential = data.cloud_credential;
- scope.forks = data.forks;
- scope.limit = data.limit;
- scope.verbosity = data.verbosity;
- scope.job_tags = data.job_tags;
- scope.variables = ParseVariableString(data.extra_vars);
-
- // If we get created_by back from the server then use it. This means that the job was kicked
- // off by a user and not a schedule AND that the user still exists in the system.
- if(data.summary_fields.created_by) {
- scope.users_url = '/#/users/' + data.summary_fields.created_by.id;
- scope.created_by = data.summary_fields.created_by.username;
- }
- else {
- if(data.summary_fields.schedule) {
- // Build the Launched By link to point to the schedule that kicked it off
- scope.scheduled_by = (data.summary_fields.schedule.name) ? data.summary_fields.schedule.name.toString() : '';
- }
- // If there is no schedule or created_by then we can assume that the job was
- // created by a deleted user
- }
-
- if (data.summary_fields.credential) {
- scope.credential_name = data.summary_fields.credential.name;
- scope.credential_url = data.related.credential
- .replace('api/v1', '#');
- } else {
- scope.credential_name = "";
- }
-
- if (data.summary_fields.cloud_credential) {
- scope.cloud_credential_name = data.summary_fields.cloud_credential.name;
- scope.cloud_credential_url = data.related.cloud_credential
- .replace('api/v1', '#');
- } else {
- scope.cloud_credential_name = "";
- }
-
- if (data.summary_fields.network_credential) {
- scope.network_credential_name = data.summary_fields.network_credential.name;
- scope.network_credential_url = data.related.network_credential
- .replace('api/v1', '#');
- } else {
- scope.network_credential_name = "";
- }
-
- for (i=0; i < verbosity_options.length; i++) {
- if (verbosity_options[i].value === data.verbosity) {
- scope.verbosity = verbosity_options[i].label;
- }
- }
-
- for (i=0; i < job_type_options.length; i++) {
- if (job_type_options[i].value === data.job_type) {
- scope.job_type = job_type_options[i].label;
- }
- }
-
- // In the case the job is already completed, or an error already happened,
- // populate scope.job_status info
- scope.job_status.status = (data.status === 'waiting' || data.status === 'new') ? 'pending' : data.status;
- scope.job_status.started = data.started;
- scope.job_status.status_class = ((data.status === 'error' || data.status === 'failed') && data.job_explanation) ? "alert alert-danger" : "";
- scope.job_status.explanation = data.job_explanation;
- if(data.result_traceback) {
- scope.job_status.traceback = data.result_traceback.trim().split('\n').join('
');
- }
- if (data.status === 'successful' || data.status === 'failed' || data.status === 'error' || data.status === 'canceled') {
- scope.job_status.finished = data.finished;
- scope.liveEventProcessing = false;
- scope.pauseLiveEvents = false;
- scope.waiting = false;
- scope.playsLoading = false;
- scope.tasksLoading = false;
- scope.hostResultsLoading = false;
- }
- else {
- scope.job_status.finished = null;
- }
-
- if (data.started && data.finished) {
- scope.job_status.elapsed = GetElapsed({
- start: data.started,
- end: data.finished
- });
- }
- else {
- scope.job_status.elapsed = '00:00:00';
- }
- scope.status_choices.every(function(status) {
- if (status.value === scope.job.status) {
- scope.job_status.status_label = status.label;
- return false;
- }
- return true;
- });
- //scope.setSearchAll('host');
- ParseTypeChange({ scope: scope, field_id: 'pre-formatted-variables', readOnly: true });
- scope.$emit('LoadPlays', data.related.job_events);
- })
- .error(function(data, status) {
- ProcessErrors(scope, data, status, null, { hdr: 'Error!',
- msg: 'Failed to retrieve job: ' + $stateParams.id + '. GET returned: ' + status });
- });
- });
-
-
- if (scope.removeRefreshCompleted) {
- scope.removeRefreshCompleted();
- }
- scope.removeRefreshCompleted = scope.$on('RefreshCompleted', function() {
- refresh_count++;
- if (refresh_count === 1) {
- // First time. User just loaded page.
- scope.$emit('LoadJob');
- }
- });
-
- scope.adjustSize = function() {
- var height, ww = $(window).width();
- if (ww < 1024) {
- $('#job-summary-container').hide();
- $('#job-detail-container').css({ "width": "100%", "padding-right": "15px" });
- $('#summary-button').show();
- }
- else {
- $('.overlay').hide();
- $('#summary-button').hide();
- $('#hide-summary-button').hide();
- $('#job-summary-container .job_well').css({
- 'box-shadow': 'none',
- 'height': 'auto'
- });
- $('#job-summary-container').css({
- "width": "41.66666667%",
- "padding-left": "7px",
- "padding-right": "15px",
- "z-index": 0
- });
- setTimeout(function() { $('#job-summary-container .job_well').height($('#job-detail-container').height() - 18); }, 500);
- $('#job-summary-container').show();
- }
-
- scope.lessStatus = false; // close the view more status option
-
-
- height = $(window).height() - $('#main-menu-container .navbar').outerHeight() -
- $('#job-detail-container').outerHeight() - 20;
- scope.$emit('RefreshCompleted');
- };
-
- setTimeout(function() { scope.adjustSize(); }, 500);
-
- // Use debounce for the underscore library to adjust after user resizes window.
- $(window).resize(_.debounce(function(){
- scope.adjustSize();
- }, 500));
-
- function flashPlayTip() {
- setTimeout(function(){
- $('#play-help').popover('show');
- },500);
- setTimeout(function() {
- $('#play-help').popover('hide');
- }, 5000);
- }
-
- scope.selectPlay = function(id) {
- if (scope.liveEventProcessing && !scope.pauseLiveEvents) {
- scope.pauseLiveEvents = true;
- flashPlayTip();
- }
- SelectPlay({
- scope: scope,
- id: id
- });
- };
-
- scope.selectTask = function(id) {
- if (scope.liveEventProcessing && !scope.pauseLiveEvents) {
- scope.pauseLiveEvents = true;
- flashPlayTip();
- }
- SelectTask({
- scope: scope,
- id: id
- });
- };
-
- scope.togglePlayButton = function() {
- if (scope.pauseLiveEvents) {
- scope.pauseLiveEvents = false;
- scope.$emit('LoadJob');
- }
- };
-
- scope.objectIsEmpty = function(obj) {
- if (angular.isObject(obj)) {
- return (Object.keys(obj).length > 0) ? false : true;
- }
- return true;
- };
-
- scope.toggleLessEvents = function() {
- if (!scope.lessEvents) {
- $('#events-summary').slideUp(0);
- scope.lessEvents = true;
- }
- else {
- $('#events-summary').slideDown(0);
- scope.lessEvents = false;
- }
- };
-
- scope.toggleLessStatus = function() {
- if (!scope.lessStatus) {
- $('#job-status-form').slideUp(200);
- scope.lessStatus = true;
- }
- else {
- $('#job-status-form').slideDown(200);
- scope.lessStatus = false;
- }
- };
-
- scope.toggleLessDetail = function() {
- if (!scope.lessDetail) {
- $('#job-detail-details').slideUp(200);
- scope.lessDetail = true;
- }
- else {
- $('#job-detail-details').slideDown(200);
- scope.lessDetail = false;
- }
- };
-
- if (scope.removeDeleteFinished) {
- scope.removeDeleteFinished();
- }
- scope.removeDeleteFinished = scope.$on('DeleteFinished', function(e, action) {
- Wait('stop');
- if (action !== 'cancel') {
- Wait('stop');
- $location.url('/jobs');
- }
- });
-
- scope.deleteJob = function() {
- DeleteJob({
- scope: scope,
- id: scope.job.id,
- job: scope.job,
- callback: 'DeleteFinished'
- });
- };
-
- scope.relaunchJob = function() {
- RelaunchPlaybook({
- scope: scope,
- id: scope.job.id
- });
- };
-
- scope.playsScrollDown = function() {
- // check for more plays when user scrolls to bottom of play list...
- if (((!scope.liveEventProcessing) || (scope.liveEventProcessing && scope.pauseLiveEvents)) && scope.next_plays) {
- $('#playsMoreRows').fadeIn();
- scope.playsLoading = true;
- JobDetailService.getNextPage(scope.next_plays)
- .success( function(data) {
- scope.next_plays = data.next;
- data.results.forEach(function(event, idx) {
- var status, status_text, start, end, elapsed, ok, changed, failed, skipped;
-
- status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful';
- status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK';
- start = event.started;
-
- if (idx < data.results.length - 1) {
- // end date = starting date of the next event
- end = data.results[idx + 1].started;
- }
- else if (JobIsFinished(scope)) {
- // this is the last play and the job already finished
- end = scope.job_status.finished;
- }
- if (end) {
- elapsed = GetElapsed({
- start: start,
- end: end
- });
- }
- else {
- elapsed = '00:00:00';
- }
-
- scope.plays.push({
- id: event.id,
- name: event.play,
- created: start,
- finished: end,
- status: status,
- status_text: status_text,
- status_tip: "Event ID: " + event.id + "
Status: " + status_text,
- elapsed: elapsed,
- hostCount: 0,
- fistTask: null,
- playActiveClass: '',
- unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0,
- });
-
- ok = (event.ok_count) ? event.ok_count : 0;
- changed = (event.changed_count) ? event.changed_count : 0;
- failed = (event.failed_count) ? event.failed_count : 0;
- skipped = (event.skipped_count) ? event.skipped_count : 0;
-
- scope.plays[scope.plays.length - 1].hostCount = ok + changed + failed + skipped;
- scope.playsLoading = false;
- });
- $('#playsMoreRows').fadeOut(400);
- })
- .error( function(data, status) {
- ProcessErrors(scope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + scope.next_plays + '. GET returned: ' + status });
- });
- }
- };
-
- scope.tasksScrollDown = function() {
- // check for more tasks when user scrolls to bottom of task list...
- if (((!scope.liveEventProcessing) || (scope.liveEventProcessing && scope.pauseLiveEvents)) && scope.next_tasks) {
- $('#tasksMoreRows').fadeIn();
- scope.tasksLoading = true;
- JobDetailService.getNextPage(scope.next_tasks)
- .success(function(data) {
- scope.next_tasks = data.next;
- data.results.forEach(function(event, idx) {
- var end, elapsed, status, status_text;
- if (idx < data.results.length - 1) {
- // end date = starting date of the next event
- end = data.results[idx + 1].created;
- }
- else {
- // no next event (task), get the end time of the play
- scope.plays.every(function(p, j) {
- if (p.id === scope.selectedPlay) {
- end = scope.plays[j].finished;
- return false;
- }
- return true;
- });
- }
- if (end) {
- elapsed = GetElapsed({
- start: event.created,
- end: end
- });
- }
- else {
- elapsed = '00:00:00';
- }
-
- status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful';
- status_text = (event.failed) ? 'Failed' : (event.changed) ? 'Changed' : 'OK';
-
- scope.tasks.push({
- id: event.id,
- play_id: scope.selectedPlay,
- name: event.name,
- status: status,
- status_text: status_text,
- status_tip: "Event ID: " + event.id + "
Status: " + status_text,
- created: event.created,
- modified: event.modified,
- finished: end,
- elapsed: elapsed,
- hostCount: event.host_count, // hostCount,
- reportedHosts: event.reported_hosts,
- successfulCount: event.successful_count,
- failedCount: event.failed_count,
- changedCount: event.changed_count,
- skippedCount: event.skipped_count,
- taskActiveClass: ''
- });
- SetTaskStyles({
- task: scope.tasks[scope.tasks.length - 1]
- });
- });
- $('#tasksMoreRows').fadeOut(400);
- scope.tasksLoading = false;
- })
- .error(function(data, status) {
- $('#tasksMoreRows').fadeOut(400);
- ProcessErrors(scope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + scope.next_tasks + '. GET returned: ' + status });
- });
- }
- };
-
- scope.hostResultsScrollDown = function() {
- // check for more hosts when user scrolls to bottom of host results list...
- if (((!scope.liveEventProcessing) || (scope.liveEventProcessing && scope.pauseLiveEvents)) && scope.next_host_results) {
- $('#hostResultsMoreRows').fadeIn();
- scope.hostResultsLoading = true;
- JobDetailService.getNextPage(scope.next_host_results)
- .success(function(data) {
- scope.next_host_results = data.next;
- data.results.forEach(function(row) {
- var status, status_text, item, msg;
- if (row.event === "runner_on_skipped") {
- status = 'skipped';
- }
- else if (row.event === "runner_on_unreachable") {
- status = 'unreachable';
- }
- else {
- status = (row.failed) ? 'failed' : (row.changed) ? 'changed' : 'successful';
- }
- switch(status) {
- case "successful":
- status_text = 'OK';
- break;
- case "changed":
- status_text = "Changed";
- break;
- case "failed":
- status_text = "Failed";
- break;
- case "unreachable":
- status_text = "Unreachable";
- break;
- case "skipped":
- status_text = "Skipped";
- }
- if (row.event_data && row.event_data.res) {
- item = row.event_data.res.item;
- if (typeof item === "object") {
- item = JSON.stringify(item);
- }
- }
- msg = '';
- if (row.event_data && row.event_data.res) {
- if (typeof row.event_data.res === 'object') {
- msg = row.event_data.res.msg;
- } else {
- msg = row.event_data.res;
- }
- }
- scope.hostResults.push({
- id: row.id,
- status: status,
- status_text: status_text,
- host_id: row.host,
- task_id: row.parent,
- name: row.event_data.host,
- created: row.created,
- msg: (row.event_data && row.event_data.res) ? row.event_data.res.msg : '',
- item: item
- });
- scope.hostResultsLoading = false;
- });
- $('#hostResultsMoreRows').fadeOut(400);
- })
- .error(function(data, status) {
- $('#hostResultsMoreRows').fadeOut(400);
- ProcessErrors(scope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + scope.next_host_results + '. GET returned: ' + status });
- });
- }
- };
-
- scope.refresh = function(){
- $scope.$emit('LoadJob');
- };
-
- // Click binding for the expand/collapse button on the standard out log
- $scope.toggleStdoutFullscreen = function() {
- $scope.stdoutFullScreen = !$scope.stdoutFullScreen;
- };
-
- scope.editSchedule = function() {
- // We need to get the schedule's ID out of the related links
- // An example of the related schedule link looks like /api/v1/schedules/5
- // where 5 is the ID we are trying to capture
- var regex = /\/api\/v1\/schedules\/(\d+)\//;
- var id = scope.job.related.schedule.match(regex)[1];
-
- if(scope.job.job_template && id) {
- $state.go('jobTemplateSchedules.edit', {id: scope.job.job_template, schedule_id: id});
- }
- };
-
- // SchedulesRefresh is the callback string that we passed to the edit schedule modal
- // When the modal successfully updates the schedule it will emit this event and pass
- // the updated schedule object
- if (scope.removeSchedulesRefresh) {
- scope.removeSchedulesRefresh();
- }
- scope.$on('SchedulesRefresh', function(e, data) {
- if (data) {
- scope.scheduled_by = data.name;
- }
- });
- }
-];
diff --git a/awx/ui/client/src/job-detail/job-detail.partial.html b/awx/ui/client/src/job-detail/job-detail.partial.html
deleted file mode 100644
index bd0b488b18..0000000000
--- a/awx/ui/client/src/job-detail/job-detail.partial.html
+++ /dev/null
@@ -1,435 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1 Please select from a play below to view its associated tasks.
-
-
-
-
-
-
-
-
- | {{ play.name }} |
- {{ play.created | date: 'HH:mm:ss' }} |
- {{ play.elapsed }} |
-
-
-
- | Waiting... |
-
-
- | Loading... |
-
-
- | No matching plays |
-
-
-
-
-
-
-
-
-
-
-
-
2 Please select a task below to view its associated hosts
-
-
-
-
-
-
-
- | {{ task.name }} |
- {{ task.created | date: 'HH:mm:ss' }} |
- {{ task.elapsed }} |
-
-
-
- |
-
-
- | Waiting... |
-
-
- | Loading... |
-
-
- | No matching tasks |
-
-
-
-
-
-
-
-
-
-
3 Please select a host below to view associated task details.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/awx/ui/client/src/job-detail/job-detail.route.js b/awx/ui/client/src/job-detail/job-detail.route.js
deleted file mode 100644
index 94088c126b..0000000000
--- a/awx/ui/client/src/job-detail/job-detail.route.js
+++ /dev/null
@@ -1,91 +0,0 @@
-// <<<<<<< 4cf6a946a1aa14b7d64a8e1e8dabecfd3d056f27
-// //<<<<<<< bc59236851902d7c768aa26abdb7dc9c9dc27a5a
-// /*************************************************
-// * Copyright (c) 2016 Ansible, Inc.
-// *
-// * All Rights Reserved
-// *************************************************/
-//
-// // <<<<<<< a3d9eea2c9ddb4e16deec9ec38dea16bf37c559d
-// // import { templateUrl } from '../shared/template-url/template-url.factory';
-// //
-// // export default {
-// // name: 'jobDetail',
-// // url: '/jobs/{id: int}',
-// // ncyBreadcrumb: {
-// // parent: 'jobs',
-// // label: "{{ job.id }} - {{ job.name }}"
-// // },
-// // data: {
-// // socket: {
-// // "groups": {
-// // "jobs": ["status_changed", "summary"],
-// // "job_events": []
-// // }
-// // }
-// // },
-// // templateUrl: templateUrl('job-detail/job-detail'),
-// // controller: 'JobDetailController'
-// // };
-// // =======
-// // import {templateUrl} from '../shared/template-url/template-url.factory';
-// //
-// // export default {
-// // name: 'jobDetail',
-// // url: '/jobs/:id',
-// // ncyBreadcrumb: {
-// // parent: 'jobs',
-// // label: "{{ job.id }} - {{ job.name }}"
-// // },
-// // socket: {
-// // "groups":{
-// // "jobs": ["status_changed", "summary"],
-// // "job_events": []
-// // }
-// // },
-// // templateUrl: templateUrl('job-detail/job-detail'),
-// // controller: 'JobDetailController'
-// // };
-// //=======
-// =======
-// >>>>>>> Rebase of devel (w/ channels) + socket rework for new job details
-// // /*************************************************
-// // * Copyright (c) 2016 Ansible, Inc.
-// // *
-// // * All Rights Reserved
-// // *************************************************/
-// //
-// // import {templateUrl} from '../shared/template-url/template-url.factory';
-// //
-// // export default {
-// // name: 'jobDetail',
-// // url: '/jobs/:id',
-// // ncyBreadcrumb: {
-// // parent: 'jobs',
-// // label: "{{ job.id }} - {{ job.name }}"
-// // },
-// // socket: {
-// // "groups":{
-// // "jobs": ["status_changed", "summary"],
-// // "job_events": []
-// // }
-// // },
-// // resolve: {
-// // jobEventsSocket: ['Socket', '$rootScope', function(Socket, $rootScope) {
-// // if (!$rootScope.event_socket) {
-// // $rootScope.event_socket = Socket({
-// // scope: $rootScope,
-// // endpoint: "job_events"
-// // });
-// // $rootScope.event_socket.init();
-// // // returns should really be providing $rootScope.event_socket
-// // // otherwise, we have to inject the entire $rootScope into the controller
-// // return true;
-// // } else {
-// // return true;
-// // }
-// // }]
-// // },
-// // templateUrl: templateUrl('job-detail/job-detail'),
-// // controller: 'JobDetailController'
-// // };
diff --git a/awx/ui/client/src/job-detail/job-detail.service.js b/awx/ui/client/src/job-detail/job-detail.service.js
deleted file mode 100644
index 8e436a3e96..0000000000
--- a/awx/ui/client/src/job-detail/job-detail.service.js
+++ /dev/null
@@ -1,215 +0,0 @@
-export default
- ['$rootScope', 'Rest', 'GetBasePath', 'ProcessErrors', function($rootScope, Rest, GetBasePath, ProcessErrors){
- return {
- stringifyParams: function(params){
- return _.reduce(params, (result, value, key) => {
- return result + key + '=' + value + '&';
- }, '');
- },
-
- // the the API passes through Ansible's event_data response
- // we need to massage away the verbose & redundant stdout/stderr properties
- processJson: function(data){
- // configure fields to ignore
- var ignored = [
- 'type',
- 'event_data',
- 'related',
- 'summary_fields',
- 'url',
- 'ansible_facts',
- ];
- // remove ignored properties
- var result = _.chain(data).cloneDeep().forEach(function(value, key, collection){
- if (ignored.indexOf(key) > -1){
- delete collection[key];
- }
- }).value();
- return result;
- },
- // Return Ansible's passed-through response msg on a job_event
- processEventMsg: function(event){
- return typeof event.event_data.res === 'object' ? event.event_data.res.msg : event.event_data.res;
- },
- // Return only Ansible's passed-through response item on a job_event
- processEventItem: function(event){
- try{
- var item = event.event_data.res.item;
- return typeof item === 'object' ? JSON.stringify(item) : item;
- }
- catch(err){return;}
- },
- processsEventTip: function(event, status){
- try{
- var string = `Event ID: ${ event.id }
Status: ${ _.capitalize(status.status)}. Click for details`;
- return typeof item === 'object' ? JSON.stringify(string) : string;
- }
- catch(err){return;}
- },
- // Generate a helper class for job_event statuses
- // the stack for which status to display is
- // unreachable > failed > changed > ok
- // uses the API's runner events and convenience properties .failed .changed to determine status.
- // see: job_event_callback.py for more filters to support
- processEventStatus: function(event){
- if (event.event === 'runner_on_unreachable'){
- return {
- class: 'HostEvents-status--unreachable',
- status: 'unreachable'
- };
- }
- // equiv to 'runner_on_error' && 'runner on failed'
- if (event.failed){
- return {
- class: 'HostEvents-status--failed',
- status: 'failed'
- };
- }
- // catch the changed case before ok, because both can be true
- if (event.changed){
- return {
- class: 'HostEvents-status--changed',
- status: 'changed'
- };
- }
- if (event.event === 'runner_on_ok' || event.event === 'runner_on_async_ok'){
- return {
- class: 'HostEvents-status--ok',
- status: 'ok'
- };
- }
- if (event.event === 'runner_on_skipped'){
- return {
- class: 'HostEvents-status--skipped',
- status: 'skipped'
- };
- }
- },
- // Consumes a response from this.getRelatedJobEvents(id, params)
- // returns an array for view logic to iterate over to build host result rows
- processHostEvents: function(data){
- var self = this;
- var results = [];
- data.forEach(function(event){
- if (event.event !== 'runner_on_no_hosts'){
- var status = self.processEventStatus(event);
- var msg = self.processEventMsg(event);
- var item = self.processEventItem(event);
- var tip = self.processsEventTip(event, status);
- results.push({
- id: event.id,
- status: status.status,
- status_text: _.capitalize(status.status),
- host_id: event.host,
- task_id: event.parent,
- name: event.event_data.host,
- created: event.created,
- tip: typeof tip === 'undefined' ? undefined : tip,
- msg: typeof msg === 'undefined' ? undefined : msg,
- item: typeof item === 'undefined' ? undefined : item
- });
- }
- });
- return results;
- },
- // GET events related to a job run
- // e.g.
- // ?event=playbook_on_stats
- // ?parent=206&event__startswith=runner&page_size=200&order=host_name,counter
- getRelatedJobEvents: function(id, params){
- var url = GetBasePath('jobs');
- url = url + id + '/job_events/?' + this.stringifyParams(params);
- Rest.setUrl(url);
- return Rest.get()
- .success(function(data){
- return data;
- })
- .error(function(data, status) {
- ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + url + '. GET returned: ' + status });
- });
- },
- getJobEventChildren: function(uuid){
- var url = GetBasePath('job_events');
- url = `${url}?parent__uuid=${uuid}&order_by=host_name`;
- Rest.setUrl(url);
- return Rest.get()
- .success(function(data){
- return data;
- })
- .error(function(data, status) {
- ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + url + '. GET returned: ' + status });
- });
- },
- // GET job host summaries related to a job run
- // e.g. ?page_size=200&order=host_name
- getJobHostSummaries: function(id, params){
- var url = GetBasePath('jobs');
- url = url + id + '/job_host_summaries/?' + this.stringifyParams(params);
- Rest.setUrl(url);
- return Rest.get()
- .success(function(data){
- return data;
- })
- .error(function(data, status) {
- ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + url + '. GET returned: ' + status });
- });
- },
- // GET job plays related to a job run
- // e.g. ?page_size=200
- getJobPlays: function(id, params){
- var url = GetBasePath('jobs');
- url = url + id + '/job_plays/?' + this.stringifyParams(params);
- Rest.setUrl(url);
- return Rest.get()
- .success(function(data){
- return data;
- })
- .error(function(data, status) {
- ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + url + '. GET returned: ' + status });
- });
- },
- getJobTasks: function(id, params){
- var url = GetBasePath('jobs');
- url = url + id + '/job_tasks/?' + this.stringifyParams(params);
- Rest.setUrl(url);
- return Rest.get()
- .success(function(data){
- return data;
- })
- .error(function(data, status) {
- ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + url + '. GET returned: ' + status });
- });
- },
- getJob: function(params){
- var url = GetBasePath('unified_jobs') + '?' + this.stringifyParams(params);
- Rest.setUrl(url);
- return Rest.get()
- .success(function(data){
- return data;
- })
- .error(function(data, status) {
- ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + url + '. GET returned: ' + status });
- });
- },
- // GET next set of paginated results
- // expects 'next' param returned by the API e.g.
- // "/api/v1/jobs/51/job_plays/?order_by=id&page=2&page_size=1"
- getNextPage: function(url){
- Rest.setUrl(url);
- return Rest.get()
- .success(function(data){
- return data;
- })
- .error(function(data, status) {
- ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
- msg: 'Call to ' + url + '. GET returned: ' + status });
- });
- }
- };
- }];
diff --git a/awx/ui/client/src/job-detail/main.js b/awx/ui/client/src/job-detail/main.js
deleted file mode 100644
index 628f537e43..0000000000
--- a/awx/ui/client/src/job-detail/main.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*************************************************
- * Copyright (c) 2016 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
-// import route from './job-detail.route';
-import controller from './job-detail.controller';
-import service from './job-detail.service';
-import hostEvents from './host-events/main';
-// import hostEvent from './host-event/main';
-import hostSummary from './host-summary/main';
-
-export default
- angular.module('jobDetail', [
- hostEvents.name,
- // hostEvent.name,
- hostSummary.name
- ])
- .controller('JobDetailController', controller)
- .service('JobDetailService', service);
- // .run(['$stateExtender', function($stateExtender) {
- // $stateExtender.addState(route);
- // }]);
diff --git a/awx/ui/client/src/job-results/host-event/host-event-modal.partial.html b/awx/ui/client/src/job-results/host-event/host-event-modal.partial.html
index cf9dc67ac4..f8d488b4b3 100644
--- a/awx/ui/client/src/job-results/host-event/host-event-modal.partial.html
+++ b/awx/ui/client/src/job-results/host-event/host-event-modal.partial.html
@@ -9,7 +9,7 @@
{{event.host_name}}
-