diff --git a/awx/ui/static/js/forms/JobTemplates.js b/awx/ui/static/js/forms/JobTemplates.js index 0a3e07a969..788883c1ba 100644 --- a/awx/ui/static/js/forms/JobTemplates.js +++ b/awx/ui/static/js/forms/JobTemplates.js @@ -257,7 +257,16 @@ angular.module('JobTemplateFormDefinition', []) index: false, open: false, - actions: { + actions: { + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('job')", + iconSize: 'large' + } }, fields: { diff --git a/awx/ui/static/js/forms/Organizations.js b/awx/ui/static/js/forms/Organizations.js index 273c678552..1cc07304cc 100644 --- a/awx/ui/static/js/forms/Organizations.js +++ b/awx/ui/static/js/forms/Organizations.js @@ -62,6 +62,15 @@ angular.module('OrganizationFormDefinition', []) label: 'Add', icon: 'icon-plus', awToolTip: 'Add a new user' + }, + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('user')", + iconSize: 'large' } }, @@ -108,6 +117,15 @@ angular.module('OrganizationFormDefinition', []) icon: 'icon-plus', label: 'Add', awToolTip: 'Add new administrator' + }, + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('admin')", + iconSize: 'large' } }, fields: { diff --git a/awx/ui/static/js/forms/Projects.js b/awx/ui/static/js/forms/Projects.js index 4e15fb1154..778f7d30ad 100644 --- a/awx/ui/static/js/forms/Projects.js +++ b/awx/ui/static/js/forms/Projects.js @@ -215,6 +215,15 @@ angular.module('ProjectFormDefinition', []) icon: 'icon-plus', label: 'Add', awToolTip: 'Add an organization' + }, + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('organization')", + iconSize: 'large' } }, diff --git a/awx/ui/static/js/forms/Teams.js b/awx/ui/static/js/forms/Teams.js index d2ae7d2696..17056307ab 100644 --- a/awx/ui/static/js/forms/Teams.js +++ b/awx/ui/static/js/forms/Teams.js @@ -74,6 +74,15 @@ angular.module('TeamFormDefinition', []) icon: 'icon-plus', label: 'Add', add: 'Add a new credential' + }, + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('credential')", + iconSize: 'large' } }, @@ -118,6 +127,15 @@ angular.module('TeamFormDefinition', []) label: 'Add', awToolTip: 'Add a permission for this user', ngShow: 'PermissionAddAllowed' + }, + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('permission')", + iconSize: 'large' } }, @@ -176,6 +194,15 @@ angular.module('TeamFormDefinition', []) ngClick: "add('projects')", icon: 'icon-plus', label: 'Add' + }, + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('project')", + iconSize: 'large' } }, @@ -219,6 +246,15 @@ angular.module('TeamFormDefinition', []) icon: 'icon-plus', label: 'Add', awToolTip: 'Add a user' + }, + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('user')", + iconSize: 'large' } }, diff --git a/awx/ui/static/js/forms/Users.js b/awx/ui/static/js/forms/Users.js index 25cbf7a86e..ec04dd9326 100644 --- a/awx/ui/static/js/forms/Users.js +++ b/awx/ui/static/js/forms/Users.js @@ -122,6 +122,15 @@ angular.module('UserFormDefinition', []) icon: 'icon-plus', label: 'Add', awToolTip: 'Add a credential for this user' + }, + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('credential')", + iconSize: 'large' } }, @@ -166,6 +175,15 @@ angular.module('UserFormDefinition', []) label: 'Add', awToolTip: 'Add a permission for this user', ngShow: 'PermissionAddAllowed' + }, + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('permission')", + iconSize: 'large' } }, @@ -221,6 +239,18 @@ angular.module('UserFormDefinition', []) open: false, // Open accordion on load? base: '/organizations', + actions: { + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('adminof')", + iconSize: 'large' + } + }, + fields: { name: { key: true, @@ -238,6 +268,18 @@ angular.module('UserFormDefinition', []) iterator: 'organization', open: false, + actions: { + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('organization')", + iconSize: 'large' + } + }, + fields: { name: { key: true, @@ -255,6 +297,18 @@ angular.module('UserFormDefinition', []) iterator: 'team', open: false, + actions: { + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('team')", + iconSize: 'large' + } + }, + fields: { name: { key: true, @@ -272,6 +326,18 @@ angular.module('UserFormDefinition', []) iterator: 'project', open: false, + actions: { + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch('project')", + iconSize: 'large' + } + }, + fields: { name: { key: true, diff --git a/awx/ui/static/js/helpers/refresh-related.js b/awx/ui/static/js/helpers/refresh-related.js index 1b6122971e..ffb968c51e 100644 --- a/awx/ui/static/js/helpers/refresh-related.js +++ b/awx/ui/static/js/helpers/refresh-related.js @@ -22,7 +22,7 @@ angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities']) var set = params.set; var iterator = params.iterator; var url = params.url; - + Rest.setUrl(url); Rest.get() .success( function(data, status, headers, config) { @@ -33,6 +33,7 @@ angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities']) scope[iterator + 'PageCount'] = Math.ceil((data.count / scope[iterator + 'PageSize'])); scope[iterator + 'SearchSpin'] = false; scope[iterator + 'Loading'] = false; + scope[iterator + 'HoldInput'] = false; scope.$emit('related' + set); if (!params.scope.$$phase) { params.scope.$digest(); diff --git a/awx/ui/static/js/helpers/related-search.js b/awx/ui/static/js/helpers/related-search.js index b0e75f98cf..7df0d59c49 100644 --- a/awx/ui/static/js/helpers/related-search.js +++ b/awx/ui/static/js/helpers/related-search.js @@ -16,7 +16,7 @@ */ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelatedHelper']) - .factory('RelatedSearchInit', ['Alert', 'Rest', 'RefreshRelated', function(Alert, Rest, RefreshRelated) { + .factory('RelatedSearchInit', ['$timeout', 'Alert', 'Rest', 'RefreshRelated', function($timeout, Alert, Rest, RefreshRelated) { return function(params) { var scope = params.scope; @@ -24,36 +24,46 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat var form = params.form; // Set default values - var iterator, f; - for (var set in form.related) { - if (form.related[set].type != 'tree') { - iterator = form.related[set].iterator; - for (var fld in form.related[set].fields) { - if (form.related[set].fields[fld].key) { - scope[iterator + 'SearchField'] = fld - scope[iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label; - break; + function setDefaults(inIterator) { + var iterator, f; + for (var set in form.related) { + if (form.related[set].type != 'tree' && (inIterator === undefined || inIterator == form.related[set].iterator)) { + iterator = form.related[set].iterator; + for (var fld in form.related[set].fields) { + if (form.related[set].fields[fld].key) { + scope[iterator + 'SearchField'] = fld + scope[iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label; + break; + } + } + scope[iterator + 'SortOrder'] = null; + scope[iterator + 'SearchType'] = 'icontains'; + scope[iterator + 'SearchTypeLabel'] = 'Contains'; + scope[iterator + 'SearchValue'] = null; + scope[iterator + 'SelectShow'] = false; + scope[iterator + 'HideSearchType'] = false; + f = scope[iterator + 'SearchField'] + if (form.related[set].fields[f].searchType && ( form.related[set].fields[f].searchType == 'boolean' + || form.related[set].fields[f].searchType == 'select')) { + scope[iterator + 'SelectShow'] = true; + scope[iterator + 'SearchSelectOpts'] = list.fields[f].searchOptions; + } + if (form.related[set].fields[f].searchType && form.related[set].fields[f].searchType == 'int') { + scope[iterator + 'HideSearchType'] = true; + } + if (form.related[set].fields[f].searchType && form.related[set].fields[f].searchType == 'gtzero') { + scope[iterator + "InputHide"] = true; } } - scope[iterator + 'SortOrder'] = null; - scope[iterator + 'SearchType'] = 'contains'; - scope[iterator + 'SearchTypeLabel'] = 'Contains'; - scope[iterator + 'SelectShow'] = false; - scope[iterator + 'HideSearchType'] = false; - f = scope[iterator + 'SearchField'] - if (form.related[set].fields[f].searchType && ( form.related[set].fields[f].searchType == 'boolean' - || form.related[set].fields[f].searchType == 'select')) { - scope[iterator + 'SelectShow'] = true; - scope[iterator + 'SearchSelectOpts'] = list.fields[f].searchOptions; - } - if (form.related[set].fields[f].searchType && form.related[set].fields[f].searchType == 'int') { - scope[iterator + 'HideSearchType'] = true; - } - if (form.related[set].fields[f].searchType && form.related[set].fields[f].searchType == 'gtzero') { - scope[iterator + "InputHide"] = true; - } + } + } + + setDefaults(); + + scope.resetSearch = function(iterator) { + setDefaults(iterator); + scope.search(iterator); } - } // Functions to handle search widget changes scope.setSearchField = function(iterator, fld, label) { @@ -93,9 +103,23 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat scope.search(model); } + scope.startSearch = function(iterator) { + //Called on each keydown event for seachValue field. Using a timer + //to prevent executing a search until user is finished typing. + if (scope.searchTimer) { + $timeout.cancel(scope.searchTimer); + } + scope.searchTimer = $timeout( + function() { + scope.search(iterator); + } + , 1000); + } + scope.search = function(iterator) { scope[iterator + 'SearchSpin'] = true; scope[iterator + 'Loading'] = true; + scope[iterator + 'HoldInput'] = true; if (iterator == 'host') { if (scope['hostSearchField'] == 'has_active_failures') { @@ -126,7 +150,7 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat break; } } - + sort_order = (scope[iterator + 'SortOrder'] == null) ? sort_order : scope[iterator + 'SortOrder']; var f = form.related[set].fields[scope[iterator + 'SearchField']]; diff --git a/awx/ui/static/js/helpers/search.js b/awx/ui/static/js/helpers/search.js index f3edabcdfc..8806aba8e4 100644 --- a/awx/ui/static/js/helpers/search.js +++ b/awx/ui/static/js/helpers/search.js @@ -182,7 +182,6 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) window.location = '/#' + $location.path(); scope.search(iterator); } - if (scope.removeDoSearch) { scope.removeDoSearch(); diff --git a/awx/ui/static/js/lists/Organizations.js b/awx/ui/static/js/lists/Organizations.js index 39c6501faa..6241625515 100644 --- a/awx/ui/static/js/lists/Organizations.js +++ b/awx/ui/static/js/lists/Organizations.js @@ -36,6 +36,15 @@ angular.module('OrganizationListDefinition', []) "class": 'btn-success btn-xs', awToolTip: 'Create a new organization' }, + reset: { + dataPlacement: 'top', + icon: "icon-undo", + mode: 'all', + 'class': 'btn-xs btn-primary', + awToolTip: "Reset the search filter", + ngClick: "resetSearch()", + iconSize: 'large' + }, stream: { 'class': "btn-primary btn-xs activity-btn", ngClick: "showActivity()", diff --git a/awx/ui/static/js/widgets/Stream.js b/awx/ui/static/js/widgets/Stream.js index 3274f19947..433a5a0879 100644 --- a/awx/ui/static/js/widgets/Stream.js +++ b/awx/ui/static/js/widgets/Stream.js @@ -184,9 +184,9 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti .factory('Stream', ['$rootScope', '$location', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', 'StreamList', 'SearchInit', 'PaginateInit', 'GenerateList', 'FormatDate', 'ShowStream', 'HideStream', 'BuildDescription', 'FixUrl', 'BuildUrl', - 'ShowDetail', + 'ShowDetail', 'LoadBreadCrumbs', function($rootScope, $location, Rest, GetBasePath, ProcessErrors, Wait, StreamList, SearchInit, PaginateInit, GenerateList, - FormatDate, ShowStream, HideStream, BuildDescription, FixUrl, BuildUrl, ShowDetail) { + FormatDate, ShowStream, HideStream, BuildDescription, FixUrl, BuildUrl, ShowDetail, LoadBreadCrumbs) { return function(params) { var list = StreamList; @@ -207,6 +207,10 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti $('#tab-content-container').append('
'); ShowStream(); + if ($rootScope.breadcrumbs.length == 0) { + var title = base.substr(0,1).toUpperCase() + base.substr(1); + $rootScope.breadcrumbs.push({ path: $location.path(), title: title}); + } // Generate the list var scope = view.inject(list, {