Commit 4f713dc0 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'cngo-fix-filtered-search-suggestions-not-showing' into 'master'

Fix Epic and Label != filtered search suggestions not showing

See merge request gitlab-org/gitlab!82814
parents afd8cf21 c9b18202
...@@ -76,6 +76,7 @@ export default { ...@@ -76,6 +76,7 @@ export default {
}, },
data() { data() {
return { return {
hasFetched: false, // use this to avoid flash of `No suggestions found` before fetching
searchKey: '', searchKey: '',
recentSuggestions: this.config.recentSuggestionsStorageKey recentSuggestions: this.config.recentSuggestionsStorageKey
? getRecentlyUsedSuggestions(this.config.recentSuggestionsStorageKey) ?? [] ? getRecentlyUsedSuggestions(this.config.recentSuggestionsStorageKey) ?? []
...@@ -86,6 +87,9 @@ export default { ...@@ -86,6 +87,9 @@ export default {
isRecentSuggestionsEnabled() { isRecentSuggestionsEnabled() {
return Boolean(this.config.recentSuggestionsStorageKey); return Boolean(this.config.recentSuggestionsStorageKey);
}, },
suggestionsEnabled() {
return !this.config.suggestionsDisabled;
},
recentTokenIds() { recentTokenIds() {
return this.recentSuggestions.map((tokenValue) => tokenValue[this.valueIdentifier]); return this.recentSuggestions.map((tokenValue) => tokenValue[this.valueIdentifier]);
}, },
...@@ -134,17 +138,6 @@ export default { ...@@ -134,17 +138,6 @@ export default {
showAvailableSuggestions() { showAvailableSuggestions() {
return this.availableSuggestions.length > 0; return this.availableSuggestions.length > 0;
}, },
showSuggestions() {
// These conditions must match the template under `#suggestions` slot
// See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65817#note_632619411
return (
this.showDefaultSuggestions ||
this.showRecentSuggestions ||
this.showPreloadedSuggestions ||
this.suggestionsLoading ||
this.showAvailableSuggestions
);
},
searchTerm() { searchTerm() {
return this.searchBy && this.activeTokenValue return this.searchBy && this.activeTokenValue
? this.activeTokenValue[this.searchBy] ? this.activeTokenValue[this.searchBy]
...@@ -161,6 +154,13 @@ export default { ...@@ -161,6 +154,13 @@ export default {
} }
}, },
}, },
suggestionsLoading: {
handler(loading) {
if (loading) {
this.hasFetched = true;
}
},
},
}, },
methods: { methods: {
handleInput: debounce(function debouncedSearch({ data, operator }) { handleInput: debounce(function debouncedSearch({ data, operator }) {
...@@ -216,7 +216,7 @@ export default { ...@@ -216,7 +216,7 @@ export default {
<template #view="viewTokenProps"> <template #view="viewTokenProps">
<slot name="view" :view-token-props="{ ...viewTokenProps, activeTokenValue }"></slot> <slot name="view" :view-token-props="{ ...viewTokenProps, activeTokenValue }"></slot>
</template> </template>
<template v-if="showSuggestions" #suggestions> <template v-if="suggestionsEnabled" #suggestions>
<template v-if="showDefaultSuggestions"> <template v-if="showDefaultSuggestions">
<gl-filtered-search-suggestion <gl-filtered-search-suggestion
v-for="token in availableDefaultSuggestions" v-for="token in availableDefaultSuggestions"
...@@ -238,12 +238,13 @@ export default { ...@@ -238,12 +238,13 @@ export default {
:suggestions="preloadedSuggestions" :suggestions="preloadedSuggestions"
></slot> ></slot>
<gl-loading-icon v-if="suggestionsLoading" size="sm" /> <gl-loading-icon v-if="suggestionsLoading" size="sm" />
<template v-else-if="showAvailableSuggestions">
<slot name="suggestions-list" :suggestions="availableSuggestions"></slot>
</template>
<gl-dropdown-text v-else-if="showNoMatchesText"> <gl-dropdown-text v-else-if="showNoMatchesText">
{{ __('No matches found') }} {{ __('No matches found') }}
</gl-dropdown-text> </gl-dropdown-text>
<template v-else> <gl-dropdown-text v-else-if="hasFetched">{{ __('No suggestions found') }}</gl-dropdown-text>
<slot name="suggestions-list" :suggestions="availableSuggestions"></slot>
</template>
</template> </template>
</gl-filtered-search-token> </gl-filtered-search-token>
</template> </template>
...@@ -150,6 +150,7 @@ export default { ...@@ -150,6 +150,7 @@ export default {
token: LabelToken, token: LabelToken,
operators: OPERATOR_IS_ONLY, operators: OPERATOR_IS_ONLY,
defaultLabels: [], defaultLabels: [],
suggestionsDisabled: true,
fetchLabels: () => { fetchLabels: () => {
return Promise.resolve([]); return Promise.resolve([]);
}, },
......
...@@ -124,6 +124,7 @@ Object { ...@@ -124,6 +124,7 @@ Object {
"value": "=", "value": "=",
}, },
], ],
"suggestionsDisabled": true,
"symbol": "~", "symbol": "~",
"title": "Label", "title": "Label",
"token": "LabelTokenMock", "token": "LabelTokenMock",
......
...@@ -25036,6 +25036,9 @@ msgstr "" ...@@ -25036,6 +25036,9 @@ msgstr ""
msgid "No start date" msgid "No start date"
msgstr "" msgstr ""
msgid "No suggestions found"
msgstr ""
msgid "No tag selected" msgid "No tag selected"
msgstr "" msgstr ""
......
...@@ -4,6 +4,7 @@ import { ...@@ -4,6 +4,7 @@ import {
GlFilteredSearchSuggestion, GlFilteredSearchSuggestion,
GlDropdownSectionHeader, GlDropdownSectionHeader,
GlDropdownDivider, GlDropdownDivider,
GlDropdownText,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
...@@ -81,6 +82,7 @@ const mockProps = { ...@@ -81,6 +82,7 @@ const mockProps = {
function createComponent({ function createComponent({
props = {}, props = {},
data = {},
stubs = defaultStubs, stubs = defaultStubs,
slots = defaultSlots, slots = defaultSlots,
scopedSlots = defaultScopedSlots, scopedSlots = defaultScopedSlots,
...@@ -100,6 +102,9 @@ function createComponent({ ...@@ -100,6 +102,9 @@ function createComponent({
unregister: jest.fn(), unregister: jest.fn(),
}, },
}, },
data() {
return data;
},
stubs, stubs,
slots, slots,
scopedSlots, scopedSlots,
...@@ -168,6 +173,24 @@ describe('BaseToken', () => { ...@@ -168,6 +173,24 @@ describe('BaseToken', () => {
}); });
describe('suggestions', () => { describe('suggestions', () => {
describe('with suggestions disabled', () => {
beforeEach(() => {
wrapper = createComponent({
props: {
config: {
suggestionsDisabled: true,
},
suggestions: [{ id: 'Foo' }],
},
mountFn: shallowMountExtended,
});
});
it('does not render suggestions', () => {
expect(findMockSuggestionList().exists()).toBe(false);
});
});
describe('with available suggestions', () => { describe('with available suggestions', () => {
let mockSuggestions; let mockSuggestions;
...@@ -306,6 +329,28 @@ describe('BaseToken', () => { ...@@ -306,6 +329,28 @@ describe('BaseToken', () => {
}); });
}); });
}); });
describe('with no suggestions', () => {
it.each`
data | expected
${{ searchKey: 'search' }} | ${'No matches found'}
${{ hasFetched: true }} | ${'No suggestions found'}
`('shows $expected text', ({ data, expected }) => {
wrapper = createComponent({
props: {
config: { recentSuggestionsStorageKey: null },
defaultSuggestions: [],
preloadedSuggestions: [],
suggestions: [],
suggestionsLoading: false,
},
data,
mountFn: shallowMountExtended,
});
expect(wrapper.findComponent(GlDropdownText).text()).toBe(expected);
});
});
}); });
describe('methods', () => { describe('methods', () => {
......
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