From 82833c848faf6ffb852dd2ea7b54b4073db8f93c Mon Sep 17 00:00:00 2001 From: chouseknecht Date: Wed, 21 Aug 2013 12:50:25 -0400 Subject: [PATCH] AC-331 Latest changes and cleanup from testing --- awx/ui/static/js/controllers/Inventories.js | 31 +-- awx/ui/static/js/controllers/JobHosts.js | 8 + awx/ui/static/js/forms/Inventories.js | 31 +-- awx/ui/static/js/helpers/Groups.js | 13 +- awx/ui/static/js/helpers/inventory.js | 10 +- awx/ui/static/js/helpers/search.js | 6 + awx/ui/static/js/lists/Inventories.js | 11 +- awx/ui/static/less/ansible-ui.less | 8 +- awx/ui/static/lib/ansible/directives.js | 4 +- awx/ui/static/lib/ansible/form-generator.js | 17 +- .../static/lib/ansible/generator-helpers.js | 200 +++++++++++------- awx/ui/static/lib/ansible/list-generator.js | 7 + awx/ui/templates/ui/index.html | 31 ++- 13 files changed, 216 insertions(+), 161 deletions(-) diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index 0413571b90..62ca24f2b5 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -94,6 +94,11 @@ function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routePa var defaultUrl = GetBasePath('inventory'); var form = InventoryForm; var generator = GenerateForm; + + form.well = true, + form.formLabelSize = null; + form.formFieldSize = null; + var scope = generator.inject(form, {mode: 'add', related: false}); scope.inventoryParseType = 'yaml'; @@ -398,7 +403,7 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP scope.inventoryEditHide = true; scope.groupDeleteHide = false; scope.createButtonShow = true; - //scope.group_id = node.attr('group_id'); + scope.group_id = node.attr('group_id'); //scope.groupName = n.data; //scope.groupTitle = '

' + n.data + '

'; //scope.groupTitle += (node.attr('description')) ? '

' + node.attr('description') + '

' : ''; @@ -413,7 +418,7 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP scope.createButtonShow = false; //scope.groupName = 'All Hosts'; //scope.groupTitle = '

All Hosts

