AC-216 Job events detail, 2nd iteration.

This commit is contained in:
chouseknecht 2013-07-16 17:33:11 -04:00
parent f70dcf8dbb
commit aac2d0955e
7 changed files with 197 additions and 109 deletions

View File

@ -51,6 +51,7 @@ angular.module('ansible', [
'JobFormDefinition',
'JobEventsListDefinition',
'JobEventFormDefinition',
'JobModalEventDefinition',
'JobHostDefinition',
'GroupsHelper',
'HostsHelper',

View File

@ -12,7 +12,7 @@
function JobEventsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobEventList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, GetBasePath, LookUpInit, ToggleChildren, EventView,
ClearScope, ProcessErrors, GetBasePath, LookUpInit, ToggleChildren,
FormatDate)
{
ClearScope('htmlTemplate');
@ -153,7 +153,7 @@ function JobEventsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
LoadBreadCrumbs();
scope.viewJobEvent = function(id) {
EventView({"event_id": id });
$location.path('/jobs/' + $routeParams.id + '/job_events/' + id);
}
scope.refresh = function() {
@ -173,15 +173,14 @@ function JobEventsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
JobEventsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobEventList',
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
'ProcessErrors','GetBasePath', 'LookUpInit', 'ToggleChildren', 'EventView', 'FormatDate'
'ProcessErrors','GetBasePath', 'LookUpInit', 'ToggleChildren', 'FormatDate'
];
function JobEventsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventForm, GenerateForm,
Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, FormatDate)
Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, FormatDate, EventView)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
// Inject dynamic view
var form = JobEventForm;
var generator = GenerateForm;
@ -195,35 +194,82 @@ function JobEventsEdit ($scope, $rootScope, $compile, $location, $log, $routePar
Rest.setUrl(defaultUrl);
Rest.get()
.success( function(data, status, headers, config) {
LoadBreadCrumbs({ path: '/job_events/' + $routeParams.event_id, title: data.event });
for (var fld in form.fields) {
if (fld == 'status') {
scope['status'] = (data.failed) ? 'error' : 'success';
}
else if (fld == 'event_data') {
scope['event_data'] = JSON.stringify(data['event_data'], undefined, '\t');
}
else {
if (fld == 'created') {
scope['event_display'] = data['event_display'].replace(/^\u00a0*/g,'');
LoadBreadCrumbs({ path: '/jobs/' + $routeParams.job_id + '/job_events/' + $routeParams.event_id,
title: scope['event_display'] });
for (var fld in form.fields) {
switch(fld) {
case 'status':
if (data['failed']) {
scope['status'] = 'error';
}
else if (data['changed']) {
scope['status'] = 'changed';
}
else {
scope['status'] = 'success';
}
break;
case 'created':
var cDate = new Date(data['created']);
scope['created'] = FormatDate(cDate);
}
else {
if (data[fld]) {
scope[fld] = data[fld];
break;
case 'host':
if (data['summary_fields'] && data['summary_fields']['host']) {
scope['host'] = data['summary_fields']['host']['name'];
}
break;
case 'id':
case 'task':
scope[fld] = data[fld];
break;
case 'msg':
case 'stdout':
case 'stderr':
case 'start':
case 'end':
case 'delta':
case 'rc':
if (data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] !== undefined) {
scope[fld] = data['event_data']['res'][fld];
if (form.fields[fld].type == 'textarea') {
var n = data['event_data']['res'][fld].match(/\n/g);
rows = (n) ? n.length : 1;
rows = (rows > 15) ? 5 : rows;
$('textarea[name="' + fld + '"]').attr('rows',rows);
}
}
}
}
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve event detail: ' + $routeParams.event_id + '. GET status: ' + status });
});
break;
case 'conditional':
if (data['event_data']['res']) {
scope[fld] = data['event_data']['res']['is_conditional'];
}
break;
case 'module_name':
case 'module_args':
if (data['event_data']['res'] && data['event_data']['res']['invocation']) {
scope[fld] = data['event_data']['res']['invocation'][fld];
}
break;
}
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve host: ' + $routeParams.event_id + '. GET status: ' + status });
});
scope.navigateBack = function() {
window.history.back();
}
scope.rawView = function() {
EventView({"event_id": scope.id });
}
}
JobEventsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobEventForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath',
'FormatDate'
'FormatDate', 'EventView'
];

View File

@ -10,9 +10,8 @@ angular.module('JobEventFormDefinition', [])
.value(
'JobEventForm', {
editTitle: '{{ id }} - {{ event }}', //Legend in edit mode
editTitle: '{{ id }} - {{ event_display }}', //Legend in edit mode
name: 'job_events',
"class": 'horizontal-narrow',
well: false,
fields: {
@ -66,7 +65,7 @@ angular.module('JobEventFormDefinition', [])
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'modal-input-xlarge',
'class': 'span12',
rows: 1
},
stdout: {
@ -74,7 +73,7 @@ angular.module('JobEventFormDefinition', [])
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'modal-input-xlarge',
'class': 'span12',
rows: 1
},
stderr: {
@ -82,7 +81,7 @@ angular.module('JobEventFormDefinition', [])
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'modal-input-xlarge',
'class': 'span12',
rows: 1
},
start: {
@ -117,8 +116,31 @@ angular.module('JobEventFormDefinition', [])
}
},
buttons: {
navigation: {
back_top: {
label: 'Back',
position: 'top',
'class': 'btn-small pull-right',
icon: 'icon-arrow-left',
ngClick: 'navigateBack()'
},
back_bottom: {
label: 'Back',
position: 'bottom',
'class': 'btn-small pull-right',
icon: 'icon-arrow-left',
ngClick: 'navigateBack()'
},
raw_view: {
label: 'View raw JSON results',
icon: 'icon-zoom-in',
position: 'bottom',
'class': 'btn-small',
ngClick: 'rawView()'
}
},
buttons: {
},
related: { //related colletions (and maybe items?)

View File

@ -0,0 +1,35 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* JobModalEvent.js
* Form definition for Job Events model
*
*
*/
angular.module('JobModalEventDefinition', [])
.value(
'JobModalEventForm', {
editTitle: '{{ id }} - {{ event_display }}', //Legend in edit mode
name: 'job_events',
well: false,
'class': 'horizontal-narrow',
fields: {
event_data: {
label: 'Event Data',
type: 'textarea',
readonly: true,
rows: 10,
'class': 'modal-input-xlarge'
}
},
buttons: {
},
related: { //related colletions (and maybe items?)
}
}); //Form

View File

@ -6,8 +6,8 @@
* EventView - show the job_events form in a modal dialog
*
*/
angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventFormDefinition'])
.factory('EventView', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobEventForm', 'GenerateForm',
angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobModalEventDefinition'])
.factory('EventView', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobModalEventForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate',
function($rootScope, $location, $log, $routeParams, Rest, Alert, JobEventForm, GenerateForm, Prompt, ProcessErrors, GetBasePath,
FormatDate) {
@ -25,7 +25,6 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventFormDefini
}
scope.formModalActionLabel = 'OK';
//scope.formModalHeader = 'View Event';
scope.formModalCancelShow = false;
$('#form-modal .btn-success').removeClass('btn-success').addClass('btn-none');
@ -34,67 +33,13 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventFormDefini
Rest.setUrl(defaultUrl);
Rest.get()
.success( function(data, status, headers, config) {
for (var fld in form.fields) {
switch(fld) {
case 'status':
if (data['failed']) {
scope['status'] = 'error';
}
else if (data['changed']) {
scope['status'] = 'changed';
}
else {
scope['status'] = 'success';
}
break;
case 'created':
var cDate = new Date(data['created']);
scope['created'] = FormatDate(cDate);
break;
case 'host':
if (data['summary_fields'] && data['summary_fields']['host']) {
scope['host'] = data['summary_fields']['host']['name'];
}
break;
case 'id':
case 'task':
scope[fld] = data[fld];
break;
case 'msg':
case 'stdout':
case 'stderr':
case 'start':
case 'end':
case 'delta':
case 'rc':
if (data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] !== undefined) {
scope[fld] = data['event_data']['res'][fld];
if (form.fields[fld].type == 'textarea') {
var n = data['event_data']['res'][fld].match(/\n/g);
rows = (n) ? n.length : 1;
rows = (rows > 5) ? 5 : rows;
$('textarea[name="' + fld + '"]').attr('rows',rows);
}
}
break;
case 'conditional':
if (data['event_data']['res']) {
scope[fld] = data['event_data']['res']['is_conditional'];
}
break;
case 'module_name':
case 'module_args':
if (data['event_data']['res'] && data['event_data']['res']['invocation']) {
scope[fld] = data['event_data']['res']['invocation'][fld];
}
break;
}
}
scope['formModalHeader'] = data.event_display.replace(/^\u00a0*/g,'');
scope.formModalHeader = data['event_display'];
scope.event_data = JSON.stringify(data['event_data'], null, '\t');
})
.error( function(data, status, headers, config) {
$('#form-modal').modal("hide");
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve host: ' + event_id + '. GET status: ' + status });
{ hdr: 'Error!', msg: 'Failed to retrieve event: ' + event_id + '. GET status: ' + status });
});
if (!scope.$$phase) {

View File

@ -181,6 +181,21 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
return html;
},
button: function(btn) {
// pass in a button object and get back an html string containing
// a <button> element.
var html = '';
html += "<button ";
html += "class=\"btn";
html += (btn['class']) ? " " + btn['class'] : "";
html += "\" ";
html += (btn.ngClick) ? this.attr(btn, 'ngClick') : "";
html += ">" + this.attr(btn, 'icon');
html += " " + btn.label;
html += "</button>\n";
return html;
},
buildField: function(fld, field, options) {
var html='';
@ -582,22 +597,23 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
else {
if ( this.form.collapse && this.form.collapseMode == options.mode) {
/*html += "<div class=\"accordion-group\">\n";
html += "<div class=\"accordion-heading\">\n";
html += "<a id=\"" + this.form.name + "-collapse-0\" class=\"accordion-toggle\" data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#collapse0\">";
html += "<i class=\"icon-angle-down icon-white\"></i>" + this.form.collapseTitle + "</a>\n";
html += "</div>\n";
html += "<div id=\"collapse0\" class=\"accordion-body collapse";
html += (this.form.collapseOpen) ? " in" : "";
html += "\">\n";
html += "<div class=\"accordion-inner\">\n";
*/
html += "<div id=\"" + this.form.name + "-collapse-0\" ";
html += (this.form.collapseOpen) ? "data-open=\"true\" " : "";
html += "class=\"jqui-accordion\">\n";
html += "<h3>" + this.form.collapseTitle + "<h3>\n";
html += "<h3>" + this.form.collapseTitle + "</h3>\n";
html += "<div>\n";
}
if (this.form.navigation) {
html += "<div class=\"navigation-buttons navigation-buttons-top\">\n";
for (btn in this.form.navigation) {
var btn = this.form.navigation[btn];
if (btn.position == 'top') {
html += this.button(btn);
}
}
html += "</div>\n";
}
// Start the well
if ( this.has('well') ) {
@ -632,15 +648,26 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
}
else {
// original, single-column form
var section = '';
var section = '';
for (var fld in this.form.fields) {
var field = this.form.fields[fld];
if (field.section && field.section != section) {
html += "<div class=\"form-section-title\">" + field.section + "</div>\n";
section = field.section;
if (section !== '') {
html += "</div>\n</div>\n";
}
else {
html += "<div id=\"" + this.form.name + "-collapse\" class=\"jqui-accordion\" data-open=\"true\">\n";
}
html += "<h3>" + field.section + "</h3>\n";
html += "<div>\n";
html += "<div class=\"well\">\n";
section = field.section;
}
html += this.buildField(fld, field, options);
}
if (section !== '') {
html += "</div>\n</div>\n</div>\n";
}
}
//buttons
@ -691,6 +718,17 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
html += "</div>\n";
}
if (this.form.navigation) {
html += "<div class=\"navigation-buttons navigation-buttons-bottom\">\n";
for (btn in this.form.navigation) {
var btn = this.form.navigation[btn];
if (btn.position == 'bottom') {
html += this.button(btn);
}
}
html += "</div>\n";
}
if ( this.form.collapse && this.form.collapseMode == options.mode ) {
html += "</div>\n";
html += "</div>\n";

View File

@ -54,6 +54,7 @@
<script src="{{ STATIC_URL }}js/forms/JobEvents.js"></script>
<script src="{{ STATIC_URL }}js/forms/Projects.js"></script>
<script src="{{ STATIC_URL }}js/forms/Permissions.js"></script>
<script src="{{ STATIC_URL }}js/forms/JobModalEvent.js"></script>
<script src="{{ STATIC_URL }}js/lists/Users.js"></script>
<script src="{{ STATIC_URL }}js/lists/Organizations.js"></script>
<script src="{{ STATIC_URL }}js/lists/Admins.js"></script>