diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 17:34:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 17:34:42 +0300 |
commit | 9f46488805e86b1bc341ea1620b866016c2ce5ed (patch) | |
tree | f9748c7e287041e37d6da49e0a29c9511dc34768 /app/assets/javascripts/filtered_search | |
parent | dfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff) |
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'app/assets/javascripts/filtered_search')
8 files changed, 75 insertions, 22 deletions
diff --git a/app/assets/javascripts/filtered_search/constants.js b/app/assets/javascripts/filtered_search/constants.js index d7264e96b13..7e7a2588951 100644 --- a/app/assets/javascripts/filtered_search/constants.js +++ b/app/assets/javascripts/filtered_search/constants.js @@ -4,3 +4,8 @@ export const DROPDOWN_TYPE = { hint: 'hint', operator: 'operator', }; + +export const FILTER_TYPE = { + none: 'none', + any: 'any', +}; diff --git a/app/assets/javascripts/filtered_search/dropdown_operator.js b/app/assets/javascripts/filtered_search/dropdown_operator.js index 0c8c8140ee9..1bbd33b6258 100644 --- a/app/assets/javascripts/filtered_search/dropdown_operator.js +++ b/app/assets/javascripts/filtered_search/dropdown_operator.js @@ -47,13 +47,17 @@ export default class DropdownOperator extends FilteredSearchDropdown { title: '=', help: __('is'), }, - { + ]; + + if (gon.features?.notIssuableQueries) { + dropdownData.push({ tag: 'not-equal', type: 'string', title: '!=', help: __('is not'), - }, - ]; + }); + } + this.droplab.changeHookList(this.hookId, this.dropdown, [Filter], this.config); this.droplab.setData(this.hookId, dropdownData); super.renderContent(forceShowList); diff --git a/app/assets/javascripts/filtered_search/event_hub.js b/app/assets/javascripts/filtered_search/event_hub.js index 0948c2e5352..e31806ad199 100644 --- a/app/assets/javascripts/filtered_search/event_hub.js +++ b/app/assets/javascripts/filtered_search/event_hub.js @@ -1,3 +1,3 @@ -import Vue from 'vue'; +import createEventHub from '~/helpers/event_hub_factory'; -export default new Vue(); +export default createEventHub(); diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js index 2b6e1f25dc6..f7ce2ea01e0 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js +++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js @@ -1,6 +1,7 @@ import DropdownUtils from './dropdown_utils'; import FilteredSearchDropdownManager from './filtered_search_dropdown_manager'; import FilteredSearchVisualTokens from './filtered_search_visual_tokens'; +import { FILTER_TYPE } from './constants'; const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger'; @@ -74,6 +75,9 @@ export default class FilteredSearchDropdown { renderContent(forceShowList = false) { const currentHook = this.getCurrentHook(); + + FilteredSearchDropdown.hideDropdownItemsforNotOperator(currentHook); + if (forceShowList && currentHook && currentHook.list.hidden) { currentHook.list.show(); } @@ -138,4 +142,41 @@ export default class FilteredSearchDropdown { hook.list.render(results); } } + + /** + * Hide None & Any options from the current dropdown. + * Hiding happens only for NOT operator. + */ + static hideDropdownItemsforNotOperator(currentHook) { + const lastOperator = FilteredSearchVisualTokens.getLastTokenOperator(); + + if (lastOperator === '!=') { + const { list: dropdownEl } = currentHook.list; + + let shouldHideDivider = true; + + // Iterate over all the static dropdown values, + // then hide `None` and `Any` items. + Array.from(dropdownEl.querySelectorAll('li[data-value]')).forEach(itemEl => { + const { + dataset: { value }, + } = itemEl; + + if (value.toLowerCase() === FILTER_TYPE.none || value.toLowerCase() === FILTER_TYPE.any) { + itemEl.classList.add('hidden'); + } else { + // If we encountered any element other than None/Any, then + // we shouldn't hide the divider + shouldHideDivider = false; + } + }); + + if (shouldHideDivider) { + const divider = dropdownEl.querySelector('li.divider'); + if (divider) { + divider.classList.add('hidden'); + } + } + } + } } diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js index d051b60814e..161a65c511d 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js @@ -120,7 +120,7 @@ export default class FilteredSearchDropdownManager { filter: key, }; const extraArguments = mappingKey.extraArguments || {}; - const glArguments = Object.assign({}, defaultArguments, extraArguments); + const glArguments = { ...defaultArguments, ...extraArguments }; // Passing glArguments to `new glClass(<arguments>)` mappingKey.reference = new (Function.prototype.bind.apply(glClass, [null, glArguments]))(); diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js index 724f80f8866..55a0e91b0f3 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js @@ -31,6 +31,7 @@ export default class FilteredSearchManager { isGroupDecendent = false, filteredSearchTokenKeys = IssuableFilteredSearchTokenKeys, stateFiltersSelector = '.issues-state-filters', + placeholder = __('Search or filter results...'), }) { this.isGroup = isGroup; this.isGroupAncestor = isGroupAncestor; @@ -45,6 +46,7 @@ export default class FilteredSearchManager { this.tokensContainer = this.container.querySelector('.tokens-container'); this.filteredSearchTokenKeys = filteredSearchTokenKeys; this.stateFiltersSelector = stateFiltersSelector; + this.placeholder = placeholder; const { multipleAssignees } = this.filteredSearchInput.dataset; if (multipleAssignees && this.filteredSearchTokenKeys.enableMultipleAssignees) { @@ -395,11 +397,10 @@ export default class FilteredSearchManager { handleInputPlaceholder() { const query = DropdownUtils.getSearchQuery(); - const placeholder = __('Search or filter results...'); const currentPlaceholder = this.filteredSearchInput.placeholder; - if (query.length === 0 && currentPlaceholder !== placeholder) { - this.filteredSearchInput.placeholder = placeholder; + if (query.length === 0 && currentPlaceholder !== this.placeholder) { + this.filteredSearchInput.placeholder = this.placeholder; } else if (query.length > 0 && currentPlaceholder !== '') { this.filteredSearchInput.placeholder = ''; } @@ -710,13 +711,17 @@ export default class FilteredSearchManager { } } - search(state = null) { - const paths = []; + getSearchTokens() { const searchQuery = DropdownUtils.getSearchQuery(); this.saveCurrentSearchQuery(); const tokenKeys = this.filteredSearchTokenKeys.getKeys(); - const { tokens, searchToken } = this.tokenizer.processTokens(searchQuery, tokenKeys); + return this.tokenizer.processTokens(searchQuery, tokenKeys); + } + + search(state = null) { + const paths = []; + const { tokens, searchToken } = this.getSearchTokens(); const currentState = state || getParameterByName('state') || 'opened'; paths.push(`state=${currentState}`); diff --git a/app/assets/javascripts/filtered_search/stores/recent_searches_store.js b/app/assets/javascripts/filtered_search/stores/recent_searches_store.js index b3eb0475d6f..cdbc9ec84bd 100644 --- a/app/assets/javascripts/filtered_search/stores/recent_searches_store.js +++ b/app/assets/javascripts/filtered_search/stores/recent_searches_store.js @@ -2,14 +2,12 @@ import { uniq } from 'lodash'; class RecentSearchesStore { constructor(initialState = {}, allowedKeys) { - this.state = Object.assign( - { - isLocalStorageAvailable: true, - recentSearches: [], - allowedKeys, - }, - initialState, - ); + this.state = { + isLocalStorageAvailable: true, + recentSearches: [], + allowedKeys, + ...initialState, + }; } addRecentSearch(newSearch) { diff --git a/app/assets/javascripts/filtered_search/visual_token_value.js b/app/assets/javascripts/filtered_search/visual_token_value.js index b8f4cd8a1e1..02caf0851af 100644 --- a/app/assets/javascripts/filtered_search/visual_token_value.js +++ b/app/assets/javascripts/filtered_search/visual_token_value.js @@ -1,4 +1,4 @@ -import { escape as esc } from 'lodash'; +import { escape } from 'lodash'; import { USER_TOKEN_TYPES } from 'ee_else_ce/filtered_search/constants'; import FilteredSearchContainer from '~/filtered_search/container'; import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens'; @@ -48,7 +48,7 @@ export default class VisualTokenValue { tokenValueContainer.dataset.originalValue = tokenValue; tokenValueElement.innerHTML = ` <img class="avatar s20" src="${user.avatar_url}" alt=""> - ${esc(user.name)} + ${escape(user.name)} `; /* eslint-enable no-param-reassign */ }) |