Commit bf4a91ef authored by Samantha Ming's avatar Samantha Ming

Persist loading state while applying MR suggestion

Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/250859
parent 127db4b9
...@@ -435,6 +435,10 @@ export const saveNote = ({ commit, dispatch }, noteData) => { ...@@ -435,6 +435,10 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
}; };
const pollSuccessCallBack = (resp, commit, state, getters, dispatch) => { const pollSuccessCallBack = (resp, commit, state, getters, dispatch) => {
if (state.isResolvingDiscussion) {
return null;
}
if (resp.notes?.length) { if (resp.notes?.length) {
dispatch('updateOrCreateNotes', resp.notes); dispatch('updateOrCreateNotes', resp.notes);
dispatch('startTaskList'); dispatch('startTaskList');
...@@ -574,6 +578,9 @@ export const submitSuggestion = ( ...@@ -574,6 +578,9 @@ export const submitSuggestion = (
const dispatchResolveDiscussion = () => const dispatchResolveDiscussion = () =>
dispatch('resolveDiscussion', { discussionId }).catch(() => {}); dispatch('resolveDiscussion', { discussionId }).catch(() => {});
commit(types.SET_RESOLVING_DISCUSSION, true);
dispatch('stopPolling');
return Api.applySuggestion(suggestionId) return Api.applySuggestion(suggestionId)
.then(() => commit(types.APPLY_SUGGESTION, { discussionId, noteId, suggestionId })) .then(() => commit(types.APPLY_SUGGESTION, { discussionId, noteId, suggestionId }))
.then(dispatchResolveDiscussion) .then(dispatchResolveDiscussion)
...@@ -587,6 +594,10 @@ export const submitSuggestion = ( ...@@ -587,6 +594,10 @@ export const submitSuggestion = (
const flashMessage = errorMessage || defaultMessage; const flashMessage = errorMessage || defaultMessage;
Flash(__(flashMessage), 'alert', flashContainer); Flash(__(flashMessage), 'alert', flashContainer);
})
.finally(() => {
commit(types.SET_RESOLVING_DISCUSSION, false);
dispatch('restartPolling');
}); });
}; };
...@@ -605,6 +616,8 @@ export const submitSuggestionBatch = ({ commit, dispatch, state }, { flashContai ...@@ -605,6 +616,8 @@ export const submitSuggestionBatch = ({ commit, dispatch, state }, { flashContai
}); });
commit(types.SET_APPLYING_BATCH_STATE, true); commit(types.SET_APPLYING_BATCH_STATE, true);
commit(types.SET_RESOLVING_DISCUSSION, true);
dispatch('stopPolling');
return Api.applySuggestionBatch(suggestionIds) return Api.applySuggestionBatch(suggestionIds)
.then(() => Promise.all(applyAllSuggestions())) .then(() => Promise.all(applyAllSuggestions()))
...@@ -621,7 +634,11 @@ export const submitSuggestionBatch = ({ commit, dispatch, state }, { flashContai ...@@ -621,7 +634,11 @@ export const submitSuggestionBatch = ({ commit, dispatch, state }, { flashContai
Flash(__(flashMessage), 'alert', flashContainer); Flash(__(flashMessage), 'alert', flashContainer);
}) })
.finally(() => commit(types.SET_APPLYING_BATCH_STATE, false)); .finally(() => {
commit(types.SET_APPLYING_BATCH_STATE, false);
commit(types.SET_RESOLVING_DISCUSSION, false);
dispatch('restartPolling');
});
}; };
export const addSuggestionInfoToBatch = ({ commit }, { suggestionId, noteId, discussionId }) => export const addSuggestionInfoToBatch = ({ commit }, { suggestionId, noteId, discussionId }) =>
......
...@@ -42,6 +42,7 @@ export default () => ({ ...@@ -42,6 +42,7 @@ export default () => ({
current_user: {}, current_user: {},
preview_note_path: 'path/to/preview', preview_note_path: 'path/to/preview',
}, },
isResolvingDiscussion: false,
commentsDisabled: false, commentsDisabled: false,
resolvableDiscussionsCount: 0, resolvableDiscussionsCount: 0,
unresolvedDiscussionsCount: 0, unresolvedDiscussionsCount: 0,
......
...@@ -38,6 +38,7 @@ export const SET_TIMELINE_VIEW = 'SET_TIMELINE_VIEW'; ...@@ -38,6 +38,7 @@ export const SET_TIMELINE_VIEW = 'SET_TIMELINE_VIEW';
export const SET_SELECTED_COMMENT_POSITION = 'SET_SELECTED_COMMENT_POSITION'; export const SET_SELECTED_COMMENT_POSITION = 'SET_SELECTED_COMMENT_POSITION';
export const SET_SELECTED_COMMENT_POSITION_HOVER = 'SET_SELECTED_COMMENT_POSITION_HOVER'; export const SET_SELECTED_COMMENT_POSITION_HOVER = 'SET_SELECTED_COMMENT_POSITION_HOVER';
export const SET_FETCHING_DISCUSSIONS = 'SET_FETCHING_DISCUSSIONS'; export const SET_FETCHING_DISCUSSIONS = 'SET_FETCHING_DISCUSSIONS';
export const SET_RESOLVING_DISCUSSION = 'SET_RESOLVING_DISCUSSION';
// Issue // Issue
export const CLOSE_ISSUE = 'CLOSE_ISSUE'; export const CLOSE_ISSUE = 'CLOSE_ISSUE';
......
...@@ -213,6 +213,10 @@ export default { ...@@ -213,6 +213,10 @@ export default {
} }
}, },
[types.SET_RESOLVING_DISCUSSION](state, isResolving) {
state.isResolvingDiscussion = isResolving;
},
[types.UPDATE_NOTE](state, note) { [types.UPDATE_NOTE](state, note) {
const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id); const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id);
......
---
title: Retain spinner when applying MR suggestions
merge_request: 46203
author:
type: fixed
...@@ -944,10 +944,16 @@ describe('Actions Notes Store', () => { ...@@ -944,10 +944,16 @@ describe('Actions Notes Store', () => {
it('when service success, commits and resolves discussion', done => { it('when service success, commits and resolves discussion', done => {
testSubmitSuggestion(done, () => { testSubmitSuggestion(done, () => {
expect(commit.mock.calls).toEqual([ expect(commit.mock.calls).toEqual([
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
[mutationTypes.APPLY_SUGGESTION, { discussionId, noteId, suggestionId }], [mutationTypes.APPLY_SUGGESTION, { discussionId, noteId, suggestionId }],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
]); ]);
expect(dispatch.mock.calls).toEqual([['resolveDiscussion', { discussionId }]]); expect(dispatch.mock.calls).toEqual([
['stopPolling'],
['resolveDiscussion', { discussionId }],
['restartPolling'],
]);
expect(Flash).not.toHaveBeenCalled(); expect(Flash).not.toHaveBeenCalled();
}); });
}); });
...@@ -958,8 +964,11 @@ describe('Actions Notes Store', () => { ...@@ -958,8 +964,11 @@ describe('Actions Notes Store', () => {
Api.applySuggestion.mockReturnValue(Promise.reject(response)); Api.applySuggestion.mockReturnValue(Promise.reject(response));
testSubmitSuggestion(done, () => { testSubmitSuggestion(done, () => {
expect(commit).not.toHaveBeenCalled(); expect(commit.mock.calls).toEqual([
expect(dispatch).not.toHaveBeenCalled(); [mutationTypes.SET_RESOLVING_DISCUSSION, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
]);
expect(dispatch.mock.calls).toEqual([['stopPolling'], ['restartPolling']]);
expect(Flash).toHaveBeenCalledWith(TEST_ERROR_MESSAGE, 'alert', flashContainer); expect(Flash).toHaveBeenCalledWith(TEST_ERROR_MESSAGE, 'alert', flashContainer);
}); });
}); });
...@@ -970,8 +979,11 @@ describe('Actions Notes Store', () => { ...@@ -970,8 +979,11 @@ describe('Actions Notes Store', () => {
Api.applySuggestion.mockReturnValue(Promise.reject(response)); Api.applySuggestion.mockReturnValue(Promise.reject(response));
testSubmitSuggestion(done, () => { testSubmitSuggestion(done, () => {
expect(commit).not.toHaveBeenCalled(); expect(commit.mock.calls).toEqual([
expect(dispatch).not.toHaveBeenCalled(); [mutationTypes.SET_RESOLVING_DISCUSSION, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
]);
expect(dispatch.mock.calls).toEqual([['stopPolling'], ['restartPolling']]);
expect(Flash).toHaveBeenCalledWith( expect(Flash).toHaveBeenCalledWith(
'Something went wrong while applying the suggestion. Please try again.', 'Something went wrong while applying the suggestion. Please try again.',
'alert', 'alert',
...@@ -1015,15 +1027,19 @@ describe('Actions Notes Store', () => { ...@@ -1015,15 +1027,19 @@ describe('Actions Notes Store', () => {
testSubmitSuggestionBatch(done, () => { testSubmitSuggestionBatch(done, () => {
expect(commit.mock.calls).toEqual([ expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true], [mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
[mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[0]], [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[0]],
[mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[1]], [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[1]],
[mutationTypes.CLEAR_SUGGESTION_BATCH], [mutationTypes.CLEAR_SUGGESTION_BATCH],
[mutationTypes.SET_APPLYING_BATCH_STATE, false], [mutationTypes.SET_APPLYING_BATCH_STATE, false],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
]); ]);
expect(dispatch.mock.calls).toEqual([ expect(dispatch.mock.calls).toEqual([
['stopPolling'],
['resolveDiscussion', { discussionId: discussionIds[0] }], ['resolveDiscussion', { discussionId: discussionIds[0] }],
['resolveDiscussion', { discussionId: discussionIds[1] }], ['resolveDiscussion', { discussionId: discussionIds[1] }],
['restartPolling'],
]); ]);
expect(Flash).not.toHaveBeenCalled(); expect(Flash).not.toHaveBeenCalled();
...@@ -1038,10 +1054,12 @@ describe('Actions Notes Store', () => { ...@@ -1038,10 +1054,12 @@ describe('Actions Notes Store', () => {
testSubmitSuggestionBatch(done, () => { testSubmitSuggestionBatch(done, () => {
expect(commit.mock.calls).toEqual([ expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true], [mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
[mutationTypes.SET_APPLYING_BATCH_STATE, false], [mutationTypes.SET_APPLYING_BATCH_STATE, false],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
]); ]);
expect(dispatch).not.toHaveBeenCalled(); expect(dispatch.mock.calls).toEqual([['stopPolling'], ['restartPolling']]);
expect(Flash).toHaveBeenCalledWith(TEST_ERROR_MESSAGE, 'alert', flashContainer); expect(Flash).toHaveBeenCalledWith(TEST_ERROR_MESSAGE, 'alert', flashContainer);
}); });
}); });
...@@ -1054,10 +1072,12 @@ describe('Actions Notes Store', () => { ...@@ -1054,10 +1072,12 @@ describe('Actions Notes Store', () => {
testSubmitSuggestionBatch(done, () => { testSubmitSuggestionBatch(done, () => {
expect(commit.mock.calls).toEqual([ expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true], [mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
[mutationTypes.SET_APPLYING_BATCH_STATE, false], [mutationTypes.SET_APPLYING_BATCH_STATE, false],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
]); ]);
expect(dispatch).not.toHaveBeenCalled(); expect(dispatch.mock.calls).toEqual([['stopPolling'], ['restartPolling']]);
expect(Flash).toHaveBeenCalledWith( expect(Flash).toHaveBeenCalledWith(
'Something went wrong while applying the batch of suggestions. Please try again.', 'Something went wrong while applying the batch of suggestions. Please try again.',
'alert', 'alert',
...@@ -1072,10 +1092,12 @@ describe('Actions Notes Store', () => { ...@@ -1072,10 +1092,12 @@ describe('Actions Notes Store', () => {
testSubmitSuggestionBatch(done, () => { testSubmitSuggestionBatch(done, () => {
expect(commit.mock.calls).toEqual([ expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true], [mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
[mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[0]], [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[0]],
[mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[1]], [mutationTypes.APPLY_SUGGESTION, batchSuggestionsInfo[1]],
[mutationTypes.CLEAR_SUGGESTION_BATCH], [mutationTypes.CLEAR_SUGGESTION_BATCH],
[mutationTypes.SET_APPLYING_BATCH_STATE, false], [mutationTypes.SET_APPLYING_BATCH_STATE, false],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
]); ]);
expect(Flash).not.toHaveBeenCalled(); expect(Flash).not.toHaveBeenCalled();
......
...@@ -377,6 +377,16 @@ describe('Notes Store mutations', () => { ...@@ -377,6 +377,16 @@ describe('Notes Store mutations', () => {
}); });
}); });
describe('SET_RESOLVING_DISCUSSION', () => {
it('should set resolving discussion state', () => {
const state = {};
mutations.SET_RESOLVING_DISCUSSION(state, true);
expect(state.isResolvingDiscussion).toEqual(true);
});
});
describe('UPDATE_NOTE', () => { describe('UPDATE_NOTE', () => {
it('should update a note', () => { it('should update a note', () => {
const state = { const state = {
......
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