Job Events detail page starting to work.

This commit is contained in:
chouseknecht
2013-05-20 00:05:26 -04:00
committed by chouseknecht
parent 0bd576de62
commit 3d3782fcee
17 changed files with 205 additions and 60 deletions

View File

@@ -267,5 +267,11 @@
.job-pending, .job-running { .job-pending, .job-running {
color: #5bb75b; color: #5bb75b;
} }
.job-detail-status {
font-size: 15px;
font-weight: bold;
padding-left: 15px;
}
/* End Jobs Page */ /* End Jobs Page */

View File

@@ -46,7 +46,8 @@ angular.module('ansible', [
'JobTemplateHelper', 'JobTemplateHelper',
'ProjectsListDefinition', 'ProjectsListDefinition',
'JobsListDefinition', 'JobsListDefinition',
'JobFormDefinition' 'JobFormDefinition',
'JobEventFormDefinition'
]) ])
.config(['$routeProvider', function($routeProvider) { .config(['$routeProvider', function($routeProvider) {
$routeProvider. $routeProvider.
@@ -56,6 +57,9 @@ angular.module('ansible', [
when('/jobs/:id', when('/jobs/:id',
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobsEdit }). { templateUrl: urlPrefix + 'partials/jobs.html', controller: JobsEdit }).
when('/jobs/:id/job_events',
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobEvents }).
when('/job_templates', when('/job_templates',
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesList }). { templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesList }).

View File

@@ -32,6 +32,11 @@ function JobsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Aler
$location.path($location.path() + '/' + id); $location.path($location.path() + '/' + id);
} }
scope.viewEvents = function(id) {
console.log('headed to: ' + $location.path() + '/' + id + '/job_events');
$location.path($location.path() + '/' + id + '/job_events');
}
} }
JobsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobList', JobsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobList',
@@ -266,3 +271,53 @@ JobsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', 'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList',
'ProjectList', 'LookUpInit', 'PromptPasswords', 'GetBasePath' 'ProjectList', 'LookUpInit', 'PromptPasswords', 'GetBasePath'
]; ];
function JobEvents ($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
// Inject dynamic view
var form = JobEventForm;
var generator = GenerateForm;
var scope = GenerateForm.inject(form, {mode: 'edit', related: true});
generator.reset();
var defaultUrl = GetBasePath('jobs') + $routeParams.id + '/job_events';
var base = $location.path().replace(/^\//,'').split('/')[0];
var master = {};
var id = $routeParams.id;
var relatedSets = {};
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl);
Rest.get({ params: {page_size: 1} })
.success( function(data, status, headers, config) {
LoadBreadCrumbs({ path: '/organizations/' + id, title: data.name });
for (var fld in form.fields) {
if (data[fld]) {
scope[fld] = data[fld];
}
}
for (var fld in form.items) {
if (data[fld]) {
scope[fld] = data[fld];
}
}
scope['event_satus'] = (data.failed) ? 'failed' : 'success';
scope.next = data.next;
scope.previous = data.previous;
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve job event data: ' + $routeParams.id + '. GET status: ' + status });
});
}
JobEvents.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobEventForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath' ];

View File

@@ -0,0 +1,74 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* JobEvents.js
* Form definition for Job Events model
*
*
*/
angular.module('JobEventFormDefinition', [])
.value(
'JobEventForm', {
editTitle: '{{ name }} Events', //Legend in edit mode
name: 'job_events',
well: true,
formInline: true,
fields: {
job: {
label: 'Job ID',
type: 'text',
readonly: true
},
name: {
label: 'Name',
type: 'text',
sourceModel: 'job',
sourceField: 'name',
readonly: true
},
description: {
label: 'Description',
type: 'text',
sourceModel: 'job',
sourceField: 'description',
readonly: true
}
},
buttons: {
},
items: {
event: {
label: 'Event',
type: 'text',
readonly: true
},
created: {
label: 'Event Timestamp',
type: 'text',
readonly: true
},
event_status: {
label: 'Event Status <span class="job-detail-status job-\{\{ status \}\}"><i class="icon-circle"></i> \{\{ status \}\}</span>',
type: 'text',
readonly: true,
control: false
},
event_data: {
label: 'Event Data',
type: 'textarea',
class: 'span12',
rows: 10
}
},
related: { //related colletions (and maybe items?)
}
}); //Form

