diff --git a/awx/ui/static/js/controllers/Home.js b/awx/ui/static/js/controllers/Home.js index ad863752dc..735604c501 100644 --- a/awx/ui/static/js/controllers/Home.js +++ b/awx/ui/static/js/controllers/Home.js @@ -95,12 +95,51 @@ function HomeGroups ($location, $routeParams, HomeGroupList, GenerateList, Proce SearchInit({ scope: scope, set: 'groups', list: list, url: defaultUrl }); PaginateInit({ scope: scope, list: list, url: defaultUrl }); + // Process search params if ($routeParams['has_active_failures']) { - scope[HomeGroupList.iterator + 'InputDisable'] = true; - scope[HomeGroupList.iterator + 'SearchValue'] = $routeParams['has_active_failures']; - scope[HomeGroupList.iterator + 'SearchField'] = 'has_active_failures'; - scope[HomeGroupList.iterator + 'SearchFieldLabel'] = HomeGroupList.fields['has_active_failures'].label; - scope[HomeGroupList.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 }; + scope[list.iterator + 'InputDisable'] = true; + scope[list.iterator + 'SearchValue'] = $routeParams['has_active_failures']; + scope[list.iterator + 'SearchField'] = 'has_active_failures'; + scope[list.iterator + 'SearchFieldLabel'] = list.fields['has_active_failures'].label; + scope[list.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 }; + } + + if ($routeParams['status'] && !$routeParams['source']) { + scope[list.iterator + 'SearchField'] = 'status'; + scope[list.iterator + 'SelectShow'] = true; + scope[list.iterator + 'SearchSelectOpts'] = list.fields['status'].searchOptions; + scope[list.iterator + 'SearchFieldLabel'] = list.fields['status'].label.replace(/\/g,' '); + for (var opt in list.fields['status'].searchOptions) { + if (list.fields['status'].searchOptions[opt].value == $routeParams['status']) { + scope[list.iterator + 'SearchSelectValue'] = list.fields['status'].searchOptions[opt]; + break; + } + } + } + + if ($routeParams['source']) { + scope[list.iterator + 'SearchField'] = 'source'; + scope[list.iterator + 'SelectShow'] = true; + scope[list.iterator + 'SearchSelectOpts'] = list.fields['source'].searchOptions; + scope[list.iterator + 'SearchFieldLabel'] = list.fields['source'].label.replace(/\/g,' '); + for (var opt in list.fields['source'].searchOptions) { + if (list.fields['source'].searchOptions[opt].value == $routeParams['source']) { + scope[list.iterator + 'SearchSelectValue'] = list.fields['source'].searchOptions[opt]; + break; + } + } + + if ($routeParams['status']) { + scope[list.iterator + 'ExtraParms'] = '&inventory_source__status__icontains=' + $routeParams['status']; + } + } + + if ($routeParams['has_external_source']) { + scope[list.iterator + 'SearchField'] = 'has_external_source'; + scope[list.iterator + 'SearchValue'] = list.fields['has_external_source'].searchValue; + scope[list.iterator + 'InputDisable'] = true; + scope[list.iterator + 'SearchType'] = 'in'; + scope[list.iterator + 'SearchFieldLabel'] = list.fields['has_external_source'].label; } scope.search(list.iterator); @@ -117,7 +156,7 @@ HomeGroups.$inject = [ '$location', '$routeParams', 'HomeGroupList', 'GenerateLi function HomeHosts ($location, $routeParams, HomeHostList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, - GetBasePath, SearchInit, PaginateInit, FormatDate, SetHostStatus, ToggleHostEnabled) { + GetBasePath, SearchInit, PaginateInit, FormatDate, SetHostStatus, ToggleHostEnabled, HostsEdit) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. @@ -156,10 +195,23 @@ function HomeHosts ($location, $routeParams, HomeHostList, GenerateList, Process scope.toggle_host_enabled = function(id, sources) { ToggleHostEnabled(id, sources, scope); } + scope.editHost = function(host_id, host_name) { + var host; + for (var i=0; i < scope['hosts'].length; i++) { + if (scope['hosts'][i].id == host_id) { + host = scope['hosts'][i]; + break; + } + } + if (host) { + HostsEdit({ host_id: host_id, inventory_id: host.inventory, group_id: null, hostsReload: false }); + } + } + } HomeGroups.$inject = [ '$location', '$routeParams', 'HomeGroupList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'HostsStatusMsg', 'UpdateStatusMsg', 'ViewUpdateStatus', - 'SetHostStatus', 'ToggleHostEnabled' + 'SetHostStatus', 'ToggleHostEnabled', 'HostsEdit' ]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index 5b17f45f98..55fba75cec 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -37,7 +37,6 @@ function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Res } if ($routeParams['has_active_failures']) { - //scope.resetSearch(InventoryHostsForm.iterator); scope[InventoryList.iterator + 'InputDisable'] = true; scope[InventoryList.iterator + 'SearchValue'] = $routeParams['has_active_failures']; scope[InventoryList.iterator + 'SearchField'] = 'has_active_failures'; @@ -45,6 +44,21 @@ function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Res scope[InventoryList.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 }; } + if ($routeParams['has_inventory_sources']) { + scope[InventoryList.iterator + 'InputDisable'] = true; + scope[InventoryList.iterator + 'SearchValue'] = $routeParams['has_inventory_sources']; + scope[InventoryList.iterator + 'SearchField'] = 'has_inventory_sources'; + scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields['has_inventory_sources'].label; + scope[InventoryList.iterator + 'SearchSelectValue'] = ($routeParams['has_inventory_sources'] == 'true') ? { value: 1 } : { value: 0 }; + } + + if ($routeParams['inventory_sources_with_failures']) { + // pass a value of true, however this field actually contains an integer value + scope[InventoryList.iterator + 'InputDisable'] = true; + scope[InventoryList.iterator + 'SearchField'] = 'inventory_sources_with_failures'; + scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields['inventory_sources_with_failures'].label; + } + scope.search(list.iterator); LoadBreadCrumbs(); diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js index bf28beb401..56ba78810f 100644 --- a/awx/ui/static/js/helpers/Groups.js +++ b/awx/ui/static/js/helpers/Groups.js @@ -393,7 +393,6 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' scope[list.iterator + 'InputDisable'] = true; scope[list.iterator + 'SearchType'] = 'in'; scope[list.iterator + 'SearchFieldLabel'] = list.fields['has_external_source'].label; - //=ec2,rackspace,file) } else if ($routeParams['status']) { // with status param, called post update-submit diff --git a/awx/ui/static/js/helpers/Hosts.js b/awx/ui/static/js/helpers/Hosts.js index 1b41de81d9..bf1d246e20 100644 --- a/awx/ui/static/js/helpers/Hosts.js +++ b/awx/ui/static/js/helpers/Hosts.js @@ -278,6 +278,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H var host_id = params.host_id; var inventory_id = params.inventory_id; var group_id = params.group_id; + var hostsReload = (params.hostsReload == undefined || params.hostsReload) ? true : false; var generator = GenerateForm; var form = HostForm; @@ -367,7 +368,9 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H function finished() { $('#form-modal').modal('hide'); - scope.$emit('hostsReload'); + if (hostsReload) { + scope.$emit('hostsReload'); + } } try { diff --git a/awx/ui/static/js/helpers/search.js b/awx/ui/static/js/helpers/search.js index 00fc5d7ee4..d9ac0443cf 100644 --- a/awx/ui/static/js/helpers/search.js +++ b/awx/ui/static/js/helpers/search.js @@ -25,57 +25,62 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) var list = params.list; var iterator = (params.iterator) ? params.iterator : list.iterator; var sort_order; - - // Set default values - for (fld in list.fields) { - if (list.fields[fld].key) { - if (list.fields[fld].sourceModel) { - var fka = list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField; - sort_order = (list.fields[fld].desc) ? '-' + fka : fka; - } - else { - sort_order = (list.fields[fld].desc) ? '-' + fld : fld; - } - if (list.fields[fld].searchable == undefined || list.fields[fld].searchable == true) { - scope[iterator + 'SearchField'] = fld; - scope[iterator + 'SearchFieldLabel'] = list.fields[fld].label; - } - break; + + function setDefaults() { + // Set default values + for (fld in list.fields) { + if (list.fields[fld].key) { + if (list.fields[fld].sourceModel) { + var fka = list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField; + sort_order = (list.fields[fld].desc) ? '-' + fka : fka; + } + else { + sort_order = (list.fields[fld].desc) ? '-' + fld : fld; + } + if (list.fields[fld].searchable == undefined || list.fields[fld].searchable == true) { + scope[iterator + 'SearchField'] = fld; + scope[iterator + 'SearchFieldLabel'] = list.fields[fld].label; + } + break; + } } - } - if (!scope[iterator + 'SearchField']) { - // A field marked as key may not be 'searchable' - for (fld in list.fields) { - if (list.fields[fld].searchable == undefined || list.fields[fld].searchable == true) { - scope[iterator + 'SearchField'] = fld; - scope[iterator + 'SearchFieldLabel'] = list.fields[fld].label; - break; + if (!scope[iterator + 'SearchField']) { + // A field marked as key may not be 'searchable' + for (fld in list.fields) { + if (list.fields[fld].searchable == undefined || list.fields[fld].searchable == true) { + scope[iterator + 'SearchField'] = fld; + scope[iterator + 'SearchFieldLabel'] = list.fields[fld].label; + break; + } } - } - } + } - scope[iterator + 'SearchType'] = 'icontains'; - scope[iterator + 'SearchTypeLabel'] = 'Contains'; - scope[iterator + 'SearchParams'] = ''; - scope[iterator + 'SearchValue'] = ''; - scope[iterator + 'SelectShow'] = false; // show/hide the Select - scope[iterator + 'HideSearchType'] = false; - scope[iterator + 'InputDisable'] = false; + scope[iterator + 'SearchType'] = 'icontains'; + scope[iterator + 'SearchTypeLabel'] = 'Contains'; + scope[iterator + 'SearchParams'] = ''; + scope[iterator + 'SearchValue'] = ''; + scope[iterator + 'SelectShow'] = false; // show/hide the Select + scope[iterator + 'HideSearchType'] = false; + scope[iterator + 'InputDisable'] = false; + scope[iterator + 'ExtraParms'] = ''; - var f = scope[iterator + 'SearchField'] - if (list.fields[f].searchType && ( list.fields[f].searchType == 'boolean' - || list.fields[f].searchType == 'select')) { - scope[iterator + 'SelectShow'] = true; - scope[iterator + 'SearchSelectOpts'] = list.fields[f].searchOptions; - } - if (list.fields[f].searchType && list.fields[f].searchType == 'int') { - scope[iterator + 'HideSearchType'] = true; - } - if (list.fields[f].searchType && list.fields[f].searchType == 'gtzero') { - scope[iterator + "InputHide"] = true; - } - + var f = scope[iterator + 'SearchField'] + if (list.fields[f].searchType && ( list.fields[f].searchType == 'boolean' + || list.fields[f].searchType == 'select')) { + scope[iterator + 'SelectShow'] = true; + scope[iterator + 'SearchSelectOpts'] = list.fields[f].searchOptions; + } + if (list.fields[f].searchType && list.fields[f].searchType == 'int') { + scope[iterator + 'HideSearchType'] = true; + } + if (list.fields[f].searchType && list.fields[f].searchType == 'gtzero') { + scope[iterator + "InputHide"] = true; + } + } + + setDefaults(); + // Functions to handle search widget changes scope.setSearchField = function(iterator, fld, label) { scope[iterator + 'SearchFieldLabel'] = label; @@ -126,12 +131,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) scope.resetSearch = function(iterator) { // Respdond to click of reset button - scope[iterator + "SearchValue"] = ''; - scope[iterator + "SearchSelectValue"] = ''; - scope[iterator + 'SelectShow'] = false; - scope[iterator + 'HideSearchType'] = false; - scope[iterator + 'InputHide'] = false; - scope[iterator + 'InputDisable'] = false; + setDefaults(); // Force removal of search keys from the URL window.location = '/#' + $location.path(); } @@ -224,6 +224,9 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) if (page) { url += '&page=' + page; } + if (scope[iterator + 'ExtraParms']) { + url += scope[iterator + 'ExtraParms']; + } Refresh({ scope: scope, set: set, iterator: iterator, url: url }); } diff --git a/awx/ui/static/js/lists/Inventories.js b/awx/ui/static/js/lists/Inventories.js index a65130fdae..f81b785a16 100644 --- a/awx/ui/static/js/lists/Inventories.js +++ b/awx/ui/static/js/lists/Inventories.js @@ -72,6 +72,11 @@ angular.module('InventoriesListDefinition', []) searchType: 'boolean', searchValue: 'true', searchOnly: true + }, + inventory_sources_with_failures: { + label: 'Has inventory update failures?', + searchType: 'gtzero', + searchOnly: true } }, diff --git a/awx/ui/static/js/widgets/InventorySyncStatus.js b/awx/ui/static/js/widgets/InventorySyncStatus.js index dc0066383f..c28ec1f983 100644 --- a/awx/ui/static/js/widgets/InventorySyncStatus.js +++ b/awx/ui/static/js/widgets/InventorySyncStatus.js @@ -20,7 +20,7 @@ angular.module('InventorySyncStatusWidget', ['RestServices', 'Utilities']) var hostCount = 0; var hostFails = 0; var counts = 0; - var expectedCounts = 4; + var expectedCounts = 5; var target = params.target; var results = []; var expected; @@ -71,15 +71,15 @@ angular.module('InventorySyncStatusWidget', ['RestServices', 'Utilities']) html += makeRow({ label: 'Inventories', count: inventoryCount, fail: inventoryFails, - link: GetBasePath('inventory'), - fail_link: GetBasePath('inventory') + '/?status=failed' }); + link: '/#/inventories/?has_inventory_sources=true', + fail_link: '/#/inventories/?inventory_sources_with_failures=true' }); rowcount++; } if (groupCount > 0) { html += makeRow({ label: 'Groups', count: groupCount, fail: groupFails, - link: '/#/home/groups/?has_inventory_sources=true', + link: '/#/home/groups/?has_external_source=true', fail_link: '/#/home/groups/?status=failed' }); rowcount++; } @@ -122,7 +122,17 @@ angular.module('InventorySyncStatusWidget', ['RestServices', 'Utilities']) { hdr: 'Error!', msg: 'Failed to get ' + url + '. GET status: ' + status }); }); - inventoryFails = 0; + var url = GetBasePath('inventory') + '?inventory_sources_with_failures__gt=0&page=1'; + Rest.setUrl(url); + Rest.get() + .success( function(data, status, headers, config) { + inventoryFails=data.count; + scope.$emit('CountReceived'); + }) + .error( function(data, status, headers, config) { + ProcessErrors(scope, data, status, null, + { hdr: 'Error!', msg: 'Failed to get ' + url + '. GET status: ' + status }); + }); url = GetBasePath('inventory_sources') + '?source__in=ec2,rackspace&page=1'; Rest.setUrl(url); @@ -215,7 +225,6 @@ angular.module('InventorySyncStatusWidget', ['RestServices', 'Utilities']) Rest.get() .success( function(data, status, headers, config) { // figure out the scm_type we're looking at and its label - console.log('config'); var label = getLabel(config); var count = data.count; var fail = 0; diff --git a/awx/ui/static/js/widgets/ObjectCount.js b/awx/ui/static/js/widgets/ObjectCount.js index e677e6b688..6c86e0571e 100644 --- a/awx/ui/static/js/widgets/ObjectCount.js +++ b/awx/ui/static/js/widgets/ObjectCount.js @@ -45,16 +45,30 @@ angular.module('ObjectCountWidget', ['RestServices', 'Utilities']) for (var i=0; i < keys.length; i++) { html += "\n"; html += "