Latest UI changs. First iteration on Jobs page.

This commit is contained in:
chouseknecht 2013-05-19 15:05:03 -04:00
parent 14bc3c02f8
commit f409db7778
21 changed files with 229 additions and 48 deletions

View File

@ -248,4 +248,23 @@
.well {
padding-bottom: 0;
}
}
/* Jobs page */
.jobs-table tbody tr:hover > td,
.jobs-table tbody tr:hover > th {
background-color: #fff;
}
.job-error, .job-failure {
color: #da4f49;
}
.job-new {
color: #778899;
}
.job-pending, .job-running {
color: #5bb75b;
}

View File

@ -44,10 +44,14 @@ angular.module('ansible', [
'JobTemplatesListDefinition',
'JobTemplateFormDefinition',
'JobTemplateHelper',
'ProjectsListDefinition'
'ProjectsListDefinition',
'JobsListDefinition'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/jobs',
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobsList }).
when('/job_templates',
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesList }).

View File

@ -0,0 +1,36 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
*
* Jobs.js
*
* Controller functions for the Job model.
*
*/
'use strict';
function JobsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, GetBasePath, LookUpInit)
{
ClearScope('htmlTemplate');
var list = JobList;
var defaultUrl = GetBasePath('jobs');
var view = GenerateList;
var base = $location.path().replace(/^\//,'').split('/')[0];
var scope = view.inject(list, { mode: 'edit' });
scope.selected = [];
SearchInit({ scope: scope, set: 'jobs', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
LoadBreadCrumbs();
}
JobsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobList',
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
'ProcessErrors','GetBasePath', 'LookUpInit'
];

View File

@ -20,7 +20,7 @@ angular.module('PaginateHelper', ['RefreshHelper'])
var scope = params.scope;
var list = params.list;
var defaultUrl = params.url;
var url = params.url;
var mode = (params.mode) ? params.mode : null;
scope[list.iterator + 'Page'] = 0;
@ -45,7 +45,8 @@ angular.module('PaginateHelper', ['RefreshHelper'])
scope.changePageSize = function(set, iterator) {
// Called when a new page size is selected
scope[iterator + 'Page'] = 0;
Refresh({ scope: scope, set: set, iterator: iterator, url: defaultUrl });
url += (scope[iterator + 'SearchParams']) ? scope[iterator + 'SearchParams'] : '';
Refresh({ scope: scope, set: set, iterator: iterator, url: url });
}
}
}]);

View File

