mirror of
https://github.com/ansible/awx.git
synced 2026-02-16 02:30:01 -03:30
331 lines
14 KiB
JavaScript
331 lines
14 KiB
JavaScript
export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', 'QuerySet', 'SmartSearchService', 'i18n',
|
|
function($stateParams, $scope, $state, QuerySet, GetBasePath, qs, SmartSearchService, i18n) {
|
|
|
|
let path, relations,
|
|
defaults,
|
|
queryset,
|
|
stateChangeSuccessListener;
|
|
|
|
if($scope.defaultParams) {
|
|
defaults = $scope.defaultParams;
|
|
}
|
|
else {
|
|
// steps through the current tree of $state configurations, grabs default search params
|
|
defaults = _.find($state.$current.path, (step) => {
|
|
return step.params.hasOwnProperty(`${$scope.iterator}_search`);
|
|
}).params[`${$scope.iterator}_search`].config.value;
|
|
}
|
|
|
|
if($scope.querySet) {
|
|
queryset = _.cloneDeep($scope.querySet);
|
|
}
|
|
else {
|
|
queryset = $stateParams[`${$scope.iterator}_search`];
|
|
}
|
|
|
|
// build $scope.tags from $stateParams.QuerySet, build fieldset key
|
|
init();
|
|
|
|
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) => {
|
|
$scope.models = data.models;
|
|
$scope.options = data.options.data;
|
|
$scope.$emit(`${$scope.list.iterator}_options`, data.options);
|
|
});
|
|
$scope.searchPlaceholder = $scope.disableSearch ? i18n._('Cannot search running job') : i18n._('Search');
|
|
|
|
function compareParams(a, b) {
|
|
for (let key in a) {
|
|
if (!(key in b) || a[key].toString() !== b[key].toString()) {
|
|
return false;
|
|
}
|
|
}
|
|
for (let key in b) {
|
|
if (!(key in a)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if(stateChangeSuccessListener) {
|
|
stateChangeSuccessListener();
|
|
}
|
|
|
|
stateChangeSuccessListener = $scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
|
|
// State has changed - check to see if this is a param change
|
|
if(fromState.name === toState.name) {
|
|
if(!compareParams(fromParams[`${$scope.iterator}_search`], toParams[`${$scope.iterator}_search`])) {
|
|
// Params are not the same - we need to update the search. This should only happen when the user
|
|
// hits the forward/back navigation buttons in their browser.
|
|
queryset = toParams[`${$scope.iterator}_search`];
|
|
qs.search(path, queryset).then((res) => {
|
|
$scope.dataset = res.data;
|
|
$scope.collection = res.data.results;
|
|
});
|
|
|
|
$scope.searchTerm = null;
|
|
$scope.searchTags = stripDefaultParams(queryset);
|
|
}
|
|
}
|
|
});
|
|
|
|
$scope.$on('$destroy', stateChangeSuccessListener);
|
|
|
|
$scope.$watch('disableSearch', function(disableSearch){
|
|
if(disableSearch) {
|
|
$scope.searchPlaceholder = i18n._('Cannot search running job');
|
|
}
|
|
else {
|
|
$scope.searchPlaceholder = i18n._('Search');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Removes state definition defaults and pagination terms
|
|
function stripDefaultParams(params) {
|
|
let stripped =_.pick(params, (value, key) => {
|
|
// setting the default value of a term to null in a state definition is a very explicit way to ensure it will NEVER generate a search tag, even with a non-default value
|
|
return defaults[key] !== value && key !== 'order_by' && key !== 'page' && key !== 'page_size' && defaults[key] !== null;
|
|
});
|
|
let strippedCopy = _.cloneDeep(stripped);
|
|
if(_.keys(_.pick(defaults, _.keys(strippedCopy))).length > 0){
|
|
for (var key in strippedCopy) {
|
|
if (strippedCopy.hasOwnProperty(key)) {
|
|
let value = strippedCopy[key];
|
|
if(_.isArray(value)){
|
|
let index = _.indexOf(value, defaults[key]);
|
|
value = value.splice(index, 1)[0];
|
|
}
|
|
}
|
|
}
|
|
stripped = strippedCopy;
|
|
}
|
|
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);
|
|
} else {
|
|
return {
|
|
search: encodeURIComponent(term)
|
|
};
|
|
}
|
|
}
|
|
|
|
$scope.toggleKeyPane = function() {
|
|
$scope.showKeyPane = !$scope.showKeyPane;
|
|
};
|
|
|
|
$scope.clearAll = function(){
|
|
let cleared = _.cloneDeep(defaults);
|
|
delete cleared.page;
|
|
queryset = cleared;
|
|
if(!$scope.querySet) {
|
|
$state.go('.', {[$scope.iterator + '_search']: queryset}, {notify: false});
|
|
}
|
|
qs.search(path, queryset).then((res) => {
|
|
if($scope.querySet) {
|
|
$scope.querySet = queryset;
|
|
}
|
|
$scope.dataset = res.data;
|
|
$scope.collection = res.data.results;
|
|
});
|
|
$scope.searchTags = stripDefaultParams(queryset);
|
|
};
|
|
|
|
// remove tag, merge new queryset, $state.go
|
|
$scope.remove = function(index) {
|
|
let tagToRemove = $scope.searchTags.splice(index, 1)[0],
|
|
termParts = SmartSearchService.splitTermIntoParts(tagToRemove),
|
|
removed;
|
|
|
|
let removeFromQuerySet = function(set) {
|
|
_.each(removed, (value, key) => {
|
|
if (Array.isArray(set[key])){
|
|
_.remove(set[key], (item) => item === value);
|
|
// If the array is now empty, remove that key
|
|
if(set[key].length === 0) {
|
|
delete set[key];
|
|
}
|
|
}
|
|
else {
|
|
delete set[key];
|
|
}
|
|
});
|
|
};
|
|
|
|
if (termParts.length === 1) {
|
|
removed = setDefaults(tagToRemove);
|
|
}
|
|
else {
|
|
let root = termParts[0].split(".")[0].replace(/^-/, '');
|
|
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') {
|
|
encodeParams.relatedSearchTerm = true;
|
|
}
|
|
else {
|
|
encodeParams.searchTerm = true;
|
|
}
|
|
removed = qs.encodeParam(encodeParams);
|
|
}
|
|
else {
|
|
removed = setDefaults(termParts[termParts.length-1]);
|
|
}
|
|
}
|
|
removeFromQuerySet(queryset);
|
|
if(!$scope.querySet) {
|
|
$state.go('.', {
|
|
[$scope.iterator + '_search']: queryset }, {notify: false}).then(function(){
|
|
// ISSUE: for some reason deleting a tag from a list in a modal does not
|
|
// remove the param from $stateParams. Here we'll manually check to make sure
|
|
// that that happened and remove it if it didn't.
|
|
|
|
removeFromQuerySet($stateParams[`${$scope.iterator}_search`]);
|
|
});
|
|
}
|
|
qs.search(path, queryset).then((res) => {
|
|
if($scope.querySet) {
|
|
$scope.querySet = queryset;
|
|
}
|
|
$scope.dataset = res.data;
|
|
$scope.collection = res.data.results;
|
|
});
|
|
$scope.searchTags = stripDefaultParams(queryset);
|
|
};
|
|
|
|
// add a search tag, merge new queryset, $state.go()
|
|
$scope.add = function(terms) {
|
|
let params = {},
|
|
origQueryset = _.clone(queryset);
|
|
|
|
// Remove leading/trailing whitespace if there is any
|
|
terms = (terms) ? terms.trim() : "";
|
|
|
|
if(terms && terms !== '') {
|
|
// Split the terms up
|
|
let splitTerms = SmartSearchService.splitSearchIntoTerms(terms);
|
|
_.forEach(splitTerms, (term) => {
|
|
|
|
let termParts = SmartSearchService.splitTermIntoParts(term);
|
|
|
|
function combineSameSearches(a,b){
|
|
if (_.isArray(a)) {
|
|
return a.concat(b);
|
|
}
|
|
else {
|
|
if(a) {
|
|
return [a,b];
|
|
}
|
|
}
|
|
}
|
|
|
|
// if only a value is provided, search using default keys
|
|
if (termParts.length === 1) {
|
|
params = _.merge(params, setDefaults(term), combineSameSearches);
|
|
} 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') {
|
|
params = _.merge(params, qs.encodeParam({term: term, relatedSearchTerm: true}), combineSameSearches);
|
|
}
|
|
else {
|
|
params = _.merge(params, qs.encodeParam({term: term, searchTerm: true}), combineSameSearches);
|
|
}
|
|
}
|
|
// Its not a search term or a related search term - treat it as a string
|
|
else {
|
|
params = _.merge(params, setDefaults(term), combineSameSearches);
|
|
}
|
|
|
|
}
|
|
});
|
|
|
|
queryset = _.merge(queryset, params, (objectValue, sourceValue, key, object) => {
|
|
if (object[key] && object[key] !== sourceValue){
|
|
if(_.isArray(object[key])) {
|
|
// Add the new value to the array and return
|
|
object[key].push(sourceValue);
|
|
return object[key];
|
|
}
|
|
else {
|
|
// Start the array of keys
|
|
return [object[key], sourceValue];
|
|
}
|
|
}
|
|
else {
|
|
// // https://lodash.com/docs/3.10.1#merge
|
|
// If customizer fn returns undefined merging is handled by default _.merge algorithm
|
|
return undefined;
|
|
}
|
|
});
|
|
|
|
// Go back to the first page after a new search
|
|
delete queryset.page;
|
|
|
|
// https://ui-router.github.io/docs/latest/interfaces/params.paramdeclaration.html#dynamic
|
|
// This transition will not reload controllers/resolves/views
|
|
// but will register new $stateParams[$scope.iterator + '_search'] terms
|
|
if(!$scope.querySet) {
|
|
$state.go('.', {
|
|
[$scope.iterator + '_search']: queryset }, {notify: false}).then(function(){
|
|
// ISSUE: same as above in $scope.remove. For some reason deleting the page
|
|
// from the queryset works for all lists except lists in modals.
|
|
delete $stateParams[$scope.iterator + '_search'].page;
|
|
});
|
|
}
|
|
qs.search(path, queryset).then((res) => {
|
|
if($scope.querySet) {
|
|
$scope.querySet = queryset;
|
|
}
|
|
$scope.dataset = res.data;
|
|
$scope.collection = res.data.results;
|
|
})
|
|
.catch(function() {
|
|
$scope.revertSearch(origQueryset);
|
|
});
|
|
|
|
$scope.searchTerm = null;
|
|
$scope.searchTags = stripDefaultParams(queryset);
|
|
}
|
|
};
|
|
|
|
$scope.revertSearch = function(queryToBeRestored) {
|
|
queryset = queryToBeRestored;
|
|
// https://ui-router.github.io/docs/latest/interfaces/params.paramdeclaration.html#dynamic
|
|
// This transition will not reload controllers/resolves/views
|
|
// but will register new $stateParams[$scope.iterator + '_search'] terms
|
|
if(!$scope.querySet) {
|
|
$state.go('.', {
|
|
[$scope.iterator + '_search']: queryset }, {notify: false});
|
|
}
|
|
qs.search(path, queryset).then((res) => {
|
|
if($scope.querySet) {
|
|
$scope.querySet = queryset;
|
|
}
|
|
$scope.dataset = res.data;
|
|
$scope.collection = res.data.results;
|
|
});
|
|
|
|
$scope.searchTerm = null;
|
|
$scope.searchTags = stripDefaultParams(queryset);
|
|
};
|
|
}
|
|
];
|