Commit 5cf6c84a authored by Michael Lunøe's avatar Michael Lunøe Committed by Jose Ivan Vargas

Fix(filtered search manager): add state option

Add option parameter to use default state, so
usages of the filtered_search_manager can specify
whether to use the default state, or not.

This created issues around the application where
state='opened' had an unintentional effect and
would cause inconsistencies between what was being
displayed when. See ticket for more information:
https://gitlab.com/gitlab-org/gitlab/-/issues/232734
parent 025aeb49
......@@ -10,6 +10,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
isGroupDecendent: true,
stateFiltersSelector: '.issues-state-filters',
isGroup: IS_EE,
useDefaultState: false,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
});
......
......@@ -29,6 +29,7 @@ export default class FilteredSearchManager {
isGroup = false,
isGroupAncestor = true,
isGroupDecendent = false,
useDefaultState = false,
filteredSearchTokenKeys = IssuableFilteredSearchTokenKeys,
stateFiltersSelector = '.issues-state-filters',
placeholder = __('Search or filter results...'),
......@@ -37,6 +38,7 @@ export default class FilteredSearchManager {
this.isGroup = isGroup;
this.isGroupAncestor = isGroupAncestor;
this.isGroupDecendent = isGroupDecendent;
this.useDefaultState = useDefaultState;
this.states = ['opened', 'closed', 'merged', 'all'];
this.page = page;
......@@ -724,8 +726,13 @@ export default class FilteredSearchManager {
search(state = null) {
const paths = [];
const { tokens, searchToken } = this.getSearchTokens();
const currentState = state || getParameterByName('state') || 'opened';
let currentState = state || getParameterByName('state');
if (!currentState && this.useDefaultState) {
currentState = 'opened';
}
if (this.states.includes(currentState)) {
paths.push(`state=${currentState}`);
}
tokens.forEach(token => {
const condition = this.filteredSearchTokenKeys.searchByConditionKeyValue(
......
......@@ -6,5 +6,6 @@ document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.ADMIN_RUNNERS,
filteredSearchTokenKeys: AdminRunnersFilteredSearchTokenKeys,
useDefaultState: true,
});
});
......@@ -8,6 +8,7 @@ document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.ISSUES,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
useDefaultState: true,
});
projectSelect();
......
......@@ -10,6 +10,7 @@ document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
useDefaultState: true,
});
projectSelect();
......
......@@ -17,6 +17,7 @@ document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.ISSUES,
isGroupDecendent: true,
useDefaultState: true,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
});
projectSelect();
......
......@@ -14,6 +14,7 @@ document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
isGroupDecendent: true,
useDefaultState: true,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
});
projectSelect();
......
......@@ -13,6 +13,7 @@ document.addEventListener('DOMContentLoaded', () => {
page: FILTERED_SEARCH.ADMIN_RUNNERS,
filteredSearchTokenKeys: GroupRunnersFilteredSearchTokenKeys,
anchor: FILTERED_SEARCH.GROUP_RUNNERS_ANCHOR,
useDefaultState: false,
});
if (gon.features.newVariablesUi) {
......
......@@ -17,6 +17,7 @@ document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.ISSUES,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
useDefaultState: true,
});
new IssuableIndex(ISSUABLE_INDEX.ISSUE);
......
......@@ -9,6 +9,7 @@ export default class FilteredSearchServiceDesk extends FilteredSearchManager {
super({
page: 'service_desk',
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
useDefaultState: true,
});
this.supportBotData = supportBotData;
......
......@@ -13,6 +13,7 @@ document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
useDefaultState: true,
});
new IssuableIndex(ISSUABLE_INDEX.MERGE_REQUEST); // eslint-disable-line no-new
......
......@@ -6,6 +6,7 @@ export default ({
isGroup,
isGroupAncestor,
isGroupDecendent,
useDefaultState,
stateFiltersSelector,
anchor,
}) => {
......@@ -16,6 +17,7 @@ export default ({
isGroup,
isGroupAncestor,
isGroupDecendent,
useDefaultState,
filteredSearchTokenKeys,
stateFiltersSelector,
anchor,
......
---
title: Fix bug where filtering would sometimes display only open issues on different pages listing issues
merge_request: 38906
author:
type: fixed
......@@ -12,6 +12,7 @@ export default class FilteredSearchCodeReviewAnalytics extends FilteredSearchMan
isGroupDecendent: true,
stateFiltersSelector: '.issues-state-filters',
isGroup: true,
useDefaultState: false,
filteredSearchTokenKeys: CodeReviewAnalyticsFilteredSearchTokenKeys,
placeholder: __('Filter results...'),
});
......
......@@ -11,6 +11,7 @@ export default class FilteredSearchProductivityAnalytics extends FilteredSearchM
isGroupDecendent: true,
stateFiltersSelector: '.issues-state-filters',
isGroup,
useDefaultState: false,
filteredSearchTokenKeys: ProductivityAnalyticsFilteredSearchTokenKeys,
placeholder: __('Filter results...'),
});
......
......@@ -20,6 +20,7 @@ export default class FilteredSearchIssueAnalytics extends FilteredSearchManager
isGroupDecendent: true,
stateFiltersSelector: '.issues-state-filters',
isGroup: true,
useDefaultState: false,
filteredSearchTokenKeys: issuesAnalyticsTokenKeys,
placeholder: __('Filter results...'),
});
......
......@@ -10,6 +10,7 @@ document.addEventListener('DOMContentLoaded', () => {
page: 'epics',
isGroup: true,
isGroupDecendent: true,
useDefaultState: true,
filteredSearchTokenKeys: FilteredSearchTokenKeysEpics,
stateFiltersSelector: '.epics-state-filters',
});
......
......@@ -9,6 +9,7 @@ document.addEventListener('DOMContentLoaded', () => {
page: 'epics',
isGroup: true,
isGroupDecendent: true,
useDefaultState: false,
filteredSearchTokenKeys: FilteredSearchTokenKeysEpics,
stateFiltersSelector: '.epics-state-filters',
});
......
......@@ -77,7 +77,7 @@ describe('Filtered Search Manager', () => {
jest.spyOn(FilteredSearchDropdownManager.prototype, 'setDropdown').mockImplementation();
});
const initializeManager = () => {
const initializeManager = ({ useDefaultState } = {}) => {
jest.spyOn(FilteredSearchManager.prototype, 'loadSearchParamsFromURL').mockImplementation();
jest.spyOn(FilteredSearchManager.prototype, 'tokenChange').mockImplementation();
jest
......@@ -88,7 +88,7 @@ describe('Filtered Search Manager', () => {
input = document.querySelector('.filtered-search');
tokensContainer = document.querySelector('.tokens-container');
manager = new FilteredSearchManager({ page });
manager = new FilteredSearchManager({ page, useDefaultState });
manager.setup();
};
......@@ -184,17 +184,27 @@ describe('Filtered Search Manager', () => {
});
describe('search', () => {
const defaultParams = '?scope=all&utf8=%E2%9C%93&state=opened';
const defaultParams = '?scope=all&utf8=%E2%9C%93';
const defaultState = '&state=opened';
beforeEach(() => {
it('should search with a single word', done => {
initializeManager();
input.value = 'searchTerm';
visitUrl.mockImplementation(url => {
expect(url).toEqual(`${defaultParams}&search=searchTerm`);
done();
});
it('should search with a single word', done => {
manager.search();
});
it('sets default state', done => {
initializeManager({ useDefaultState: true });
input.value = 'searchTerm';
visitUrl.mockImplementation(url => {
expect(url).toEqual(`${defaultParams}&search=searchTerm`);
expect(url).toEqual(`${defaultParams}${defaultState}&search=searchTerm`);
done();
});
......@@ -202,6 +212,7 @@ describe('Filtered Search Manager', () => {
});
it('should search with multiple words', done => {
initializeManager();
input.value = 'awesome search terms';
visitUrl.mockImplementation(url => {
......@@ -213,6 +224,7 @@ describe('Filtered Search Manager', () => {
});
it('should search with special characters', done => {
initializeManager();
input.value = '~!@#$%^&*()_+{}:<>,.?/';
visitUrl.mockImplementation(url => {
......@@ -226,6 +238,7 @@ describe('Filtered Search Manager', () => {
});
it('should use replacement URL for condition', done => {
initializeManager();
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', '13', true),
);
......@@ -246,6 +259,7 @@ describe('Filtered Search Manager', () => {
});
it('removes duplicated tokens', done => {
initializeManager();
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug')}
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug')}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment