diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue index 88f053aed67de45a10107107f9e7afbd922117a9..102afaf308f197e920adca05bbc8d78ba411df46 100644 --- a/app/assets/javascripts/notes/components/discussion_filter.vue +++ b/app/assets/javascripts/notes/components/discussion_filter.vue @@ -39,7 +39,7 @@ export default { }; }, computed: { - ...mapGetters(['getNotesDataByProp', 'timelineEnabled']), + ...mapGetters(['getNotesDataByProp', 'timelineEnabled', 'isLoading']), currentFilter() { if (!this.currentValue) return this.filters[0]; return this.filters.find((filter) => filter.value === this.currentValue); @@ -119,6 +119,7 @@ export default { class="gl-mr-3 full-width-mobile discussion-filter-container js-discussion-filter-container" data-qa-selector="discussion_filter_dropdown" :text="currentFilter.title" + :disabled="isLoading" > <div v-for="filter in filters" :key="filter.value" class="dropdown-item-wrapper"> <gl-dropdown-item diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js index c862a29ad9c008566d908fea3b45a8678dd0c141..50b05ea9d69567802ef5a39d5039f6c021f8e32e 100644 --- a/app/assets/javascripts/notes/stores/actions.js +++ b/app/assets/javascripts/notes/stores/actions.js @@ -601,7 +601,8 @@ export const setLoadingState = ({ commit }, data) => { commit(types.SET_NOTES_LOADING_STATE, data); }; -export const filterDiscussion = ({ dispatch }, { path, filter, persistFilter }) => { +export const filterDiscussion = ({ commit, dispatch }, { path, filter, persistFilter }) => { + commit(types.CLEAR_DISCUSSIONS); dispatch('setLoadingState', true); dispatch('fetchDiscussions', { path, filter, persistFilter }) .then(() => { diff --git a/app/assets/javascripts/notes/stores/mutation_types.js b/app/assets/javascripts/notes/stores/mutation_types.js index fcd2846ff0d51ed449f038b35845b2f0ad81adf0..ebda08a3d621c95fa83a55de2fab030fa5c99d5c 100644 --- a/app/assets/javascripts/notes/stores/mutation_types.js +++ b/app/assets/javascripts/notes/stores/mutation_types.js @@ -1,6 +1,7 @@ export const ADD_NEW_NOTE = 'ADD_NEW_NOTE'; export const ADD_NEW_REPLY_TO_DISCUSSION = 'ADD_NEW_REPLY_TO_DISCUSSION'; export const ADD_OR_UPDATE_DISCUSSIONS = 'ADD_OR_UPDATE_DISCUSSIONS'; +export const CLEAR_DISCUSSIONS = 'CLEAR_DISCUSSIONS'; export const DELETE_NOTE = 'DELETE_NOTE'; export const REMOVE_PLACEHOLDER_NOTES = 'REMOVE_PLACEHOLDER_NOTES'; export const SET_NOTES_DATA = 'SET_NOTES_DATA'; diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js index 1a99750ddb3564afa0d17a76ef3485797a768faa..ba19ecd0c044911d824589467bbce41a2a54a05b 100644 --- a/app/assets/javascripts/notes/stores/mutations.js +++ b/app/assets/javascripts/notes/stores/mutations.js @@ -129,6 +129,10 @@ export default { Object.assign(state, { userData: data }); }, + [types.CLEAR_DISCUSSIONS](state) { + state.discussions = []; + }, + [types.ADD_OR_UPDATE_DISCUSSIONS](state, discussionsData) { discussionsData.forEach((d) => { const discussion = { ...d }; diff --git a/spec/frontend/notes/components/discussion_filter_spec.js b/spec/frontend/notes/components/discussion_filter_spec.js index 6f62b8ba5287700ad9f6d8cb8c2c2a47eabd4480..17998dfc9d56e77c07ddde03d11db8f47b44d343 100644 --- a/spec/frontend/notes/components/discussion_filter_spec.js +++ b/spec/frontend/notes/components/discussion_filter_spec.js @@ -1,3 +1,4 @@ +import { GlDropdown } from '@gitlab/ui'; import { createLocalVue, mount } from '@vue/test-utils'; import AxiosMockAdapter from 'axios-mock-adapter'; import Vuex from 'vuex'; @@ -88,6 +89,12 @@ describe('DiscussionFilter component', () => { ); }); + it('disables the dropdown when discussions are loading', () => { + store.state.isLoading = true; + + expect(wrapper.findComponent(GlDropdown).props('disabled')).toBe(true); + }); + it('updates to the selected item', () => { const filterItem = findFilter(DISCUSSION_FILTER_TYPES.ALL); diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js index bbe074f01058b4e9dd8f314daf711feba385e7fe..7424a87bc0fdbcef0b0c2505550845d6ea517056 100644 --- a/spec/frontend/notes/stores/actions_spec.js +++ b/spec/frontend/notes/stores/actions_spec.js @@ -1183,8 +1183,14 @@ describe('Actions Notes Store', () => { dispatch.mockReturnValue(new Promise(() => {})); }); + it('clears existing discussions', () => { + actions.filterDiscussion({ commit, dispatch }, { path, filter, persistFilter: false }); + + expect(commit.mock.calls).toEqual([[mutationTypes.CLEAR_DISCUSSIONS]]); + }); + it('fetches discussions with filter and persistFilter false', () => { - actions.filterDiscussion({ dispatch }, { path, filter, persistFilter: false }); + actions.filterDiscussion({ commit, dispatch }, { path, filter, persistFilter: false }); expect(dispatch.mock.calls).toEqual([ ['setLoadingState', true], @@ -1193,7 +1199,7 @@ describe('Actions Notes Store', () => { }); it('fetches discussions with filter and persistFilter true', () => { - actions.filterDiscussion({ dispatch }, { path, filter, persistFilter: true }); + actions.filterDiscussion({ commit, dispatch }, { path, filter, persistFilter: true }); expect(dispatch.mock.calls).toEqual([ ['setLoadingState', true], diff --git a/spec/frontend/notes/stores/mutation_spec.js b/spec/frontend/notes/stores/mutation_spec.js index c9e24039b64da8c5652ae3a93766f81531ae0b49..da1547ab6e7f6d5f63723ac1de41c3f74c5780e0 100644 --- a/spec/frontend/notes/stores/mutation_spec.js +++ b/spec/frontend/notes/stores/mutation_spec.js @@ -159,6 +159,18 @@ describe('Notes Store mutations', () => { }); }); + describe('CLEAR_DISCUSSIONS', () => { + it('should set discussions to an empty array', () => { + const state = { + discussions: [discussionMock], + }; + + mutations.CLEAR_DISCUSSIONS(state); + + expect(state.discussions).toEqual([]); + }); + }); + describe('ADD_OR_UPDATE_DISCUSSIONS', () => { it('should set the initial notes received', () => { const state = {