View File

@@ -138,11 +138,10 @@ angular.module('JobFormDefinition', [])
statusFields: { statusFields: {
status: { status: {
label: 'Status', label: 'Job Status <span class="job-detail-status job-\{\{ status \}\}"><i class="icon-circle"></i> \{\{ status \}\}</span>',
type: 'text', type: 'text',
readonly: true, readonly: true,
icon: 'icon-circle', control: false
class: 'job-\{\{ job.status \}\}'
}, },
result_stdout: { result_stdout: {
label: 'Standard Out', label: 'Standard Out',

View File

@@ -55,7 +55,7 @@ angular.module('CredentialsListDefinition', [])
ngClick: "editCredential(\{\{ credential.id \}\})", ngClick: "editCredential(\{\{ credential.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
class: 'btn-mini', class: 'btn-mini',
awToolTip: 'Edit credential' awToolTip: 'View/Edit credential'
}, },
delete: { delete: {

View File

@@ -42,7 +42,7 @@ angular.module('GroupListDefinition', [])
ngClick: "editGroup(\{\{ group.id \}\})", ngClick: "editGroup(\{\{ group.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
class: 'btn-mini', class: 'btn-mini',
awToolTip: 'Edit group' awToolTip: 'View/Edit group'
}, },
delete: { delete: {

View File

@@ -42,7 +42,7 @@ angular.module('HostListDefinition', [])
ngClick: "editHost(\{\{ host.id \}\})", ngClick: "editHost(\{\{ host.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
class: 'btn-mini', class: 'btn-mini',
awToolTip: 'Edit host' awToolTip: 'View/Edit host'
}, },
delete: { delete: {

View File

@@ -48,7 +48,7 @@ angular.module('InventoriesListDefinition', [])
ngClick: "editInventory(\{\{ inventory.id \}\})", ngClick: "editInventory(\{\{ inventory.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
class: 'btn-mini', class: 'btn-mini',
awToolTip: 'Edit' awToolTip: 'View/Edit inventory'
}, },
delete: { delete: {

View File

@@ -42,13 +42,13 @@ angular.module('JobTemplatesListDefinition', [])
edit: { edit: {
ngClick: "editJobTemplate(\{\{ job_template.id \}\})", ngClick: "editJobTemplate(\{\{ job_template.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Edit template', awToolTip: 'View/Edit template',
class: 'btn-mini' class: 'btn-mini'
}, },
submit: { submit: {
icon: 'icon-play', icon: 'icon-play',
mode: 'all', mode: 'all',
class: 'btn-mini', class: 'btn-mini btn-success',
ngClick: 'submitJob(\{\{ job_template.id \}\})', ngClick: 'submitJob(\{\{ job_template.id \}\})',
awToolTip: 'Create and run a job using this template' awToolTip: 'Create and run a job using this template'
}, },

View File

@@ -46,13 +46,13 @@ angular.module('JobsListDefinition', [])
ngClick: "editJob(\{\{ job.id \}\})", ngClick: "editJob(\{\{ job.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
class: 'btn-mini', class: 'btn-mini',
awToolTip: 'Edit/View detail', awToolTip: 'View/Edit detail',
}, },
summary: { summary: {
title: 'Summary', title: 'Summary',
icon: 'icon-filter', icon: 'icon-filter',
ngClick: 'viewSummary()', ngClick: 'viewSummary(\{{ job.id \}\})',
class: 'btn-info btn-mini', class: 'btn-success btn-mini',
awToolTip: 'View host summary', awToolTip: 'View host summary',
ngDisabled: "job.status == 'new'" ngDisabled: "job.status == 'new'"
}, },
@@ -60,8 +60,8 @@ angular.module('JobsListDefinition', [])
title: 'Detail', title: 'Detail',
icon: 'icon-list-ul', icon: 'icon-list-ul',
mode: 'all', mode: 'all',
ngClick: 'viewEvents()', ngClick: 'viewEvents(\{{ job.id \}\})',
class: 'btn-info btn-mini', class: 'btn-success btn-mini',
awToolTip: 'View events', awToolTip: 'View events',
ngDisabled: "job.status == 'new'" ngDisabled: "job.status == 'new'"
}, },

