mirror of
https://github.com/ansible/awx.git
synced 2026-01-13 02:50:02 -03:30
Job detail page refactoration
Handling play and task parallel arrival seems to be working now. Removed 'search' and 'status' labels from search dialogs. Job events viewer now displays JSON objects as nested tables. Re-ordered host event viewer fields, adding host name, and fixing links so that only the status column is clickable.
This commit is contained in:
parent
a35cd2d85e
commit
78cec19e78
@ -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'
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -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'
|
||||
|
||||
@ -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 += "<tr><td class=\"key\">" + key + ":</td><td class=\"value\">" + obj[key] + "</td></tr>";
|
||||
}
|
||||
else if (typeof obj[key] === "object" && Array.isArray(obj[key])) {
|
||||
html += "<tr><td class=\"key\">" + key + ":</td><td class=\"value\">";
|
||||
obj[key].forEach(function(row) {
|
||||
html += "[" + row + "],";
|
||||
});
|
||||
html = html.replace(/,$/,'');
|
||||
html += "</td></tr>\n";
|
||||
}
|
||||
else if (typeof obj[key] === "object") {
|
||||
html += "<tr><td class=\"key\">" + key + ":</td><td class=\"nested-table\"><table>\n<tbody>\n" + parseObject(obj[key]) + "</tbody>\n</table>\n</td></tr>\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 += "<tr><td class=\"key\">" + label + ":</td><td class=\"nested-table\">\n" + parseJSON(obj[key]) + "</td></tr>\n";
|
||||
html += "<tr><td class=\"key\">" + label + ":</td><td class=\"nested-table\"><table>\n<tbody>\n" + parseObject(obj[key]) + "</tbody>\n</table>\n</td></tr>\n";
|
||||
}
|
||||
//}
|
||||
});
|
||||
html += "</tbody>\n";
|
||||
html += "</table>\n";
|
||||
|
||||
@ -114,11 +114,11 @@ angular.module('HostEventsViewerHelper', ['ModalDialog', 'Utilities', 'EventView
|
||||
|
||||
buildRow = function(res) {
|
||||
var html = '';
|
||||
html += "<tr ng-click=\"showDetails(" + res.id + ")\" class=\"cursor-pointer\" aw-tool-tip=\"Click to view details\" data-placement=\"top\">\n";
|
||||
html += "<td class=\"col-md-3\"><i class=\"fa icon-job-" + res.status + "\"></i> <a href=\"\">" + res.status_text + "</a></td>\n";
|
||||
html += "<td class=\"col-md-3\"><a href=\"\">" + res.play + "</a></td>\n";
|
||||
html += "<td class=\"col-md-3\"><a href=\"\">" + res.task + "</a></td>\n";
|
||||
html += "<td class=\"col-md-3\"><a href=\"\">" + res.msg + "</a></td>";
|
||||
html += "<tr>\n";
|
||||
html += "<td class=\"col-md-3\"><a href=\"\" ng-click=\"showDetails(" + res.id + ")\" aw-tool-tip=\"Click to view details\" data-placement=\"top\"><i class=\"fa icon-job-" + res.status + "\"></i> " + res.status_text + "</a></td>\n";
|
||||
html += "<td class=\"col-md=3\">" + res.host_name + "</td>\n";
|
||||
html += "<td class=\"col-md-3\">" + res.play + "</td>\n";
|
||||
html += "<td class=\"col-md-3\">" + res.task + "</td>\n";
|
||||
html += "</tr>";
|
||||
return html;
|
||||
};
|
||||
|
||||
@ -295,7 +295,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
status_tip: "Event ID: " + event.id + "<br />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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -81,7 +81,6 @@
|
||||
<div class="col-lg-11 col-md-10 col-sm-10 col-xs-11" style="text-align:right;">
|
||||
<div id="play-search-form" class="search-form form-inline">
|
||||
<div class="form-group">
|
||||
<label>Search</label>
|
||||
<div class="search-name" style="display:inline-block; position:relative;">
|
||||
<input type="text" class="input-xs form-control" id="search_play_name" ng-model="search_play_name"
|
||||
placeholder="Play Name" ng-keypress="searchPlaysKeyPress($event)" >
|
||||
@ -92,7 +91,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Status</label>
|
||||
<div class="btn-group" aw-toggle-button data-after-toggle="filterPlayStatus">
|
||||
<button class="btn btn-xs btn-primary active">All</button>
|
||||
<button class="btn btn-xs btn-default">Failed</button>
|
||||
@ -141,7 +139,6 @@
|
||||
<div class="col-lg-11 col-md-10 col-sm-10" style="text-align:right;">
|
||||
<div id="task-search-form" class="search-form form-inline">
|
||||
<div class="form-group">
|
||||
<label>Search</label>
|
||||
<div class="search-name" style="display:inline-block; position:relative;">
|
||||
<input type="text" class="input-xs form-control" id="search_task_name" ng-model="search_task_name"
|
||||
placeholder="Task Name" ng-keypress="searchTasksKeyPress($event)" >
|
||||
@ -152,7 +149,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Status</label>
|
||||
<div class="btn-group" aw-toggle-button data-after-toggle="filterTaskStatus">
|
||||
<button class="btn btn-xs btn-primary active">All</button>
|
||||
<button class="btn btn-xs btn-default">Failed</button>
|
||||
@ -204,7 +200,6 @@
|
||||
<div class="col-lg-10 col-md-10 col-sm-10" style="text-align:right;">
|
||||
<div id="host-search-form" class="search-form form-inline">
|
||||
<div class="form-group">
|
||||
<label>Search</label>
|
||||
<div class="search-name" style="display:inline-block; position:relative;">
|
||||
<input type="text" class="input-xs form-control" id="search_host_name" ng-model="search_host_name"
|
||||
placeholder="Host Name" ng-keypress="searchHostsKeyPress($event)" >
|
||||
@ -215,7 +210,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Status</label>
|
||||
<div class="btn-group" aw-toggle-button data-after-toggle="filterHostStatus">
|
||||
<button class="btn btn-xs btn-primary active">All</button>
|
||||
<button class="btn btn-xs btn-default">Failed</button>
|
||||
@ -277,7 +271,6 @@
|
||||
<div class="col-lg-10 col-md-10 col-sm-10" style="text-align:right;">
|
||||
<div id="task-search-form" class="search-form form-inline">
|
||||
<div class="form-group">
|
||||
<label>Search</label>
|
||||
<div class="search-name" style="display:inline-block; position:relative;">
|
||||
<input type="text" class="input-xs form-control" id="search_host_summary_name" ng-model="search_host_summary_name"
|
||||
placeholder="Host Name" ng-keypress="searchHostSummaryKeyPress($event)" >
|
||||
@ -288,7 +281,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Status</label>
|
||||
<div class="btn-group" aw-toggle-button data-after-toggle="filterHostSummaryStatus">
|
||||
<button class="btn btn-xs btn-primary active">All</button>
|
||||
<button class="btn btn-xs btn-default">Failed</button>
|
||||
@ -385,9 +377,9 @@
|
||||
<table id="fixed-table-header" class="table">
|
||||
<thead>
|
||||
<tr><th class="col-md-3">Status</th>
|
||||
<th class="col-md-3">Host</th>
|
||||
<th class="col-md-3">Play</th>
|
||||
<th class="col-md-3">Task</th>
|
||||
<th class="col-md-3">Result</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user