Job detail page re-refactor

Fixed event viewer dialog to match old event viewer field groupings. Removed access to job_host_summaries and job_events.
This commit is contained in:
Chris Houseknecht 2014-07-09 04:39:01 -04:00
parent f223113cdc
commit eac4798c63
7 changed files with 133 additions and 217 deletions

View File

@ -60,14 +60,9 @@ angular.module('Tower', [
'CompletedJobsDefinition',
'RunningJobsDefinition',
'JobFormDefinition',
'JobEventsListDefinition',
'JobEventDataDefinition',
'JobEventsFormDefinition',
'JobHostDefinition',
'JobSummaryDefinition',
'ParseHelper',
'ChildrenHelper',
'EventsHelper',
'ProjectPathHelper',
'md5Helper',
'AccessHelper',
@ -132,21 +127,6 @@ angular.module('Tower', [
controller: 'JobStdoutController'
}).
when('/job_events/:id', {
templateUrl: urlPrefix + 'partials/job_events.html',
controller: 'JobEventsList'
}).
when('/job_host_summaries/:id', {
templateUrl: urlPrefix + 'partials/job_host_summaries.html',
controller: 'JobHostSummaryList'
}).
when('/jobs/:job_id/job_events/:event_id', {
templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobEventsEdit'
}).
when('/job_templates', {
templateUrl: urlPrefix + 'partials/job_templates.html',
controller: 'JobTemplatesList'
@ -197,11 +177,6 @@ angular.module('Tower', [
controller: 'OrganizationsAdd'
}).
when('/hosts/:id/job_host_summaries', {
templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobHostSummaryList'
}).
when('/inventories', {
templateUrl: urlPrefix + 'partials/inventories.html',
controller: 'InventoriesList'

View File

@ -0,0 +1,73 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* JobEventsForm.js
*
*/
angular.module('EventsViewerFormDefinition', [])
.value('EventsViewerForm', {
fields: {
status: {
label: 'Status',
section: 'Event'
},
id: {
label: 'ID',
section: 'Event'
},
created: {
label: 'Created On',
section: 'Event'
},
host_name: {
label: 'Host',
section: 'Event'
},
play: {
label: 'Play',
type: 'text',
section: 'Event'
},
task: {
label: 'Task',
section: 'Event'
},
role: {
label: 'Role',
section: 'Event'
},
rc: {
label: 'Return Code',
section: 'Results'
},
msg: {
label: 'Message',
section: 'Results'
},
results: {
label: 'Results',
section: 'Results'
},
start: {
label: 'Start',
section: 'Timing'
},
end: {
label: 'End',
section: 'Timing'
},
delta: {
label: 'Elapsed',
section: 'Timing'
},
module_name: {
label: 'Name',
section: 'Module'
},
module_args: {
label: 'Arguments',
section: 'Module'
}
}
});

View File

@ -1,144 +0,0 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* JobEventsForm.js
*
*/
angular.module('JobEventsFormDefinition', [])
.value('JobEventsForm', {
name: 'job_events',
well: false,
forceListeners: true,
fields: {
status: {
labelClass: 'job-{{ status }}',
type: 'custom',
section: 'Event',
control: "<div class=\"job-event-status job-{{ status }}\"><i class=\"fa icon-job-{{ status }}\"></i> {{ status }}</div>"
},
id: {
label: 'ID',
type: 'text',
readonly: true,
section: 'Event',
'class': 'span1'
},
created: {
label: 'Created On',
type: 'text',
section: 'Event',
readonly: true
},
host: {
label: 'Host',
type: 'text',
readonly: true,
section: 'Event',
ngShow: "host !== ''"
},
play: {
label: 'Play',
type: 'text',
readonly: true,
section: 'Event',
ngShow: "play !== ''"
},
task: {
label: 'Task',
type: 'text',
readonly: true,
section: 'Event',
ngShow: "task !== ''"
},
rc: {
label: 'Return Code',
type: 'text',
readonly: true,
section: 'Results',
'class': 'span1',
ngShow: "rc !== ''"
},
msg: {
label: 'Msg',
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'nowrap',
ngShow: "msg !== ''",
rows: 10
},
stdout: {
label: 'Standard Out',
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'nowrap',
ngShow: "stdout !== ''",
rows: 10
},
stderr: {
label: 'Standard Err',
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'nowrap',
ngShow: "stderr !== ''",
rows: 10
},
results: {
label: 'Results',
type: 'textarea',
section: 'Results',
readonly: true,
'class': 'nowrap',
ngShow: "results !== ''",
rows: 10
},
start: {
label: 'Start',
type: 'text',
readonly: true,
section: 'Timing',
ngShow: "start !== ''"
},
traceback: {
label: false,
type: 'textarea',
readonly: true,
section: 'Traceback',
'class': 'nowrap',
ngShow: "traceback !== ''",
rows: 10
},
end: {
label: 'End',
type: 'text',
readonly: true,
section: 'Timing',
ngShow: "end !== ''"
},
delta: {
label: 'Elapsed',
type: 'text',
readonly: true,
section: 'Timing',
ngShow: "delta !== ''"
},
module_name: {
label: 'Name',
type: 'text',
readonly: true,
section: 'Module',
ngShow: "module_name !== ''"
},
module_args: {
label: 'Args',
type: 'text',
readonly: true,
section: 'Module',
ngShow: "module_args !== ''"
}
}
});

View File

@ -7,7 +7,7 @@
'use strict';
angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'HostEventsViewerHelper'])
angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'EventsViewerFormDefinition'])
.factory('EventViewer', ['$compile', 'CreateDialog', 'GetEvent', 'Wait', 'EventAddTable', 'GetBasePath', 'LookUpName', 'Empty', 'EventAddPreFormattedText',
function($compile, CreateDialog, GetEvent, Wait, EventAddTable, GetBasePath, LookUpName, Empty, EventAddPreFormattedText) {
@ -32,17 +32,29 @@ angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'HostEventsView
var elem;
$('#status-form-container').empty();
$('#results-form-container').empty();
$('#timing-form-container').empty();
$('#stdout-form-container').empty();
$('#stderr-form-container').empty();
$('#traceback-form-container').empty();
$('#eventview-tabs li:eq(1)').hide();
$('#eventview-tabs li:eq(2)').hide();
$('#eventview-tabs li:eq(3)').hide();
$('#eventview-tabs li:eq(4)').hide();
$('#eventview-tabs li:eq(5)').hide();
EventAddTable({ scope: scope, id: 'status-form-container', event: data });
EventAddTable({ scope: scope, id: 'status-form-container', event: data, section: 'Event' });
if (EventAddTable({ scope: scope, id: 'results-form-container', event: data, section: 'Results'})) {
$('#eventview-tabs li:eq(1)').show();
}
if (EventAddTable({ scope: scope, id: 'timing-form-container', event: data, section: 'Timing' })) {
$('#eventview-tabs li:eq(2)').show();
}
if (data.stdout) {
$('#eventview-tabs li:eq(1)').show();
$('#eventview-tabs li:eq(3)').show();
EventAddPreFormattedText({
id: 'stdout-form-container',
val: data.stdout
@ -50,7 +62,7 @@ angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'HostEventsView
}
if (data.stderr) {
$('#eventview-tabs li:eq(2)').show();
$('#eventview-tabs li:eq(4)').show();
EventAddPreFormattedText({
id: 'stderr-form-container',
val: data.stderr
@ -58,7 +70,7 @@ angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'HostEventsView
}
if (data.traceback) {
$('#eventview-tabs li:eq(3)').show();
$('#eventview-tabs li:eq(5)').show();
EventAddPreFormattedText({
id: 'traceback-form-container',
val: data.traceback
@ -120,6 +132,7 @@ angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'HostEventsView
}
if (data.results[0].event_data.res.ansible_facts) {
// don't show fact gathering results
data.results[0].event_data.res.task = "Gathering Facts";
delete data.results[0].event_data.res.ansible_facts;
}
data.results[0].event_data.res.status = getStatus(data);
@ -143,13 +156,17 @@ angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'HostEventsView
}
delete event_data.invocation;
}
event_data.parent = data.results[0].parent;
event_data.play = data.results[0].play;
event_data.task = data.results[0].task;
if (data.results[0].task) {
event_data.task = data.results[0].task;
}
event_data.created = data.results[0].created;
event_data.role = data.results[0].role;
event_data.host_id = data.results[0].host;
event_data.host_name = data.results[0].host_name;
if (event_data.host) {
delete event_data.host;
}
event_data.id = data.results[0].id;
event_data.parent = data.results[0].parent;
event_data.event = (data.results[0].event_display) ? data.results[0].event_display : data.results[0].event;
@ -162,61 +179,47 @@ angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'HostEventsView
};
}])
.factory('EventAddTable', ['$compile', '$filter', 'Empty', function($compile, $filter, Empty) {
.factory('EventAddTable', ['$compile', '$filter', 'Empty', 'EventsViewerForm', function($compile, $filter, Empty, EventsViewerForm) {
return function(params) {
var scope = params.scope,
id = params.id,
event = params.event,
section = params.section,
html = '', e;
function keyToLabel(key) {
var label = '';
switch(key) {
case "id":
label = "Event ID";
break;
case "parent":
label = "Parent Event ID";
break;
case "rc":
label = "Return Code";
break;
default:
label = key.charAt(0).toUpperCase() + key.slice(1);
label = label.replace(/(\_.)/g, function(match) {
var res;
res = match.replace(/\_/,'');
res = ' ' + res.toUpperCase();
return res;
});
}
return label;
}
function parseJSON(obj) {
var html = '', keys;
var html = '', keys, found = false;
if (typeof obj === "object") {
html += "<table class=\"table eventviewer-status\">\n";
html += "<tbody>\n";
keys = Object.keys(obj).sort();
keys.forEach(function(key) {
var label;
if (key !== "stdout" && key !== "stderr" && key !== "traceback" && key !== "host_id" && key !== "host") {
label = keyToLabel(key);
if (EventsViewerForm.fields[key] && EventsViewerForm.fields[key].section === section) {
label = EventsViewerForm.fields[key].label;
if (Empty(obj[key])) {
// exclude empty items
}
else if (typeof obj[key] === "boolean" || typeof obj[key] === "number" || typeof obj[key] === "string") {
found = true;
html += "<tr><td class=\"key\">" + label + ":</td><td class=\"value\">";
if (key === "status") {
html += "<i class=\"fa icon-job-" + obj[key] + "\"></i> " + obj[key];
}
else if (key === "start" || key === "end" || key === "created") {
html += $filter('date')(obj[key], 'MM/dd/yy HH:mm:ss');
if (!/Z$/.test(obj[key])) {
//sec = parseInt(obj[key].substr(obj[key].length - 6, 6),10) / 1000);
//obj[key] = obj[key].replace(/\d{6}$/,sec) + 'Z';
obj[key] = obj[key].replace(/\ /,'T') + 'Z';
html += $filter('date')(obj[key], 'MM/dd/yy HH:mm:ss.sss');
}
else {
html += $filter('date')(obj[key], 'MM/dd/yy HH:mm:ss');
}
}
else if (key === "host_name") {
html += "<a href=\"#/home/hosts/?id=" + obj.host_id + "\" target=\"_blank\" " +
"aw-tool-tip=\"Click to view host.<br />Opens in new tab or window.\" data-placement=\"right\" " +
"aw-tool-tip=\"Click to edit host.\" data-placement=\"right\" " +
"ng-click=\"modalOK()\">" + obj[key] + "</a>";
}
else {
@ -226,6 +229,7 @@ angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'HostEventsView
html += "</td></tr>\n";
}
else if (typeof obj[key] === "object" && Array.isArray(obj[key])) {
found = true;
html += "<tr><td class=\"key\">" + label + ":</td><td class=\"value\">";
obj[key].forEach(function(row) {
html += "[" + row + "],";
@ -234,6 +238,7 @@ angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'HostEventsView
html += "</td></tr>\n";
}
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";
}
}
@ -241,12 +246,16 @@ angular.module('EventViewerHelper', ['ModalDialog', 'Utilities', 'HostEventsView
html += "</tbody>\n";
html += "</table>\n";
}
return html;
return (found) ? html : '';
}
html = parseJSON(event);
e = angular.element(document.getElementById(id));
e.empty().html(html);
$compile(e)(scope);
e.empty();
if (html) {
e.html(html);
$compile(e)(scope);
}
return (html) ? true : false;
};
}])

View File

@ -24,6 +24,7 @@ table.eventviewer-status {
margin-top: 20px;
.key {
width: 20%;
font-weight: bold;
}
.value i {

View File

@ -1,6 +1,8 @@
<div id="eventviewer-modal-dialog" title="Log View" style="display: none;">
<ul id="eventview-tabs" class="nav nav-tabs">
<li class="active"><a href="#status" id="status-link" data-toggle="tab" ng-click="toggleTab($event, 'status-link', 'eventview-tabs')">Status</a></li>
<li class="active"><a href="#status" id="status-link" data-toggle="tab" ng-click="toggleTab($event, 'status-link', 'eventview-tabs')">Event</a></li>
<li><a href="#results" id="results-link" data-toggle="tab" ng-click="toggleTab($event, 'results-link', 'eventview-tabs')">Results</a></li>
<li><a href="#timing" id="timing-link" data-toggle="tab" ng-click="toggleTab($event, 'timing-link', 'eventview-tabs')">Timing</a></li>
<li><a href="#stdout" id="stdout-link" data-toggle="tab" ng-click="toggleTab($event, 'stdout-link', 'eventview-tabs')">Standard Out</a></li>
<li><a href="#stderr" id="stderr-link" data-toggle="tab" ng-click="toggleTab($event, 'stderr-link', 'eventview-tabs')">Standard Error</a></li>
<li><a href="#traceback" id="traceback-link" data-toggle="tab" ng-click="toggleTab($event, 'traceback-link', 'eventview-tabs')">Traceback</a></li>
@ -9,6 +11,12 @@
<div class="tab-pane active" id="status">
<div id="status-form-container"></div>
</div>
<div class="tab-pane" id="results">
<div id="results-form-container"></div>
</div>
<div class="tab-pane" id="timing">
<div id="timing-form-container"></div>
</div>
<div class="tab-pane" id="stdout">
<div id="stdout-form-container"></div>
</div>

View File

@ -78,8 +78,6 @@
<script src="{{ STATIC_URL }}js/controllers/Projects.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Jobs.js"></script>
<script src="{{ STATIC_URL }}js/controllers/JobDetail.js"></script>
<script src="{{ STATIC_URL }}js/controllers/JobEvents.js"></script>
<script src="{{ STATIC_URL }}js/controllers/JobHosts.js"></script>
<script src="{{ STATIC_URL }}js/controllers/JobTemplates.js"></script>
<script src="{{ STATIC_URL }}js/controllers/JobStdout.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Permissions.js"></script>
@ -98,8 +96,7 @@
<script src="{{ STATIC_URL }}js/forms/Projects.js"></script>
<script src="{{ STATIC_URL }}js/forms/ProjectStatus.js"></script>
<script src="{{ STATIC_URL }}js/forms/Permissions.js"></script>
<script src="{{ STATIC_URL }}js/forms/JobEventData.js"></script>
<script src="{{ STATIC_URL }}js/forms/JobEvents.js"></script>
<script src="{{ STATIC_URL }}js/forms/EventsViewer.js"></script>
<script src="{{ STATIC_URL }}js/forms/HostGroups.js"></script>
<script src="{{ STATIC_URL }}js/forms/ActivityDetail.js"></script>
<script src="{{ STATIC_URL }}js/forms/JobSummary.js"></script>
@ -122,8 +119,6 @@
<script src="{{ STATIC_URL }}js/lists/CompletedJobs.js"></script>
<script src="{{ STATIC_URL }}js/lists/RunningJobs.js"></script>
<script src="{{ STATIC_URL }}js/lists/QueuedJobs.js"></script>
<script src="{{ STATIC_URL }}js/lists/JobEvents.js"></script>
<script src="{{ STATIC_URL }}js/lists/JobHosts.js"></script>
<script src="{{ STATIC_URL }}js/lists/Permissions.js"></script>
<script src="{{ STATIC_URL }}js/lists/Streams.js"></script>
<script src="{{ STATIC_URL }}js/lists/HomeGroups.js"></script>
@ -142,7 +137,6 @@
<script src="{{ STATIC_URL }}js/helpers/JobSubmission.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Lookup.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Parse.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Events.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Children.js"></script>
<script src="{{ STATIC_URL }}js/helpers/ProjectPath.js"></script>
<script src="{{ STATIC_URL }}js/helpers/md5.js"></script>