'; - //scope.group_id = null; + scope.group_id = null; } if (!scope.$$phase) { @@ -463,20 +468,18 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP request: 'remove' }); } */ - scope.showEvents = function(host_name, last_job) { - // When click on !Failed Events link, redirect to latest job/job_events for the host - Rest.setUrl(last_job); - Rest.get() - .success( function(data, status, headers, config) { - LoadBreadCrumbs({ path: '/jobs/' + data.id, title: data.name }); - $location.url('/jobs/' + data.id + '/job_events/?host=' + escape(host_name)); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to lookup last job: ' + last_job + '. GET status: ' + status }); - }); + scope.viewLastEvents = function(host_id, last_job, host_name, last_job_name) { + // Choose View-> Latest job events + LoadBreadCrumbs({ path: '/jobs/' + last_job, title: last_job_name }); + $location.url('/jobs/' + last_job + '/job_events/?host=' + escape(host_name)); } + scope.viewLastSummary = function(host_id, last_job, host_name, last_job_name) { + // Choose View-> Latest job events + LoadBreadCrumbs({ path: '/jobs/' + last_job, title: last_job_name }); + $location.url('/jobs/' + last_job + '/job_host_summaries/?host=' + escape(host_name)); + } + scope.toggleAllHosts = function() { scope.hostDeleteDisabled = (scope.toggleAllFlag) ? false : true; scope.hostDeleteDisabledClass = (scope.hostDeleteDisabled) ? "disabled" : ""; diff --git a/awx/ui/static/js/controllers/JobHosts.js b/awx/ui/static/js/controllers/JobHosts.js index af915e5031..e7a28044cb 100644 --- a/awx/ui/static/js/controllers/JobHosts.js +++ b/awx/ui/static/js/controllers/JobHosts.js @@ -35,6 +35,14 @@ function JobHostSummaryList ($scope, $rootScope, $location, $log, $routeParams, SearchInit({ scope: scope, set: 'jobhosts', list: list, url: defaultUrl }); PaginateInit({ scope: scope, list: list, url: defaultUrl }); + + // Called from Inventories tab, host failed events link: + if ($routeParams.host) { + scope[list.iterator + 'SearchField'] = 'host'; + scope[list.iterator + 'SearchValue'] = $routeParams.host; + scope[list.iterator + 'SearchFieldLabel'] = list.fields['host'].label; + } + scope.search(list.iterator); LoadBreadCrumbs(); diff --git a/awx/ui/static/js/forms/Inventories.js b/awx/ui/static/js/forms/Inventories.js index 811752bd6d..912858c6f6 100644 --- a/awx/ui/static/js/forms/Inventories.js +++ b/awx/ui/static/js/forms/Inventories.js @@ -14,19 +14,12 @@ angular.module('InventoryFormDefinition', []) editTitle: '{{ inventory_name }}', name: 'inventory', parseTypeName: 'inventoryParseType', - well: false, + well: true, + /*, formLabelSize: 'col-lg-3', - formFieldSize: 'col-lg-9', + formFieldSize: 'col-lg-9',*/ fields: { - has_active_failures: { - label: 'Status', - control: '
' + - ' Contains hosts with failed jobs
', - type: 'custom', - ngShow: 'has_active_failures', - readonly: true - }, inventory_name: { realName: 'name', label: 'Name', @@ -116,18 +109,26 @@ angular.module('InventoryFormDefinition', []) badgeShow: "\{\{ host.has_active_failures \}\}", badgeIcon: 'icon-exclamation-sign', badgeToolTip: 'Most recent job failed', - badgePlacement: 'bottom' + badgePlacement: 'bottom', + columnClass: 'col-lg-3' }, - /*description: { - label: 'Description', - ngClick: "editHost(\{\{ host.id \}\}, '\{\{ host.name \}\}')" - },*/ groups: { label: 'Groups', searchable: false, sourceModel: 'groups', sourceField: 'name', nosort: true + }, + dropdown: { + type: 'DropDown', + label: 'View', + options: [ + { ngClick: 'viewJobs(\{\{ host.id \}\})', label: 'Jobs' }, + { ngClick: "viewLastEvents(\{\{ host.id \}\}, '\{\{ host.last_job \}\}', '\{\{ host.name \}\}', " + + "'\{\{ host.summary_fields.last_job.name \}\}')", label: 'Latest job events' }, + { ngClick: "viewLastSummary(\{\{ host.id \}\}, '\{\{ host.last_job \}\}', '\{\{ host.name \}\}', " + + "'\{\{ host.summary_fields.last_job.name \}\}')", label: 'Latest host summary' } + ] } }, fieldActions: { diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js index 49bb98962f..c6105b2464 100644 --- a/awx/ui/static/js/helpers/Groups.js +++ b/awx/ui/static/js/helpers/Groups.js @@ -341,14 +341,14 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' .factory('GroupsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm', - 'Prompt', 'ProcessErrors', 'GetBasePath', 'RefreshTree', + 'Prompt', 'ProcessErrors', 'GetBasePath', 'RefreshTree', 'Wait', function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, - GetBasePath, RefreshTree) { + GetBasePath, RefreshTree, Wait) { return function(params) { // Delete the selected group node. Disassociates it from its parent. var scope = params.scope; var group_id = params.group_id; - var inventory_id = params.inventory_id; + var inventory_id = params.inventory_id; var obj = $('#tree-view li[group_id="' + group_id + '"]'); var parent = (obj.parent().last().prop('tagName') == 'LI') ? obj.parent().last() : obj.parent().parent().last(); var url; @@ -360,16 +360,19 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' url = GetBasePath('inventory') + inventory_id + '/groups/'; } var action_to_take = function() { + $('#prompt-modal').modal('hide'); + Wait('start'); Rest.setUrl(url); Rest.post({ id: group_id, disassociate: 1 }) .success( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); scope.selectedNode = scope.selectedNode.parent().parent(); RefreshTree({ scope: scope }); + Wait('stop'); }) .error( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); + //$('#prompt-modal').modal('hide'); RefreshTree({ scope: scope }); + Wait('stop'); ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); }); diff --git a/awx/ui/static/js/helpers/inventory.js b/awx/ui/static/js/helpers/inventory.js index 1520356bad..a51281bef2 100644 --- a/awx/ui/static/js/helpers/inventory.js +++ b/awx/ui/static/js/helpers/inventory.js @@ -179,7 +179,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi items: scope.treeController } }); - + $(tree_id).bind("loaded.jstree", function () { scope['treeLoading'] = false; scope.$emit('treeLoaded'); @@ -374,7 +374,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi // Call after GroupsEdit controller saves changes $('#tree-view').jstree('rename_node', node, name); node.attr('description', description); - scope = angular.element(getElementById('htmlTemplate')).scope(); + scope = angular.element(document.getElementById('htmlTemplate')).scope(); scope['selectedNodeName'] = name; } }]) @@ -450,7 +450,11 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi var form = InventoryForm; var defaultUrl=GetBasePath('inventory'); var scope = params.scope - + + form.well = false, + form.formLabelSize = 'col-lg-3'; + form.formFieldSize = 'col-lg-9'; + generator.inject(form, {mode: 'edit', modal: true, related: false}); ParseTypeChange(scope,'inventory_variables', 'inventoryParseType'); diff --git a/awx/ui/static/js/helpers/search.js b/awx/ui/static/js/helpers/search.js index 3508fc7560..bbbab6c1bc 100644 --- a/awx/ui/static/js/helpers/search.js +++ b/awx/ui/static/js/helpers/search.js @@ -112,6 +112,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) scope[iterator + 'Loading'] = true; scope[iterator + 'SearchParms'] = ''; var url = defaultUrl; + if ( (scope[iterator + 'SelectShow'] == false && scope[iterator + 'SearchValue'] != '' && scope[iterator + 'SearchValue'] != undefined) || (scope[iterator + 'SelectShow'] && scope[iterator + 'SearchSelectValue']) || (list.fields[scope[iterator + 'SearchField']].searchType && list.fields[scope[iterator + 'SearchField']].searchType == 'gtzero') ) { @@ -156,6 +157,11 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) else { scope[iterator + 'SearchParams'] = (sort_order) ? 'order_by=' + escape(sort_order) : ""; } + + if (iterator == 'inventory' && scope.inventoryFailureFilter) { + scope[iterator + 'SearchParams'] += '&has_active_failures=true'; + } + scope[iterator + 'Page'] = (page) ? parseInt(page) - 1 : 0; if (/\/$/.test(url)) { url += '?' + scope[iterator + 'SearchParams']; diff --git a/awx/ui/static/js/lists/Inventories.js b/awx/ui/static/js/lists/Inventories.js index 053f99e256..66f754b734 100644 --- a/awx/ui/static/js/lists/Inventories.js +++ b/awx/ui/static/js/lists/Inventories.js @@ -21,7 +21,11 @@ angular.module('InventoriesListDefinition', []) fields: { name: { key: true, - label: 'Name' + label: 'Name', + badgeShow: "\{\{ inventory.has_active_failures \}\}", + badgeIcon: 'icon-exclamation-sign', + badgeToolTip: 'Contains hosts with active job failures', + badgePlacement: 'bottom' }, description: { label: 'Description' @@ -32,7 +36,8 @@ angular.module('InventoriesListDefinition', []) sourceModel: 'organization', sourceField: 'name', excludeModal: true - }, + } + /*, has_active_failures: { label: 'Failed Jobs?', showValue: false, @@ -45,7 +50,7 @@ angular.module('InventoriesListDefinition', []) searchType: 'boolean', searchOptions: [{ name: "No", value: 0 }, { name: "Yes", value: 1 }], excludeModal: true - } + }*/ }, actions: { diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index c12eac4afc..dbdb538e66 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -179,8 +179,6 @@ a:hover { text-decoration: none; } - - .site-footer { width: 100%; padding-top: 20px; @@ -225,10 +223,6 @@ a:hover { text-align: center; } - - - - .login-header { text-align: center; } @@ -620,7 +614,7 @@ input[type="text"].job-successful { } - .host-badge { + .field-badge { color: @red; font-size: 12px; } diff --git a/awx/ui/static/lib/ansible/directives.js b/awx/ui/static/lib/ansible/directives.js index 8248a7f4e5..279489a7c5 100644 --- a/awx/ui/static/lib/ansible/directives.js +++ b/awx/ui/static/lib/ansible/directives.js @@ -533,7 +533,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos html += "" + data.results[i].name + " "; html += "" + - "\n"; + "\n"; } html = (html !== '') ? "\n" : ""; var compiled = $compile(html)(scope); @@ -580,7 +580,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos "> " + "{{ treeData[0].name }} " + "" + - "" + + "" + "\n" + "\n"; var compiled = $compile(html)(scope); diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js index cc0c36faed..fb21106c18 100644 --- a/awx/ui/static/lib/ansible/form-generator.js +++ b/awx/ui/static/lib/ansible/form-generator.js @@ -63,7 +63,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) // From here use 'scope' to manipulate the form, as the form is not in '$scope' $compile(element)(this.scope); - if (!options.buildTree == false && !options.html) { + if (!options.buildTree && !options.html) { // Reset the scope to prevent displaying old data from our last visit to this form for (var fld in form.fields) { this.scope[fld] = null; @@ -72,6 +72,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) this.scope[set] = null; } if ( ((!options.modal) && options.related) || this.form.forceListeners ) { + console.log('adding listeners'); this.addListeners(); } if (options.mode == 'add') { @@ -1052,20 +1053,6 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) } } - html += ""; - html += "
\n"; - html += "\n"; - html += "\n"; - html += "
\n"; - html += "\n"; - html += "\n"; // Message for when a related collection is empty diff --git a/awx/ui/static/lib/ansible/generator-helpers.js b/awx/ui/static/lib/ansible/generator-helpers.js index 5cf6245c50..0228477751 100644 --- a/awx/ui/static/lib/ansible/generator-helpers.js +++ b/awx/ui/static/lib/ansible/generator-helpers.js @@ -91,7 +91,38 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers']) } }) - .factory('Column', ['Attr', 'Icon', function(Attr, Icon) { + + .factory('DropDown', ['Attr', 'Icon', function(Attr, Icon) { + return function(params) { + + var list = params['list']; + var fld = params['fld']; + var options = params['options']; + var base = params['base']; + var field = list['fields'][fld]; + + html = "\n"; + html += "
\n"; + html += "\n"; + html += "\n"; + html += "
\n"; + html += "\n"; + + return html; + + } + }]) + + + .factory('Column', ['Attr', 'Icon', 'DropDown', function(Attr, Icon, DropDown) { return function(params) { var list = params['list']; var fld = params['fld']; @@ -101,93 +132,99 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers']) var field = list['fields'][fld]; var html = ''; - html += "" : ""; - - // Add collapse/expand icon --used on job_events page - if (list['hasChildren'] && field.hasChildren) { - html += " " + - " "; - } - - // Start the Link - if ((field.key || field.link || field.linkTo || field.ngClick ) && options['mode'] != 'lookup' && options['mode'] != 'select') { - if (field.linkTo) { - html += ""; - } - else if (field.ngClick) { - html += ""; - } - else if (field.link == undefined || field.link) { - html += ""; - } - } - - // Add icon: - if (field.ngShowIcon) { - html += " "; + if (field.type !== undefined && field.type == 'DropDown') { + html = DropDown(params); } else { - if (field.icon) { - html += Icon(field.icon) + " "; - } - } + html += "" : ""; + + // Add collapse/expand icon --used on job_events page + if (list['hasChildren'] && field.hasChildren) { + html += " " + + " "; + } - if (list['hasChildren'] && field.hasChildren) { - html += ""; - } - - // close the link - if ((field.key || field.link || field.linkTo || field.ngClick ) - && options.mode != 'lookup' && options.mode != 'select') { - html += ""; - } + // Start the Link + if ((field.key || field.link || field.linkTo || field.ngClick ) && options['mode'] != 'lookup' && options['mode'] != 'select') { + if (field.linkTo) { + html += ""; + } + else if (field.ngClick) { + html += ""; + } + else if (field.link == undefined || field.link) { + html += ""; + } + } - // close ngShow - html += (field.ngShow) ? "" : ""; - - // Specific to Job Events page -showing event detail/results - html += (field.appendHTML) ? "
\n" : ""; - - // Badge - if (field.badgeIcon) { - if (field.badgeToolTip) { - html += "
"; - html += " \n"; + // Add icon: + if (field.ngShowIcon) { + html += " "; } else { - html += " \n"; - } + if (field.icon) { + html += Icon(field.icon) + " "; + } + } + + // Add data binds + if (field.showValue == undefined || field.showValue == true) { + if (field.ngBind) { + html += "{{ " + field.ngBind + " }}"; + } + else { + html += "{{" + list.iterator + "." + fld + "}}"; + } + } + + // Add additional text: + if (field.text) { + html += field.text; + } + + if (list['hasChildren'] && field.hasChildren) { + html += ""; + } + + // close the link + if ((field.key || field.link || field.linkTo || field.ngClick ) + && options.mode != 'lookup' && options.mode != 'select') { + html += ""; + } + + // close ngShow + html += (field.ngShow) ? "" : ""; + + // Specific to Job Events page -showing event detail/results + html += (field.appendHTML) ? "
\n" : ""; + + // Badge + if (field.badgeIcon) { + if (field.badgeToolTip) { + html += "\n"; + } + else { + html += " \n"; + } + } } return html += "\n"; @@ -195,6 +232,7 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers']) } }]) + .factory('SearchWidget', function() { return function(params) { // diff --git a/awx/ui/static/lib/ansible/list-generator.js b/awx/ui/static/lib/ansible/list-generator.js index 52bac8dac6..7f3201abcf 100644 --- a/awx/ui/static/lib/ansible/list-generator.js +++ b/awx/ui/static/lib/ansible/list-generator.js @@ -142,6 +142,7 @@ angular.module('ListGenerator', ['GeneratorHelpers']) if (options.mode != 'lookup' && (list.well == undefined || list.well == 'true')) { html += "
\n"; } + if (options.mode == 'lookup' || options.id != undefined) { html += SearchWidget({ iterator: list.iterator, template: list, mini: true , size: 'col-lg-8' }); @@ -164,6 +165,12 @@ angular.module('ListGenerator', ['GeneratorHelpers']) } } } + + if (list.name == 'inventories' && options.mode !== 'select') { + html += "\n"; + } + //select instructions if (options.mode == 'select' && list.selectInstructions) { var btn = { diff --git a/awx/ui/templates/ui/index.html b/awx/ui/templates/ui/index.html index 7d8972d4ae..67c179234e 100644 --- a/awx/ui/templates/ui/index.html +++ b/awx/ui/templates/ui/index.html @@ -104,26 +104,25 @@ -