From 77e79d9917a94ac8f1981c4cdacb9f747affaeba Mon Sep 17 00:00:00 2001 From: chouseknecht Date: Wed, 2 Oct 2013 02:08:04 -0400 Subject: [PATCH] AC-503 cloud inventory- first attempt at summary information on Inventory-> Groups page. Fixed compilation bugs. --- awx/ui/static/js/app.js | 1 + awx/ui/static/js/controllers/Groups.js | 7 +- awx/ui/static/js/controllers/Organizations.js | 2 +- awx/ui/static/js/helpers/Groups.js | 2 +- awx/ui/static/js/helpers/inventory.js | 63 ++++++++++++- awx/ui/static/js/lists/InventorySummary.js | 44 +++++++++ awx/ui/static/less/ansible-ui.less | 15 ++- awx/ui/static/lib/ansible/form-generator.js | 4 +- awx/ui/static/lib/ansible/list-generator.js | 93 ++++++++++--------- awx/ui/templates/ui/index.html | 1 + 10 files changed, 176 insertions(+), 56 deletions(-) create mode 100644 awx/ui/static/js/lists/InventorySummary.js diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js index 2a02013c9d..93e7668c5b 100644 --- a/awx/ui/static/js/app.js +++ b/awx/ui/static/js/app.js @@ -32,6 +32,7 @@ angular.module('ansible', [ 'InventoryHelper', 'InventoryHostsFormDefinition', 'InventoryGroupsFormDefinition', + 'InventorySummaryDefinition', 'AWFilters', 'HostFormDefinition', 'HostListDefinition', diff --git a/awx/ui/static/js/controllers/Groups.js b/awx/ui/static/js/controllers/Groups.js index d01b884a9b..abb803b8df 100644 --- a/awx/ui/static/js/controllers/Groups.js +++ b/awx/ui/static/js/controllers/Groups.js @@ -10,7 +10,7 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryGroupsForm, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, Prompt, TreeInit, GetBasePath, GroupsList, GroupsAdd, GroupsEdit, LoadInventory, - GroupsDelete, RefreshGroupName, EditInventory, SetShowGroupHelp) + GroupsDelete, RefreshGroupName, EditInventory, SetShowGroupHelp, InventoryStatus) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. @@ -155,7 +155,6 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP $('input:first').focus(); } else if (type == 'inventory') { - $('#tree-form').hide().empty(); url = node.attr('hosts'); scope.groupAddHide = true; scope.groupCreateHide = false; @@ -164,6 +163,8 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP scope.groupDeleteHide = true; scope.createButtonShow = false; scope.group_id = null; + InventoryStatus(); + $('#tree-form').show(); } if (!scope.$$phase) { @@ -221,6 +222,6 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP InventoryGroups.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryGroupsForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'Prompt', 'TreeInit', 'GetBasePath', 'GroupsList', 'GroupsAdd', 'GroupsEdit', 'LoadInventory', - 'GroupsDelete', 'RefreshGroupName', 'EditInventory', 'SetShowGroupHelp' + 'GroupsDelete', 'RefreshGroupName', 'EditInventory', 'SetShowGroupHelp', 'InventoryStatus' ]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/Organizations.js b/awx/ui/static/js/controllers/Organizations.js index 460c0e0e63..f325f8161f 100644 --- a/awx/ui/static/js/controllers/Organizations.js +++ b/awx/ui/static/js/controllers/Organizations.js @@ -91,7 +91,7 @@ function OrganizationsAdd ($scope, $rootScope, $compile, $location, $log, $route // Save scope.formSave = function() { - form.clearApiErrors();s + form.clearApiErrors(); var url = GetBasePath(base); url += (base != 'organizations') ? $routeParams['project_id'] + '/organizations/' : ''; Rest.setUrl(url); diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js index d84f69bdb9..f56e45d06d 100644 --- a/awx/ui/static/js/helpers/Groups.js +++ b/awx/ui/static/js/helpers/Groups.js @@ -232,7 +232,6 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' } }]) - .factory('GroupsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm', 'Prompt', 'ProcessErrors', 'GetBasePath', 'RefreshGroupName', 'ParseTypeChange', 'getSourceTypeOptions', function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, @@ -488,6 +487,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' { hdr: 'Error!', msg: 'Failed to update group varaibles. PUT status: ' + status }); }); } + RefreshGroupName(scope['selectedNode'], data.name, data.description); scope.$emit('formSaveSuccess', data.id); }) .error( function(data, status, headers, config) { diff --git a/awx/ui/static/js/helpers/inventory.js b/awx/ui/static/js/helpers/inventory.js index 2d14a08799..9682f9a80e 100644 --- a/awx/ui/static/js/helpers/inventory.js +++ b/awx/ui/static/js/helpers/inventory.js @@ -11,7 +11,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationListDefinition', 'SearchHelper', 'PaginateHelper', 'ListGenerator', 'AuthService', 'InventoryHelper', 'RelatedSearchHelper', 'RelatedPaginateHelper', - 'InventoryFormDefinition', 'ParseHelper' + 'InventoryFormDefinition', 'ParseHelper', 'InventorySummaryDefinition' ]) .factory('LoadTreeData', ['Alert', 'Rest', 'Authorization', '$http', 'Wait', 'SortNodes', @@ -160,6 +160,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi $(tree_id).bind("loaded.jstree", function () { scope['treeLoading'] = false; Wait('stop'); + $(tree_id).prepend('
Group Selector
'); scope.$emit('treeLoaded'); }); @@ -666,5 +667,65 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi } return newData; } + }]) + + .factory('InventoryStatus', [ 'Rest', 'Alert', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'InventorySummary', 'GenerateList', + function(Rest, Aler, ProcessErrors, GetBasePath, FormatDate, InventorySummary, GenerateList) { + return function(params) { + //Build a summary of a given inventory + + $('#tree-form').hide().empty(); + var view = GenerateList; + var scope = view.inject(InventorySummary, { mode: 'summary', id: 'tree-form', breadCrumbs: false }); + scope['groups'] = []; + + function checkSource(url) { + Rest.setUrl(url); + Rest.get() + .success( function(data, status, headers, config) { + //console.log(data); + var last_update = (data.last_updated == null) ? 'n/a' : FormatDate(new Date(data.last_updated)); + var source = 'Manual'; + switch(data.source) { + case 'file': + source = 'File'; + break; + case 'ec2': + source = 'Amazon EC2'; + break; + case 'rackspace': + source = 'Rackspace'; + break; + } + scope['groups'].push({ + name: data.summary_fields.group.name, + description: data.summary_fields.group.description, + failures: data.summary_fields.group.hosts_with_active_failures, + source: source, + last_update: last_update, + status: data.status + }); + }) + .error( function(data, status, headers, config) { + ProcessErrors(scope, data, status, null, + { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST status: ' + status }); + }); + } + + var url = GetBasePath('inventory') + scope['inventory_id'] + '/groups/'; + Rest.setUrl(url); + Rest.get() + .success( function(data, status, headers, config) { + for (var i=0; i < data.results.length; i++) { + if (data.results[i].related.inventory_source) { + checkSource(data.results[i].related.inventory_source); + } + } + }) + .error( function(data, status, headers, config) { + ProcessErrors(scope, data, status, null, + { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST status: ' + status }); + }); + } }]); diff --git a/awx/ui/static/js/lists/InventorySummary.js b/awx/ui/static/js/lists/InventorySummary.js new file mode 100644 index 0000000000..905320fa56 --- /dev/null +++ b/awx/ui/static/js/lists/InventorySummary.js @@ -0,0 +1,44 @@ +/********************************************* + * Copyright (c) 2013 AnsibleWorks, Inc. + * + * InventorySummary.js + * + * Summary of groups contained within an inventory + * + */ +angular.module('InventorySummaryDefinition', []) + .value( + 'InventorySummary', { + + name: 'groups', + iterator: 'group', + editTitle: 'Inventory Summary', + index: false, + hover: true, + + fields: { + name: { + key: true, + label: 'Name' + }, + failures: { + label: 'Hosts Failures' + }, + source: { + label: 'Source' + }, + last_update: { + label: 'Last Update' + }, + status: { + label: 'Update Status' + } + }, + + actions: { + }, + + fieldActions: { + } + }); + \ No newline at end of file diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index a01307505f..1b6d5d5cba 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -771,8 +771,15 @@ select.field-mini-height { border-radius: 6px; background-color: #e3e3e3; padding-top: 10px; - margin-top: 10px; + padding-left: 10px; + padding-bottom: 10px; min-height: 100px; + + .title { + color: #888; + padding-bottom: 5px; + margin-left: 5px; + } } /* @@ -792,13 +799,13 @@ select.field-mini-height { #tree-form { display: none; padding: 15px 10px 0 10px; - margin-top: 10px; + margin-top: 5px; border: 1px solid #e3e3e3; background-color: #e3e3e3; border-radius: 6px; .form-title { - color: #999; + color: #888; padding-left: 10px; } @@ -1102,7 +1109,7 @@ tr td button i { #tree-view { margin-left: 10px; - margin-top: 10px; + margin-top: 5px; } .label-text { diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js index 8d71c078df..0cc4c70e50 100644 --- a/awx/ui/static/lib/ansible/form-generator.js +++ b/awx/ui/static/lib/ansible/form-generator.js @@ -1230,7 +1230,9 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) html += "\n"; html += "
\n"; html += "
\n"; - html += "
\n"; + html += "
\n" + + "
\n" + + "
\n"; html += "
\n
\n
\n
\n"; html += "
\n"; html += "\n"; diff --git a/awx/ui/static/lib/ansible/list-generator.js b/awx/ui/static/lib/ansible/list-generator.js index c61fbac8da..ab88f902ee 100644 --- a/awx/ui/static/lib/ansible/list-generator.js +++ b/awx/ui/static/lib/ansible/list-generator.js @@ -169,56 +169,59 @@ 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' }); - } - else { - html += SearchWidget({ iterator: list.iterator, template: list, mini: true }); - } - if (options.mode != 'lookup') { - //actions - var base = $location.path().replace(/^\//,'').split('/')[0]; - html += "
\n"; - for (action in list.actions) { - if (list.actions[action].mode == 'all' || list.actions[action].mode == options.mode) { - if ( (list.actions[action].basePaths == undefined) || - (list.actions[action].basePaths && list.actions[action].basePaths.indexOf(base) > -1) ) { - html += this.button(list.actions[action], action); - } - } - } + if (options.mode !== 'summary') { - if (list.name == 'inventories' && options.mode !== 'select') { - html += "\n"; + if ( options.mode == 'lookup' || options.id != undefined ) { + html += SearchWidget({ iterator: list.iterator, template: list, mini: true , size: 'col-lg-8' }); } - - //select instructions - if (options.mode == 'select' && list.selectInstructions) { - var btn = { - awPopOver: list.selectInstructions, - dataPlacement: 'left', - dataContainer: 'body', - icon: "icon-question-sign", - 'class': 'btn-sm btn-help btn-info', - awToolTip: 'Click for help', - dataTitle: 'Help', - iconSize: 'large' - }; - html += this.button(btn, 'select'); + else { + html += SearchWidget({ iterator: list.iterator, template: list, mini: true }); } - } - else { - html += "
\n"; - } - html += "
\n"; - html += "
\n"; - + if (options.mode != 'lookup') { + //actions + var base = $location.path().replace(/^\//,'').split('/')[0]; + html += "
\n"; + for (action in list.actions) { + if (list.actions[action].mode == 'all' || list.actions[action].mode == options.mode) { + if ( (list.actions[action].basePaths == undefined) || + (list.actions[action].basePaths && list.actions[action].basePaths.indexOf(base) > -1) ) { + html += this.button(list.actions[action], action); + } + } + } + + if (list.name == 'inventories' && options.mode !== 'select') { + html += "\n"; + } + + //select instructions + if (options.mode == 'select' && list.selectInstructions) { + var btn = { + awPopOver: list.selectInstructions, + dataPlacement: 'left', + dataContainer: 'body', + icon: "icon-question-sign", + 'class': 'btn-sm btn-help btn-info', + awToolTip: 'Click for help', + dataTitle: 'Help', + iconSize: 'large' + }; + html += this.button(btn, 'select'); + } + } + else { + html += "
\n"; + } + + html += "
\n"; + html += "\n"; + } + // table header row html += " +