diff --git a/awx/ui/static/js/controllers/JobDetail.js b/awx/ui/static/js/controllers/JobDetail.js index a5d0b70a90..b6e7dc4531 100644 --- a/awx/ui/static/js/controllers/JobDetail.js +++ b/awx/ui/static/js/controllers/JobDetail.js @@ -828,7 +828,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar EventViewer({ scope: scope, url: scope.job.related.job_events + '?id=' + id, - title: 'Host Result' + title: 'Host Event' }); }; diff --git a/awx/ui/static/js/forms/EventsViewer.js b/awx/ui/static/js/forms/EventsViewer.js index 10292f6c4c..c97eaf2362 100644 --- a/awx/ui/static/js/forms/EventsViewer.js +++ b/awx/ui/static/js/forms/EventsViewer.js @@ -37,6 +37,10 @@ angular.module('EventsViewerFormDefinition', []) label: 'Task', section: 'Event' }, + item: { + label: 'Item', + section: 'Event' + }, module_name: { label: 'Module', section: 'Event' @@ -45,10 +49,6 @@ angular.module('EventsViewerFormDefinition', []) label: 'Arguments', section: 'Event' }, - item: { - label: 'Item', - section: 'Event' - }, rc: { label: 'Return Code', section: 'Results' diff --git a/awx/ui/static/js/helpers/EventViewer.js b/awx/ui/static/js/helpers/EventViewer.js index 8d4f82f3d6..6afa3804d6 100644 --- a/awx/ui/static/js/helpers/EventViewer.js +++ b/awx/ui/static/js/helpers/EventViewer.js @@ -195,6 +195,28 @@ angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'EventsViewerFo section = params.section, html = '', e; + function parseObject(obj) { + // parse nested JSON objects. a mini version of parseJSON without references to the event form object. + var key, html = ''; + for (key in obj) { + if (typeof obj[key] === "boolean" || typeof obj[key] === "number" || typeof obj[key] === "string") { + html += "" + key + ":" + obj[key] + ""; + } + else if (typeof obj[key] === "object" && Array.isArray(obj[key])) { + html += "" + key + ":"; + obj[key].forEach(function(row) { + html += "[" + row + "],"; + }); + html = html.replace(/,$/,''); + html += "\n"; + } + else if (typeof obj[key] === "object") { + html += "" + key + ":\n\n" + parseObject(obj[key]) + "\n
\n\n"; + } + } + return html; + } + function parseJSON(obj) { var html = '', key, keys, found = false; if (typeof obj === "object") { @@ -252,9 +274,8 @@ angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'EventsViewerFo } else if (typeof obj[key] === "object") { found = true; - html += "" + label + ":\n" + parseJSON(obj[key]) + "\n"; + html += "" + label + ":\n\n" + parseObject(obj[key]) + "\n
\n\n"; } - //} }); html += "\n"; html += "\n"; diff --git a/awx/ui/static/js/helpers/HostEventsViewer.js b/awx/ui/static/js/helpers/HostEventsViewer.js index f49f244653..2294f7ab5d 100644 --- a/awx/ui/static/js/helpers/HostEventsViewer.js +++ b/awx/ui/static/js/helpers/HostEventsViewer.js @@ -114,11 +114,11 @@ angular.module('HostEventsViewerHelper', ['ModalDialog', 'Utilities', 'EventView buildRow = function(res) { var html = ''; - html += "\n"; - html += " " + res.status_text + "\n"; - html += "" + res.play + "\n"; - html += "" + res.task + "\n"; - html += "" + res.msg + ""; + html += "\n"; + html += " " + res.status_text + "\n"; + html += "" + res.host_name + "\n"; + html += "" + res.play + "\n"; + html += "" + res.task + "\n"; html += ""; return html; }; diff --git a/awx/ui/static/js/helpers/JobDetail.js b/awx/ui/static/js/helpers/JobDetail.js index 453c355a14..32ee13ac0f 100644 --- a/awx/ui/static/js/helpers/JobDetail.js +++ b/awx/ui/static/js/helpers/JobDetail.js @@ -295,7 +295,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge status_tip: "Event ID: " + event.id + "
Status: " + status_text, created: event.created, modified: event.modified, - hostCount: (scope.activePlay && scope.jobData.plays[scope.activePlay]) ? scope.jobData.plays[scope.activePlay].hostCount : 0, + hostCount: (scope.jobData.plays[event.parent]) ? scope.jobData.plays[event.parent].hostCount : 0, reportedHosts: 0, successfulCount: 0, failedCount: 0, @@ -451,8 +451,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge }]) // Each time a runner event is received update host summary totals and the parent task -.factory('UpdateHostStatus', ['UpdateTaskStatus', 'AddHostResult', - function(UpdateTaskStatus, AddHostResult) { +.factory('UpdateHostStatus', ['UpdateTaskStatus', 'AddHostResult', function(UpdateTaskStatus, AddHostResult) { return function(params) { var scope = params.scope, status = params.status, // successful, changed, unreachable, failed, skipped @@ -516,7 +515,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge }]) // Add a new host result -.factory('AddHostResult', ['SetTaskStyles', 'SetActiveTask', function(SetTaskStyles, SetActiveTask) { +.factory('AddHostResult', ['SetTaskStyles', 'SetActivePlay', 'SetActiveTask', function(SetTaskStyles, SetActivePlay, SetActiveTask) { return function(params) { var scope = params.scope, task_id = params.task_id, @@ -528,7 +527,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge msg = params.message, item = params.item, status_text = '', - task; + task, play, play_id; switch(status) { case "successful": @@ -551,11 +550,16 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge item = JSON.stringify(item); } - if (scope.jobData.plays[scope.activePlay].tasks[task_id].hostResults[event_id]) { - // host already exists. do nothing. + 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); + } + } } - else { - scope.jobData.plays[scope.activePlay].tasks[task_id].hostResults[event_id] = { + + if (play_id) { + scope.jobData.plays[play_id].tasks[task_id].hostResults[event_id] = { id: event_id, status: status, status_text: status_text, @@ -568,15 +572,15 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge }; // increment the unreachable count on the play - if (status === 'unreachable' && scope.jobData.plays[scope.activePlay]) { - scope.jobData.plays[scope.activePlay].unreachableCount++; + if (status === 'unreachable') { + scope.jobData.plays[play_id].unreachableCount++; } // update the task status bar - task = scope.jobData.plays[scope.activePlay].tasks[task_id]; + task = scope.jobData.plays[play_id].tasks[task_id]; - if (task_id === scope.jobData.plays[scope.activePlay].firstTask) { - scope.jobData.plays[scope.activePlay].hostCount++; + if (task_id === scope.jobData.plays[play_id].firstTask) { + scope.jobData.plays[play_id].hostCount++; task.hostCount++; } @@ -591,6 +595,8 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge task: task }); + SetActivePlay({ scope: scope }); + SetActiveTask({ scope: scope }); } }; @@ -609,6 +615,14 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge 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) { diff --git a/awx/ui/static/less/event-viewer.less b/awx/ui/static/less/event-viewer.less index ef980ce2f5..2a4fc4d0ff 100644 --- a/awx/ui/static/less/event-viewer.less +++ b/awx/ui/static/less/event-viewer.less @@ -30,4 +30,31 @@ table.eventviewer-status { .value i { font-size: 12px; } +} + +.nested-table { + border: none; + padding: 0; + table { + border-top: none; + border-bottom: none; + width: auto; + td { + vertical-align: top; + padding: 0 3px 3px 3px; + } + tr { + border-top: none; + border-bottom: 1px solid #ddd; + } + /*tr td:first-of-type { + width: auto; + }*/ + tr:last-of-type { + border-bottom: none; + } + .key { + font-weight: 400; + } + } } \ No newline at end of file diff --git a/awx/ui/static/less/job-details.less b/awx/ui/static/less/job-details.less index 422602924a..c8ceb5e05e 100644 --- a/awx/ui/static/less/job-details.less +++ b/awx/ui/static/less/job-details.less @@ -506,66 +506,6 @@ font-weight: bold; } - #event-viewer-dialog { - padding-bottom: 5px; - padding-top: 10px; - padding-left: 5px; - padding-right: 5px; - overflow: hidden; - .results { - width: 100%; - height: 100%; - overflow: auto; - } - .spacer { - height: 60px; - } - table { - border-collapse: collapse; - width: 100%; - border-bottom: 1px solid @well-border; - } - tr { - border-top: 1px solid @well-border; - /*border-bottom: 1px solid @well-border;*/ - } - tr:first-child { - border-top: none; - } - tr td:first-of-type { - width: 20%; - } - .key { - vertical-align: top; - padding: 3px; - font-weight: 600; - } - .value { - padding: 3px; - i { - font-size: 12px; - } - } - .nested-table { - border: none; - padding: 0; - table { - border-top: none; - border-bottom: none; - width: auto; - tr { - border-top: none; - } - tr td:first-of-type { - width: auto; - } - .key { - font-weight: 400; - } - } - } - } - .footer-row { height: 20px; } diff --git a/awx/ui/static/partials/job_detail.html b/awx/ui/static/partials/job_detail.html index 05cd69c0b4..7825c3046a 100644 --- a/awx/ui/static/partials/job_detail.html +++ b/awx/ui/static/partials/job_detail.html @@ -81,7 +81,6 @@
-
@@ -92,7 +91,6 @@
-
@@ -141,7 +139,6 @@
-
@@ -152,7 +149,6 @@
-
@@ -204,7 +200,6 @@
-
@@ -215,7 +210,6 @@
-
@@ -277,7 +271,6 @@
-
@@ -288,7 +281,6 @@
-
@@ -385,9 +377,9 @@ + -
StatusHost Play TaskResult