@ -22,12 +22,9 @@ angular.module('RefreshHelper', ['RestServices', 'Utilities'])
var set = params.set;
var iterator = params.iterator;
var url = params.url;
url.replace(/page_size\=\d+/,''); //stop repeatedly appending page_size
url += scope[iterator + 'SearchParams'];
Rest.setUrl(url);
Rest.get({ params: { page_size: scope[iterator + 'PageSize'] }})
Rest.get()
.success( function(data, status, headers, config) {
scope[iterator + 'NextUrl'] = data.next;
scope[iterator + 'PrevUrl'] = data.previous;

View File

@ -30,7 +30,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
// Set default values
for (fld in list.fields) {
if (list.fields[fld].key) {
default_order = fld;
default_order = (list.fields[fld].desc) ? '-' + fld : fld;
scope[iterator + 'SearchField'] = fld
scope[iterator + 'SearchFieldLabel'] = list.fields[fld].label;
break;
@ -78,6 +78,8 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
scope[iterator + 'SearchParams'] = '';
scope[iterator + 'SearchParams'] += (default_order) ? '?order_by=' + escape(default_order) : '';
}
url += scope[iterator + 'SearchParams'];
url += (scope[iterator + 'PageSize']) ? '&page_size=' + scope[iterator + 'PageSize'] : "";
Refresh({ scope: scope, set: set, iterator: iterator, url: url });
}
}

View File

@ -16,6 +16,7 @@ angular.module('AdminListDefinition', [])
editTitle: 'Admins',
selectInstructions: 'Click on a row to select it. Click the Finished button when done.',
base: 'users',
index: true,
fields: {
username: {

View File

@ -15,6 +15,7 @@ angular.module('CredentialsListDefinition', [])
selectTitle: 'Add Credentials',
editTitle: 'Credentials',
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.',
index: true,
fields: {
name: {
@ -44,7 +45,7 @@ angular.module('CredentialsListDefinition', [])
mode: 'all', // One of: edit, select, all
ngClick: 'addCredential()',
basePaths: ['credentials'], // base path must be in list, or action not available
class: 'btn btn-success',
class: 'btn-success',
awToolTip: 'Create a new credential'
}
},
@ -53,13 +54,14 @@ angular.module('CredentialsListDefinition', [])
edit: {
ngClick: "editCredential(\{\{ credential.id \}\})",
icon: 'icon-edit',
class: 'btn-mini',
awToolTip: 'Edit credential'
},
delete: {
ngClick: "deleteCredential(\{\{ credential.id \}\},'\{\{ credential.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
class: 'btn-mini btn-danger',
awToolTip: 'Delete credential'
}
}

View File

@ -15,6 +15,7 @@ angular.module('GroupListDefinition', [])
selectTitle: 'Add Group',
editTitle: 'Groups',
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.',
index: true,
fields: {
name: {
@ -31,7 +32,7 @@ angular.module('GroupListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addGroup()',
class: 'btn btn-success',
class: 'btn-success',
awToolTip: 'Create a new group'
}
},
@ -40,13 +41,14 @@ angular.module('GroupListDefinition', [])
edit: {
ngClick: "editGroup(\{\{ group.id \}\})",
icon: 'icon-edit',
class: 'btn-mini',
awToolTip: 'Edit group'
},
delete: {
ngClick: "deleteGroup(\{\{ group.id \}\},'\{\{ group.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
class: 'btn-mini btn-danger',
awToolTip: 'Delete group'
}
}

View File

@ -15,6 +15,7 @@ angular.module('HostListDefinition', [])
selectTitle: 'Add Host',
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.',
editTitle: 'Hosts',
index: true,
fields: {
name: {
@ -31,7 +32,7 @@ angular.module('HostListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addHost()',
class: 'btn btn-success',
class: 'btn-success',
awToolTip: 'Create a new host'
}
},
@ -40,13 +41,14 @@ angular.module('HostListDefinition', [])
edit: {
ngClick: "editHost(\{\{ host.id \}\})",
icon: 'icon-edit',
class: 'btn-mini',
awToolTip: 'Edit host'
},
delete: {
ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
class: 'btn-mini btn-danger',
awToolTip: 'Delete host'
}
}

View File

@ -15,6 +15,7 @@ angular.module('InventoriesListDefinition', [])
selectTitle: 'Add Inventories',
editTitle: 'Inventories',
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.',
index: true,
fields: {
name: {
@ -37,7 +38,7 @@ angular.module('InventoriesListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addInventory()',
class: 'btn btn-success',
class: 'btn-success',
awToolTip: 'Create a new row'
}
},
@ -46,13 +47,14 @@ angular.module('InventoriesListDefinition', [])
edit: {
ngClick: "editInventory(\{\{ inventory.id \}\})",
icon: 'icon-edit',
class: 'btn-mini',
awToolTip: 'Edit'
},
delete: {
ngClick: "deleteInventory(\{\{ inventory.id \}\},'\{\{ inventory.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
class: 'btn-mini btn-danger',
awToolTip: 'Delete'
}
}

View File

@ -15,6 +15,7 @@ angular.module('JobTemplatesListDefinition', [])
selectTitle: 'Add Job Template',
editTitle: 'Job Templates',
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.',
index: true,
fields: {
name: {
@ -31,29 +32,30 @@ angular.module('JobTemplatesListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addJobTemplate()',
class: 'btn btn-success',
class: 'btn-success',
basePaths: ['job_templates'],
awToolTip: 'Create a new template'
}
},
fieldActions: {
submit: {
icon: 'icon-play',
mode: 'all',
ngClick: 'submitJob(\{\{ job_template.id \}\})',
class: 'btn btn-mini',
awToolTip: 'Create and run a job using this template'
},
edit: {
ngClick: "editJobTemplate(\{\{ job_template.id \}\})",
icon: 'icon-edit',
awToolTip: 'Edit template'
awToolTip: 'Edit template',
class: 'btn-mini'
},
submit: {
icon: 'icon-play',
mode: 'all',
class: 'btn-mini',
ngClick: 'submitJob(\{\{ job_template.id \}\})',
awToolTip: 'Create and run a job using this template'
},
delete: {
ngClick: "deleteJobTemplate(\{\{ job_template.id \}\},'\{\{ job_template.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
class: 'btn-danger btn-mini',
awToolTip: 'Delete template'
}
}

View File

@ -0,0 +1,79 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Jobs.js
* List view object for Team data model.
*
*
*/
angular.module('JobsListDefinition', [])
.value(
'JobList', {
name: 'jobs',
iterator: 'job',
editTitle: 'Jobs',
index: false,
hover: true,
class: 'jobs-table',
fields: {
id: {
label: 'Job ID',
key: true,
desc: true
},
created: {
label: 'Creation Date',
link: true
},
name: {
label: 'Name',
link: true,
},
status: {
label: 'Status',
icon: 'icon-circle',
class: 'job-\{\{ job.status \}\}'
}
},
actions: {
},
fieldActions: {
edit: {
ngClick: "editJob(\{\{ job.id \}\})",
icon: 'icon-edit',
class: 'btn-mini',
awToolTip: 'Edit job',
ngDisabled: "job.status != 'new'"
},
summary: {
title: 'Summary',
icon: 'icon-filter',
ngClick: 'viewSummary()',
class: 'btn-success btn-mini',
awToolTip: 'Job summary',
ngDisabled: "job.status == 'new'"
},
events: {
title: 'Detail',
icon: 'icon-list-ul',
mode: 'all',
ngClick: 'viewEvents()',
class: 'btn-info btn-mini',
awToolTip: 'Job event detail',
ngDisabled: "job.status == 'new'"
},
cancel: {
title: 'Cancel',
icon: 'icon-minus-sign',
mode: 'all',
ngClick: 'cancel(\{\{ job.id \}\})',
class: 'btn-danger btn-mini',
awToolTip: 'Cancel job',
ngDisabled: "job.status == 'error' || job.status == 'failed'"
}
}
});

View File

@ -14,6 +14,7 @@ angular.module('OrganizationListDefinition', [])
iterator: 'organization',
selectTitle: 'Add Organizations',
editTitle: 'Organizations',
index: true,
fields: {
name: {
@ -30,7 +31,7 @@ angular.module('OrganizationListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addOrganization()',
class: 'btn btn-success',
class: 'btn-success',
awToolTip: 'Create a new row'
}
},
@ -39,13 +40,14 @@ angular.module('OrganizationListDefinition', [])
edit: {
ngClick: "editOrganization(\{\{ organization.id \}\})",
icon: 'icon-edit',
class: 'btn-mini',
awToolTip: 'Edit'
},
delete: {
ngClick: "deleteOrganization(\{\{ organization.id \}\},'\{\{ organization.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
class: 'btn-mini btn-danger',
awToolTip: 'Delete'
}
}

View File

@ -15,6 +15,7 @@ angular.module('ProjectsListDefinition', [])
selectTitle: 'Add Project',
editTitle: '{{ name }}',
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.',
index: true,
fields: {
name: {
@ -31,7 +32,7 @@ angular.module('ProjectsListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addProject()',
class: 'btn btn-success',
class: 'btn-success',
awToolTip: 'Create a new project'
}
},
@ -40,13 +41,14 @@ angular.module('ProjectsListDefinition', [])
edit: {
ngClick: "editProject(\{\{ project.id \}\})",
icon: 'icon-edit',
class: 'btn-mini',
awToolTip: 'Edit project'
},
delete: {
ngClick: "deleteProject(\{\{ project.id \}\},'\{\{ project.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
class: 'btn-mini btn-danger',
awToolTip: 'Delete project'
}
}

View File

@ -15,6 +15,7 @@ angular.module('TeamsListDefinition', [])
selectTitle: 'Add Team',
editTitle: 'Teams',
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.',
index: true,
fields: {
name: {
@ -37,7 +38,7 @@ angular.module('TeamsListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addTeam()',
class: 'btn btn-success',
class: 'btn-success',
awToolTip: 'Create a new team'
}
},
@ -46,13 +47,14 @@ angular.module('TeamsListDefinition', [])
edit: {
ngClick: "editTeam(\{\{ team.id \}\})",
icon: 'icon-edit',
class: 'btn-mini',
awToolTip: 'Edit team'
},
delete: {
ngClick: "deleteTeam(\{\{ team.id \}\},'\{\{ team.name \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
class: 'btn-mini btn-danger',
awToolTip: 'Delete team'
}
}

View File

@ -16,6 +16,7 @@ angular.module('UserListDefinition', [])
editTitle: 'Users',
selectInstructions: 'Check the Select checkbox next to each user to be added, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new user.',
editInstructions: 'Create new users from the Organizations tab. Each Organization has an associated list of Users.',
index: true,
fields: {
username: {
@ -36,7 +37,7 @@ angular.module('UserListDefinition', [])
mode: 'select', // One of: edit, select, all
ngClick: 'addUser()',
basePaths: ['organizations'], // base path must be in list, or action not available
class: 'btn btn-success',
class: 'btn-success',
awToolTip: 'Create a new user'
}
},
@ -45,13 +46,14 @@ angular.module('UserListDefinition', [])
edit: {
ngClick: "editUser(\{\{ user.id \}\})",
icon: 'icon-edit',
class: 'btn-mini',
awToolTip: 'Edit user'
},
delete: {
ngClick: "deleteUser(\{\{ user.id \}\},'\{\{ user.username \}\}')",
icon: 'icon-remove',
class: 'btn-danger',
class: 'btn-mini btn-danger',
awToolTip: 'Delete user'
}
}

View File

@ -30,7 +30,9 @@ angular.module('GeneratorHelpers', [])
html += "<ul class=\"dropdown-menu\">\n";
for ( var fld in form.fields) {
html += "<li><a href=\"\" ng-click=\"setSearchField('" + iterator + "','" + fld + "','" + form.fields[fld].label + "')\">"
html += "<li><a href=\"\" ng-click=\"setSearchField('" + iterator + "','";
html += (form.fields[fld].desc) ? '-' : '';
html += fld + "','" + form.fields[fld].label + "')\">"
+ form.fields[fld].label + "</a></li>\n";
}
@ -81,11 +83,11 @@ angular.module('GeneratorHelpers', [])
html += "<button class=\"previous btn";
html += (useMini) ? " btn-mini\" " : "\" ";
html += "ng-click=\"prevSet('" + set + "','" + iterator + "')\" " +
"ng-disabled=\"prevUrl == null || prevUrl == undefined\"><i class=\"icon-chevron-left\"></i> Prev</button>\n";
"ng-disabled=\"" + iterator + "PrevUrl == null || " + iterator + "PrevUrl == undefined\"><i class=\"icon-chevron-left\"></i> Prev</button>\n";
html += "<button class=\"next btn btn";
html += (useMini) ? " btn-mini\" " : "\" ";
html += " ng-click=\"nextSet('" + set + "','" + iterator + "')\"" +
"ng-disabled=\"nextUrl == null || nextUrl == undefined\">Next <i class=\"icon-chevron-right\"></i></button>\n";
"ng-disabled=\"" + iterator + "NextUrl == null || " + iterator + "NextUrl == undefined\">Next <i class=\"icon-chevron-right\"></i></button>\n";
if (mode != 'lookup') {
html += "<label class=\"page-size-label\">Rows per page:</label>\n";

View File

@ -22,9 +22,15 @@ angular.module('ListGenerator', ['GeneratorHelpers',])
case 'ngClick':
result = "ng-click=\"" + obj[key] + "\" ";
break;
case 'ngDisabled':
result = "ng-disabled=\"" + obj[key] + "\" ";
break;
case 'ngBind':
result = "ng-bind=\"" + obj[key] + "\" ";
break;
case 'ngShow':
result = "ng-show=\"" + obj[key] + "\" ";
break;
case 'awToolTip':
result = "aw-tool-tip=\"" + obj[key] + "\" ";
break;
@ -149,11 +155,14 @@ angular.module('ListGenerator', ['GeneratorHelpers',])
// table header row
html += "<table class=\"table table-condensed"
html += (options.mode == 'lookup') ? " table-hover" : "";
html += (list.class) ? " " + list.class : "";
html += (options.mode == 'lookup' || list.hover) ? " table-hover" : "";
html += "\">\n";
html += "<thead>\n";
html += "<tr>\n";
html += "<th>#</th>\n";
if (list.index) {
html += "<th>#</th>\n";
}
for (var fld in list.fields) {
html += "<th>" + list.fields[fld].label + "</th>\n";
}
@ -173,27 +182,33 @@ angular.module('ListGenerator', ['GeneratorHelpers',])
html += "class=\"" + list.iterator + "_class\" ng-repeat=\"" + list.iterator + " in " + list.name + "\"";
html += (options.mode == 'lookup' || options.mode == 'select') ? " ng-click=\"toggle_" + list.iterator +"({{ " + list.iterator + ".id }})\"" : "";
html += ">\n";
html += "<td class=\"index-column\">{{ $index + (" + list.iterator + "Page * " + list.iterator + "PageSize) + 1 }}.</td>\n";
if (list.index) {
html += "<td class=\"index-column\">{{ $index + (" + list.iterator + "Page * " + list.iterator + "PageSize) + 1 }}.</td>\n";
}
var cnt = 2;
var base = (list.base) ? list.base : list.name;
for (fld in list.fields) {
cnt++;
if (! list.fields[fld].ngBind) {
html += "<td class=\"" + fld + "-column\">";
if (list.fields[fld].key && options.mode != 'lookup') {
html += "<td class=\"" + fld + "-column";
html += (list.fields[fld].class) ? " " + list.fields[fld].class : "";
html += "\">";
if ((list.fields[fld].key || list.fields[fld].link) && options.mode != 'lookup') {
html += "<a href=\"#/" + base + "/{{" + list.iterator + ".id }}\">";
}
html += (list.fields[fld].icon) ? this.icon(list.fields[fld].icon) : "";
html += "{{" + list.iterator + "." + fld + "}}";
html += (list.fields[fld].key && options.mode != 'lookup') ? "</a>" : "";
html += ((list.fields[fld].key || list.fields[fld].link) && options.mode != 'lookup') ? "</a>" : "";
html += "</td>\n";
}
else {
html += "<td class=\"" + fld + "-column\">";
if (list.fields[fld].key && options.mode != 'lookup') {
if ((list.fields[fld].key || list.fields[fld].link) && options.mode != 'lookup') {
html += "<a href=\"#/" + base + "/{{" + list.iterator + ".id }}\">";
}
html += (list.fields[fld].icon) ? this.icon(list.fields[fld].icon) : "";
html += "{{ " + list.fields[fld].ngBind + " }}";
html += (list.fields[fld].key && options.mode != 'lookup') ? "</a>" : "";
html += ((list.fields[fld].key || list.fields[fld].link) && options.mode != 'lookup') ? "</a>" : "";
html += "</td>\n";
}
}
@ -207,12 +222,14 @@ angular.module('ListGenerator', ['GeneratorHelpers',])
// Row level actions
html += "<td class=\"actions\">";
for (action in list.fieldActions) {
html += "<button class=\"btn btn-mini";
html += "<button class=\"btn";
if (list.fieldActions[action].class) {
html += " " + list.fieldActions[action].class;
}
html += "\" " + this.attr(list.fieldActions[action],'ngClick');
html += (list.fieldActions[action].ngShow) ? this.attr(list.fieldActions[action],'ngShow') : "";
html += (list.fieldActions[action].awToolTip) ? this.attr(list.fieldActions[action],'awToolTip') : "";
html += (list.fieldActions[action].ngDisabled) ? this.attr(list.fieldActions[action],'ngDisabled') : ""
html +=">";
html += (list.fieldActions[action].icon) ? this.icon(list.fieldActions[action].icon) : "";
html += (list.fieldActions[action].label) ? " " + list.fieldActions[action].label : "";

View File

@ -0,0 +1,3 @@
<div class="tab-pane" id="jobs">
<div id="htmlTemplate"></div>
</div>

View File

@ -35,6 +35,7 @@
<script src="{{ STATIC_URL }}js/controllers/Groups.js"></script>
<script src="{{ STATIC_URL }}js/controllers/JobTemplates.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Projects.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Jobs.js"></script>
<script src="{{ STATIC_URL }}js/forms/Users.js"></script>
<script src="{{ STATIC_URL }}js/forms/Organizations.js"></script>
<script src="{{ STATIC_URL }}js/forms/Inventories.js"></script>
@ -53,6 +54,7 @@
<script src="{{ STATIC_URL }}js/lists/Credentials.js"></script>
<script src="{{ STATIC_URL }}js/lists/JobTemplates.js"></script>
<script src="{{ STATIC_URL }}js/lists/Projects.js"></script>
<script src="{{ STATIC_URL }}js/lists/Jobs.js"></script>
<script src="{{ STATIC_URL }}js/helpers/refresh-related.js"></script>
<script src="{{ STATIC_URL }}js/helpers/related-paginate.js"></script>
<script src="{{ STATIC_URL }}js/helpers/related-search.js"></script>