UI work to incorporate related_search_fields as valid fields when searching

This commit is contained in:
Michael Abashian 2017-02-13 14:55:34 -05:00
parent 8649ae8c4a
commit c459e326b2
4 changed files with 43 additions and 84 deletions

View File

@ -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;
}
}

View File

@ -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;
},

View File

@ -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);
}

View File

@ -47,7 +47,7 @@
<div class="SmartSearch-keyRow">
<b translate>FIELDS:</b> <span ng-repeat="(key,value) in model.base">{{ key }}<span ng-if="!$last">, </span></span>
</div>
<div class="SmartSearch-keyRow">
<div class="SmartSearch-keyRow" ng-show="model.related && model.related.length > 0">
<b translate>RELATED FIELDS:</b> <span ng-repeat="relation in model.related">{{ relation }}<span ng-if="!$last">, </span></span>
</div>
<div class="SmartSearch-keyRow">