From c459e326b29d379a97896a4cbadfe843f65698cc Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Mon, 13 Feb 2017 14:55:34 -0500 Subject: [PATCH] UI work to incorporate related_search_fields as valid fields when searching --- .../smart-search/django-search-model.class.js | 53 +++++-------------- .../shared/smart-search/queryset.service.js | 45 ++++++---------- .../smart-search/smart-search.controller.js | 27 ++++------ .../smart-search/smart-search.partial.html | 2 +- 4 files changed, 43 insertions(+), 84 deletions(-) diff --git a/awx/ui/client/src/shared/smart-search/django-search-model.class.js b/awx/ui/client/src/shared/smart-search/django-search-model.class.js index 5271a38a30..81984e662e 100644 --- a/awx/ui/client/src/shared/smart-search/django-search-model.class.js +++ b/awx/ui/client/src/shared/smart-search/django-search-model.class.js @@ -1,28 +1,3 @@ -// Ignored fields are not surfaced in the UI's search key -let isIgnored = function(key, value) { - let ignored = [ - 'type', - 'url', - 'related', - 'summary_fields', - 'object_roles', - 'activity_stream', - 'update', - 'teams', - 'users', - 'owner_teams', - 'owner_users', - 'access_list', - 'notification_templates_error', - 'notification_templates_success', - 'ad_hoc_command_events', - 'fact_versions', - 'variable_data', - 'playbooks' - ]; - return ignored.indexOf(key) > -1 || value.type === 'field'; -}; - export default class DjangoSearchModel { /* @@ -36,21 +11,21 @@ class DjangoSearchModel { } @@property related ['field' ...] */ - constructor(name, endpoint, baseFields, relations) { - let base = {}; + constructor(name, baseFields, relatedSearchFields) { + function trimRelated(relatedSearchField){ + return relatedSearchField.replace(/\__search$/, ""); + } this.name = name; - this.related = _.reject(relations, isIgnored); - _.forEach(baseFields, (value, key) => { - if (!isIgnored(key, value)) { - base[key] = value; + this.related = _.map(relatedSearchFields, trimRelated); + // Remove "object" type fields from this list + for (var key in baseFields) { + if (baseFields.hasOwnProperty(key)) { + if (baseFields[key].type === 'object'){ + delete baseFields[key]; + } } - }); - this.base = base; - } - - fields() { - let result = this.base; - result.related = this.related; - return result; + } + delete baseFields.url; + this.base = baseFields; } } diff --git a/awx/ui/client/src/shared/smart-search/queryset.service.js b/awx/ui/client/src/shared/smart-search/queryset.service.js index 10ae7ef3c8..35f2b088f1 100644 --- a/awx/ui/client/src/shared/smart-search/queryset.service.js +++ b/awx/ui/client/src/shared/smart-search/queryset.service.js @@ -1,42 +1,31 @@ -export default ['$q', 'Rest', 'ProcessErrors', '$rootScope', 'Wait', 'DjangoSearchModel', '$cacheFactory', 'SmartSearchService', - function($q, Rest, ProcessErrors, $rootScope, Wait, DjangoSearchModel, $cacheFactory, SmartSearchService) { +export default ['$q', 'Rest', 'ProcessErrors', '$rootScope', 'Wait', 'DjangoSearchModel', 'SmartSearchService', + function($q, Rest, ProcessErrors, $rootScope, Wait, DjangoSearchModel, SmartSearchService) { return { // kick off building a model for a specific endpoint // this is usually a list's basePath // unified_jobs is the exception, where we need to fetch many subclass OPTIONS and summary_fields - initFieldset(path, name, relations) { - // get or set $cachFactory.Cache object with id '$http' - let defer = $q.defer(), - cache = $cacheFactory.get('$http') || $cacheFactory('$http'); - defer.resolve(this.getCommonModelOptions(path, name, relations, cache)); + initFieldset(path, name) { + let defer = $q.defer(); + defer.resolve(this.getCommonModelOptions(path, name)); return defer.promise; }, - getCommonModelOptions(path, name, relations, cache) { + getCommonModelOptions(path, name) { let resolve, base, defer = $q.defer(); - // grab a single model from the cache, if present - if (cache.get(path)) { - defer.resolve({ - models: { - [name] : new DjangoSearchModel(name, path, cache.get(path), relations) - }, - options: cache.get(path) - }); - } else { - this.url = path; - resolve = this.options(path) - .then((res) => { - base = res.data.actions.GET; - defer.resolve({ - models: { - [name]: new DjangoSearchModel(name, path, base, relations) - }, - options: res - }); + this.url = path; + resolve = this.options(path) + .then((res) => { + base = res.data.actions.GET; + let relatedSearchFields = res.data.related_search_fields; + defer.resolve({ + models: { + [name]: new DjangoSearchModel(name, base, relatedSearchFields) + }, + options: res }); - } + }); return defer.promise; }, diff --git a/awx/ui/client/src/shared/smart-search/smart-search.controller.js b/awx/ui/client/src/shared/smart-search/smart-search.controller.js index bbac64b37d..506613c125 100644 --- a/awx/ui/client/src/shared/smart-search/smart-search.controller.js +++ b/awx/ui/client/src/shared/smart-search/smart-search.controller.js @@ -1,7 +1,7 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', 'QuerySet', 'SmartSearchService', 'i18n', function($stateParams, $scope, $state, QuerySet, GetBasePath, qs, SmartSearchService, i18n) { - let path, relations, + let path, defaults, queryset, stateChangeSuccessListener; @@ -28,9 +28,8 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', ' function init() { path = GetBasePath($scope.basePath) || $scope.basePath; - relations = getRelationshipFields($scope.dataset.results); $scope.searchTags = stripDefaultParams($state.params[`${$scope.iterator}_search`]); - qs.initFieldset(path, $scope.djangoModel, relations).then((data) => { + qs.initFieldset(path, $scope.djangoModel).then((data) => { $scope.models = data.models; $scope.options = data.options.data; $scope.$emit(`${$scope.list.iterator}_options`, data.options); @@ -107,14 +106,6 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', ' return _(strippedCopy).map(qs.decodeParam).flatten().value(); } - // searchable relationships - function getRelationshipFields(dataset) { - let flat = _(dataset).map((value) => { - return _.keys(value.related); - }).flatten().uniq().value(); - return flat; - } - function setDefaults(term) { if ($scope.list.defaultSearchParams) { return $scope.list.defaultSearchParams(term); @@ -175,8 +166,8 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', ' let encodeParams = { term: tagToRemove }; - if(_.has($scope.options.actions.GET, root)) { - if($scope.options.actions.GET[root].type && $scope.options.actions.GET[root].type === 'field') { + if(_.has($scope.models[$scope.list.name].base, root)) { + if($scope.models[$scope.list.name].base[root].type && $scope.models[$scope.list.name].base[root].type === 'field') { encodeParams.relatedSearchTerm = true; } else { @@ -184,6 +175,10 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', ' } removed = qs.encodeParam(encodeParams); } + else if(_.contains($scope.models[$scope.list.name].related, root)) { + encodeParams.relatedSearchTerm = true; + removed = qs.encodeParam(encodeParams); + } else { removed = setDefaults(termParts[termParts.length-1]); } @@ -241,8 +236,8 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', ' } else { // Figure out if this is a search term let root = termParts[0].split(".")[0].replace(/^-/, ''); - if(_.has($scope.options.actions.GET, root)) { - if($scope.options.actions.GET[root].type && $scope.options.actions.GET[root].type === 'field') { + if(_.has($scope.models[$scope.list.name].base, root)) { + if($scope.models[$scope.list.name].base[root].type && $scope.models[$scope.list.name].base[root].type === 'field') { params = _.merge(params, qs.encodeParam({term: term, relatedSearchTerm: true}), combineSameSearches); } else { @@ -252,7 +247,7 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', ' // The related fields need to also be checked for related searches. // The related fields for the search are retrieved from the API // options endpoint, and are stored in the $scope.model. FYI, the - // Django search model is what sets the related fields on the model. + // Django search model is what sets the related fields on the model. else if(_.contains($scope.models[$scope.list.name].related, root)) { params = _.merge(params, qs.encodeParam({term: term, relatedSearchTerm: true}), combineSameSearches); } diff --git a/awx/ui/client/src/shared/smart-search/smart-search.partial.html b/awx/ui/client/src/shared/smart-search/smart-search.partial.html index b19b011698..13a5562aaa 100644 --- a/awx/ui/client/src/shared/smart-search/smart-search.partial.html +++ b/awx/ui/client/src/shared/smart-search/smart-search.partial.html @@ -47,7 +47,7 @@
FIELDS: {{ key }},
-
+
RELATED FIELDS: {{ relation }},