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