From 5b6eba7f93e73def8dd4e8eb7265533872cd9eeb Mon Sep 17 00:00:00 2001 From: Chris Houseknecht Date: Wed, 20 Nov 2013 09:03:01 +0000 Subject: [PATCH] AC-665 Added governor to object type searches, limiting objects to 30. Now using 'working' spinner in place of small spinner. No more auto search. Replaced the auto search with Go button and Enter key. --- awx/ui/static/js/helpers/refresh-related.js | 8 ++-- awx/ui/static/js/helpers/refresh.js | 8 ++-- awx/ui/static/js/helpers/related-search.js | 20 ++++----- awx/ui/static/js/helpers/search.js | 43 ++++++++++++------- awx/ui/static/lib/ansible/form-generator.js | 2 +- .../static/lib/ansible/generator-helpers.js | 27 ++++++------ awx/ui/static/lib/ansible/list-generator.js | 8 ++-- 7 files changed, 65 insertions(+), 51 deletions(-) diff --git a/awx/ui/static/js/helpers/refresh-related.js b/awx/ui/static/js/helpers/refresh-related.js index ffb968c51e..482fb39544 100644 --- a/awx/ui/static/js/helpers/refresh-related.js +++ b/awx/ui/static/js/helpers/refresh-related.js @@ -15,7 +15,7 @@ */ angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities']) - .factory('RefreshRelated', ['ProcessErrors', 'Rest', function(ProcessErrors, Rest) { + .factory('RefreshRelated', ['ProcessErrors', 'Rest', 'Wait', function(ProcessErrors, Rest, Wait) { return function(params) { var scope = params.scope; @@ -26,12 +26,13 @@ angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities']) Rest.setUrl(url); Rest.get() .success( function(data, status, headers, config) { + Wait('stop'); scope[set] = data['results']; scope[iterator + 'NextUrl'] = data.next; scope[iterator + 'PrevUrl'] = data.previous; scope[iterator + 'Count'] = data.count; scope[iterator + 'PageCount'] = Math.ceil((data.count / scope[iterator + 'PageSize'])); - scope[iterator + 'SearchSpin'] = false; + //scope[iterator + 'SearchSpin'] = false; scope[iterator + 'Loading'] = false; scope[iterator + 'HoldInput'] = false; scope.$emit('related' + set); @@ -40,7 +41,8 @@ angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities']) } }) .error ( function(data, status, headers, config) { - scope[iterator + 'SearchSpin'] = true; + Wait('stop'); + //scope[iterator + 'SearchSpin'] = true; ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve ' + set + '. GET returned status: ' + status }); }); diff --git a/awx/ui/static/js/helpers/refresh.js b/awx/ui/static/js/helpers/refresh.js index 5cbc3b95be..e6b4d25c50 100644 --- a/awx/ui/static/js/helpers/refresh.js +++ b/awx/ui/static/js/helpers/refresh.js @@ -15,7 +15,7 @@ */ angular.module('RefreshHelper', ['RestServices', 'Utilities']) - .factory('Refresh', ['ProcessErrors', 'Rest', function(ProcessErrors, Rest) { + .factory('Refresh', ['ProcessErrors', 'Rest', 'Wait', function(ProcessErrors, Rest, Wait) { return function(params) { var scope = params.scope; @@ -27,11 +27,12 @@ angular.module('RefreshHelper', ['RestServices', 'Utilities']) Rest.setUrl(url); Rest.get() .success( function(data, status, headers, config) { + Wait('stop'); scope[iterator + 'NextUrl'] = data.next; scope[iterator + 'PrevUrl'] = data.previous; scope[iterator + 'Count'] = data.count; scope[iterator + 'PageCount'] = Math.ceil((data.count / scope[iterator + 'PageSize'])); - scope[iterator + 'SearchSpin'] = false; + //scope[iterator + 'SearchSpin'] = false; scope[iterator + 'Loading'] = false; for (var i=1; i <= 3; i++) { var modifier = (i == 1) ? '' : i; @@ -41,7 +42,8 @@ angular.module('RefreshHelper', ['RestServices', 'Utilities']) scope.$emit('PostRefresh'); }) .error ( function(data, status, headers, config) { - scope[iterator + 'SearchSpin'] = false; + Wait('stop'); + //scope[iterator + 'SearchSpin'] = false; scope[iterator + 'HoldInput'] = false; ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve ' + set + '. GET returned status: ' + status }); diff --git a/awx/ui/static/js/helpers/related-search.js b/awx/ui/static/js/helpers/related-search.js index 7df0d59c49..a1373529a6 100644 --- a/awx/ui/static/js/helpers/related-search.js +++ b/awx/ui/static/js/helpers/related-search.js @@ -16,7 +16,8 @@ */ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelatedHelper']) - .factory('RelatedSearchInit', ['$timeout', 'Alert', 'Rest', 'RefreshRelated', function($timeout, Alert, Rest, RefreshRelated) { + .factory('RelatedSearchInit', ['$timeout', 'Alert', 'Rest', 'RefreshRelated', 'Wait', + function($timeout, Alert, Rest, RefreshRelated, Wait) { return function(params) { var scope = params.scope; @@ -103,21 +104,16 @@ 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.startSearch = function(e,iterator) { + // If use clicks enter while on input field, start the search + if (e.keyCode == 13) { + scope.search(iterator); } - scope.searchTimer = $timeout( - function() { - scope.search(iterator); - } - , 1000); } scope.search = function(iterator) { - scope[iterator + 'SearchSpin'] = true; + //scope[iterator + 'SearchSpin'] = true; + Wait('start'); scope[iterator + 'Loading'] = true; scope[iterator + 'HoldInput'] = true; diff --git a/awx/ui/static/js/helpers/search.js b/awx/ui/static/js/helpers/search.js index 8806aba8e4..bcbfb9e423 100644 --- a/awx/ui/static/js/helpers/search.js +++ b/awx/ui/static/js/helpers/search.js @@ -16,8 +16,8 @@ */ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) - .factory('SearchInit', ['Alert', 'Rest', 'Refresh', '$location', 'GetBasePath', 'Empty', '$timeout', - function(Alert, Rest, Refresh, $location, GetBasePath, Empty, $timeout) { + .factory('SearchInit', ['Alert', 'Rest', 'Refresh', '$location', 'GetBasePath', 'Empty', '$timeout', 'Wait', + function(Alert, Rest, Refresh, $location, GetBasePath, Empty, $timeout, Wait) { return function(params) { var scope = params.scope; @@ -190,7 +190,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) // // Execute the search // - scope[iterator + 'SearchSpin'] = (spin == undefined || spin == true) ? true : false; + //scope[iterator + 'SearchSpin'] = (spin == undefined || spin == true) ? true : false; scope[iterator + 'Loading'] = (load == undefined || load == true) ? true : false; var url = defaultUrl; @@ -233,6 +233,15 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) } }); + if (scope.removeResultWarning) { + scope.removeResultWarning(); + } + scope.removeResultWarning = scope.$on('resultWarning', function(e, objs, length) { + // Alert the user that the # of objects was greater than 30 + var label = (objs == 'inventory') ? 'inventories' : objs.replace(/s$/,''); + Alert('Warning', 'The number of matching ' + label + ' was too large. We limited your search to the first 30.', 'alert-info'); + }); + if (scope.removePrepareSearch) { scope.removePrepareSearch(); } @@ -241,6 +250,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) // Start build the search key/value pairs. This will process search widget, if the // selected field is an object type (used on activity stream). // + Wait('start'); scope[iterator + 'SearchParams'] = ''; var widgets = (list.searchWidgets) ? list.searchWidgets : 1; var modifier; @@ -258,7 +268,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) expected_objects++; } } - + for (var i=1; i <= widgets; i++) { var modifier = (i == 1) ? '' : i; if ( $('#search-widget-container' + modifier) ) { @@ -270,18 +280,25 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) var objUrl = GetBasePath('base') + objs + '/?name__icontains=' + scope[iterator + 'SearchValue' + modifier]; Rest.setUrl(objUrl); Rest.setHeader({ widget: i }); + Rest.setHeader({ object: objs }); Rest.get() .success( function(data, status, headers, config) { var pk=''; - for (var j=0; j < data.results.length; j++) { + //limit result set to 30 + var len = (data.results.length > 30) ? 30 : data.results.length; + for (var j=0; j < len; j++) { pk += "," + data.results[j].id; } pk = pk.replace(/^\,/,''); scope.$emit('foundObject', iterator, page, load, spin, config.headers['widget'], pk); + if (data.results.length > 30) { + scope.$emit('resultWarning', config.headers['object'], data.results.length); + } }) .error( function(data, status, headers, config) { + Wait('stop'); ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Retrieving list of ' + obj + ' where name contains: ' + scope[iterator + 'SearchValue'] + + { hdr: 'Error!', msg: 'Retrieving list of ' + objs + ' where name contains: ' + scope[iterator + 'SearchValue' + modifier] + ' GET returned status: ' + status }); }); } @@ -395,17 +412,11 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) scope.$emit('doSearch', iterator, page, load, spin); }); - 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.startSearch = function(e,iterator) { + // If use clicks enter while on input field, start the search + if (e.keyCode == 13) { + scope.search(iterator); } - scope.searchTimer = $timeout( - function() { - scope.$emit('prepareSearch', iterator); - } - , 1000); } scope.search = function(iterator, page, load, spin) { diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js index 5ca21ad428..641ffbaa3b 100644 --- a/awx/ui/static/lib/ansible/form-generator.js +++ b/awx/ui/static/lib/ansible/form-generator.js @@ -1500,7 +1500,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) html += "
\n"; html += SearchWidget({ iterator: form.related[itm].iterator, template: form.related[itm], mini: true }); - html += "
\n"; + html += "
\n"; html += "
\n"; for (var act in form.related[itm].actions) { var action = form.related[itm].actions[act]; diff --git a/awx/ui/static/lib/ansible/generator-helpers.js b/awx/ui/static/lib/ansible/generator-helpers.js index 06eb0a71a8..6e4aa32a76 100644 --- a/awx/ui/static/lib/ansible/generator-helpers.js +++ b/awx/ui/static/lib/ansible/generator-helpers.js @@ -524,26 +524,29 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers']) html += "\">\n"; html += "\n"; + "class=\"form-control\" ng-model=\"" + iterator + "SearchValue" + modifier + "\" " + + "aw-placeholder=\"" + iterator + "SearchPlaceholder" + modifier + "\" type=\"text\" ng-disabled=\"" + iterator + + "InputDisable" + modifier + " || " + iterator + "HoldInput" + modifier + "\" ng-keypress=\"startSearch($event,'" + + iterator + "')\">\n"; - // Reset button - //html += "
\n"; - //html += "\n"; - //html += "
\n"; + // Go button + html += "
\n"; + html += "\n"; + html += "
\n"; + html += "
\n"; html += "
\n"; } // Reset button and spinner - html += "
\n"; + //html += "
\n"; //html += "\n"; - html += "\n"; - html += "
\n"; + //html += "\n"; + //html += "
\n"; return html; diff --git a/awx/ui/static/lib/ansible/list-generator.js b/awx/ui/static/lib/ansible/list-generator.js index 27e6dae01c..0dc3586f6c 100644 --- a/awx/ui/static/lib/ansible/list-generator.js +++ b/awx/ui/static/lib/ansible/list-generator.js @@ -227,16 +227,16 @@ angular.module('ListGenerator', ['GeneratorHelpers']) // User supplied searchSize, calc the remaining var size = parseInt(options.searchSize.replace(/([A-Z]|[a-z]|\-)/g,'')); size = (list.searchWidgets) ? list.searchWidgets * size : size; - html += 'col-lg-' + (12 - size - 1); + html += 'col-lg-' + (12 - size); } else if (options.mode == 'summary') { - html += 'col-lg-5'; + html += 'col-lg-6'; } else if (options.id != undefined) { - html += "col-lg-3"; + html += "col-lg-4"; } else { - html += "col-lg-7 col-md-5"; + html += "col-lg-8 col-md-6"; } html += "\">\n";