View File

@@ -41,14 +41,14 @@ angular.module('OrganizationListDefinition', [])
ngClick: "editOrganization(\{\{ organization.id \}\})", ngClick: "editOrganization(\{\{ organization.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
class: 'btn-mini', class: 'btn-mini',
awToolTip: 'Edit' awToolTip: 'View/Edit organization'
}, },
delete: { delete: {
ngClick: "deleteOrganization(\{\{ organization.id \}\},'\{\{ organization.name \}\}')", ngClick: "deleteOrganization(\{\{ organization.id \}\},'\{\{ organization.name \}\}')",
icon: 'icon-remove', icon: 'icon-remove',
class: 'btn-mini btn-danger', class: 'btn-mini btn-danger',
awToolTip: 'Delete' awToolTip: 'Delete organization'
} }
} }
}); });

View File

@@ -42,7 +42,7 @@ angular.module('ProjectsListDefinition', [])
ngClick: "editProject(\{\{ project.id \}\})", ngClick: "editProject(\{\{ project.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
class: 'btn-mini', class: 'btn-mini',
awToolTip: 'Edit project' awToolTip: 'View/edit project'
}, },
delete: { delete: {

View File

@@ -48,7 +48,7 @@ angular.module('TeamsListDefinition', [])
ngClick: "editTeam(\{\{ team.id \}\})", ngClick: "editTeam(\{\{ team.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
class: 'btn-mini', class: 'btn-mini',
awToolTip: 'Edit team' awToolTip: 'View/Edit team'
}, },
delete: { delete: {

View File

@@ -47,7 +47,7 @@ angular.module('UserListDefinition', [])
ngClick: "editUser(\{\{ user.id \}\})", ngClick: "editUser(\{\{ user.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
class: 'btn-mini', class: 'btn-mini',
awToolTip: 'Edit user' awToolTip: 'View/Edit user'
}, },
delete: { delete: {

View File

@@ -154,48 +154,54 @@ angular.module('FormGenerator', ['GeneratorHelpers'])
html += "<div class=\"control-group\"" html += "<div class=\"control-group\""
html += (field.ngShow) ? this.attr(field,'ngShow') : ""; html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += ">\n"; html += ">\n";
html += "<label class=\"control-label\" for=\"" + fld + '">' + field.label + '</label>' + "\n"; html += "<label class=\"control-label";
html += (field.labelClass) ? " " + field.labelClass : "";
html += "\" for=\"" + fld + '">';
html += (field.icon) ? this.icon(field.icon) : "";
html += field.label + '</label>' + "\n";
html += "<div class=\"controls\">\n"; html += "<div class=\"controls\">\n";
html += (field.clear) ? "<div class=\"input-append\">\n" : ""; html += (field.clear) ? "<div class=\"input-append\">\n" : "";
html += "<input "; if (field.control === null || field.control === undefined || field.control) {
html += this.attr(field,'type'); html += "<input ";
html += "ng-model=\"" + fld + '" '; html += this.attr(field,'type');
html += 'name="' + fld + '" '; html += "ng-model=\"" + fld + '" ';
html += (field.ngChange) ? this.attr(field,'ngChange') : ""; html += 'name="' + fld + '" ';
html += (field.id) ? this.attr(field,'id') : ""; html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.placeholder) ? this.attr(field,'placeholder') : ""; html += (field.id) ? this.attr(field,'id') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : ""; html += (field.placeholder) ? this.attr(field,'placeholder') : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : ""; html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (field.readonly) ? "readonly " : ""; html += (options.mode == 'add' && field.addRequired) ? "required " : "";
html += (field.awPassMatch) ? "awpassmatch=\"" + field.associated + "\" " : ""; html += (field.readonly) ? "readonly " : "";
html += (field.capitalize) ? "capitalize " : ""; html += (field.awPassMatch) ? "awpassmatch=\"" + field.associated + "\" " : "";
html += (field.ask) ? "ng-disabled=\"" + fld + "_ask\" " : ""; html += (field.capitalize) ? "capitalize " : "";
html += (field.associated && this.form.fields[field.associated].ask) ? "ng-disabled=\"" + field.associated + "_ask\" " : ""; html += (field.ask) ? "ng-disabled=\"" + fld + "_ask\" " : "";
html += "/>"; html += (field.associated && this.form.fields[field.associated].ask) ? "ng-disabled=\"" + field.associated + "_ask\" " : "";
if (field.clear) { html += "/>";
html += " \n<button class=\"btn\" ng-click=\"clear('" + fld + "','" + field.associated + "')\" " + if (field.clear) {
"aw-tool-tip=\"Clear " + field.label + "\" id=\"" + fld + "-clear-btn\"><i class=\"icon-undo\"></i></button>\n"; html += " \n<button class=\"btn\" ng-click=\"clear('" + fld + "','" + field.associated + "')\" " +
html += "</div>\n"; "aw-tool-tip=\"Clear " + field.label + "\" id=\"" + fld + "-clear-btn\"><i class=\"icon-undo\"></i></button>\n";
html += "</div>\n";
}
if (field.ask) {
html += " \n<label class=\"checkbox inline ask-checkbox\"><input type=\"checkbox\" ng-model=\"" +
fld + "_ask\" ng-change=\"ask('" + fld + "','" + field.associated + "')\" /> Ask at runtime?</label>";
}
html += "<br />\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</span>\n";
}
if (field.type == "email") {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.email\">A valid email address is required!</span>\n";
}
if (field.awPassMatch) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld +
".$error.awpassmatch\">Must match Password value</span>\n";
}
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
} }
if (field.ask) {
html += " \n<label class=\"checkbox inline ask-checkbox\"><input type=\"checkbox\" ng-model=\"" +
fld + "_ask\" ng-change=\"ask('" + fld + "','" + field.associated + "')\" /> Ask at runtime?</label>";
}
html += "<br />\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</span>\n";
}
if (field.type == "email") {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.email\">A valid email address is required!</span>\n";
}
if (field.awPassMatch) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld +
".$error.awpassmatch\">Must match Password value</span>\n";
}
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
html += "</div>\n"; html += "</div>\n";
html += "</div>\n"; html += "</div>\n";
} }

View File

@@ -45,6 +45,7 @@
<script src="{{ STATIC_URL }}js/forms/Credentials.js"></script> <script src="{{ STATIC_URL }}js/forms/Credentials.js"></script>
<script src="{{ STATIC_URL }}js/forms/JobTemplates.js"></script> <script src="{{ STATIC_URL }}js/forms/JobTemplates.js"></script>
<script src="{{ STATIC_URL }}js/forms/Jobs.js"></script> <script src="{{ STATIC_URL }}js/forms/Jobs.js"></script>
<script src="{{ STATIC_URL }}js/forms/JobEvents.js"></script>
<script src="{{ STATIC_URL }}js/lists/Users.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/Organizations.js"></script>
<script src="{{ STATIC_URL }}js/lists/Admins.js"></script> <script src="{{ STATIC_URL }}js/lists/Admins.js"></script>