Commit 6ea76f20 authored by Phil Hughes's avatar Phil Hughes

Show error message when batch diffs errors

Previously we would keep showing a loading spinner even
if the request throws a 500.
This changes that to instead show a alert saying there was
an error and allows the user to retry loading.

Closes https://gitlab.com/gitlab-org/gitlab/-/issues/337216
parent b09be454
<script> <script>
import { GlLoadingIcon, GlPagination, GlSprintf } from '@gitlab/ui'; import { GlLoadingIcon, GlPagination, GlSprintf, GlAlert } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import { mapState, mapGetters, mapActions } from 'vuex'; import { mapState, mapGetters, mapActions } from 'vuex';
...@@ -78,6 +78,7 @@ export default { ...@@ -78,6 +78,7 @@ export default {
GlPagination, GlPagination,
GlSprintf, GlSprintf,
MrWidgetHowToMergeModal, MrWidgetHowToMergeModal,
GlAlert,
}, },
alerts: { alerts: {
ALERT_OVERFLOW_HIDDEN, ALERT_OVERFLOW_HIDDEN,
...@@ -200,7 +201,6 @@ export default { ...@@ -200,7 +201,6 @@ export default {
...mapState('diffs', [ ...mapState('diffs', [
'showTreeList', 'showTreeList',
'isLoading', 'isLoading',
'isBatchLoading',
'diffFiles', 'diffFiles',
'diffViewType', 'diffViewType',
'commit', 'commit',
...@@ -227,6 +227,8 @@ export default { ...@@ -227,6 +227,8 @@ export default {
'isParallelView', 'isParallelView',
'currentDiffIndex', 'currentDiffIndex',
'isVirtualScrollingEnabled', 'isVirtualScrollingEnabled',
'isBatchLoading',
'isBatchLoadingError',
]), ]),
...mapGetters('batchComments', ['draftsCount']), ...mapGetters('batchComments', ['draftsCount']),
...mapGetters(['isNotesFetched', 'getNoteableData']), ...mapGetters(['isNotesFetched', 'getNoteableData']),
...@@ -621,6 +623,9 @@ export default { ...@@ -621,6 +623,9 @@ export default {
this.subscribedToVirtualScrollingEvents = true; this.subscribedToVirtualScrollingEvents = true;
} }
}, },
reloadPage() {
window.location.reload();
},
}, },
minTreeWidth: MIN_TREE_WIDTH, minTreeWidth: MIN_TREE_WIDTH,
maxTreeWidth: MAX_TREE_WIDTH, maxTreeWidth: MAX_TREE_WIDTH,
...@@ -639,17 +644,19 @@ export default { ...@@ -639,17 +644,19 @@ export default {
:diff-files-count-text="numTotalFiles" :diff-files-count-text="numTotalFiles"
/> />
<hidden-files-warning <template v-if="!isBatchLoadingError">
v-if="visibleWarning == $options.alerts.ALERT_OVERFLOW_HIDDEN" <hidden-files-warning
:visible="numVisibleFiles" v-if="visibleWarning == $options.alerts.ALERT_OVERFLOW_HIDDEN"
:total="numTotalFiles" :visible="numVisibleFiles"
:plain-diff-path="plainDiffPath" :total="numTotalFiles"
:email-patch-path="emailPatchPath" :plain-diff-path="plainDiffPath"
/> :email-patch-path="emailPatchPath"
<collapsed-files-warning />
v-if="visibleWarning == $options.alerts.ALERT_COLLAPSED_FILES" <collapsed-files-warning
:limited="isLimitedContainer" v-if="visibleWarning == $options.alerts.ALERT_COLLAPSED_FILES"
/> :limited="isLimitedContainer"
/>
</template>
<div <div
:data-can-create-note="getNoteableData.current_user.can_create_note" :data-can-create-note="getNoteableData.current_user.can_create_note"
...@@ -678,7 +685,18 @@ export default { ...@@ -678,7 +685,18 @@ export default {
}" }"
> >
<commit-widget v-if="commit" :commit="commit" :collapsible="false" /> <commit-widget v-if="commit" :commit="commit" :collapsible="false" />
<div v-if="isBatchLoading" class="loading"><gl-loading-icon size="lg" /></div> <gl-alert
v-if="isBatchLoadingError"
variant="danger"
:dismissible="false"
:primary-button-text="__('Reload page')"
@primaryAction="reloadPage"
>
{{ __("Error: Couldn't load some or all of the changes.") }}
</gl-alert>
<div v-if="isBatchLoading && !isBatchLoadingError" class="loading">
<gl-loading-icon size="lg" />
</div>
<template v-else-if="renderDiffFiles"> <template v-else-if="renderDiffFiles">
<dynamic-scroller <dynamic-scroller
v-if="isVirtualScrollingEnabled" v-if="isVirtualScrollingEnabled"
...@@ -754,7 +772,10 @@ export default { ...@@ -754,7 +772,10 @@ export default {
</div> </div>
<gl-loading-icon v-else-if="retrievingBatches" size="lg" /> <gl-loading-icon v-else-if="retrievingBatches" size="lg" />
</template> </template>
<no-changes v-else :changes-empty-state-illustration="changesEmptyStateIllustration" /> <no-changes
v-else-if="!isBatchLoadingError"
:changes-empty-state-illustration="changesEmptyStateIllustration"
/>
</div> </div>
</div> </div>
<mr-widget-how-to-merge-modal <mr-widget-how-to-merge-modal
......
...@@ -104,7 +104,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => { ...@@ -104,7 +104,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
let totalLoaded = 0; let totalLoaded = 0;
let scrolledVirtualScroller = false; let scrolledVirtualScroller = false;
commit(types.SET_BATCH_LOADING, true); commit(types.SET_BATCH_LOADING_STATE, 'loading');
commit(types.SET_RETRIEVING_BATCHES, true); commit(types.SET_RETRIEVING_BATCHES, true);
eventHub.$emit(EVT_PERF_MARK_DIFF_FILES_START); eventHub.$emit(EVT_PERF_MARK_DIFF_FILES_START);
...@@ -115,7 +115,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => { ...@@ -115,7 +115,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
totalLoaded += diff_files.length; totalLoaded += diff_files.length;
commit(types.SET_DIFF_DATA_BATCH, { diff_files }); commit(types.SET_DIFF_DATA_BATCH, { diff_files });
commit(types.SET_BATCH_LOADING, false); commit(types.SET_BATCH_LOADING_STATE, 'loaded');
if (window.gon?.features?.diffsVirtualScrolling && !scrolledVirtualScroller) { if (window.gon?.features?.diffsVirtualScrolling && !scrolledVirtualScroller) {
const index = state.diffFiles.findIndex( const index = state.diffFiles.findIndex(
...@@ -130,7 +130,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => { ...@@ -130,7 +130,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
} }
if (!isNoteLink && !state.currentDiffFileId) { if (!isNoteLink && !state.currentDiffFileId) {
commit(types.VIEW_DIFF_FILE, diff_files[0].file_hash); commit(types.VIEW_DIFF_FILE, diff_files[0]?.file_hash);
} }
if (isNoteLink) { if (isNoteLink) {
...@@ -182,11 +182,14 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => { ...@@ -182,11 +182,14 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
return null; return null;
}) })
.catch(() => commit(types.SET_RETRIEVING_BATCHES, false)); .catch(() => {
commit(types.SET_RETRIEVING_BATCHES, false);
commit(types.SET_BATCH_LOADING_STATE, 'error');
});
return getBatch() return getBatch().then(
.then(() => !window.gon?.features?.diffsVirtualScrolling && handleLocationHash()) () => !window.gon?.features?.diffsVirtualScrolling && handleLocationHash(),
.catch(() => null); );
}; };
export const fetchDiffFilesMeta = ({ commit, state }) => { export const fetchDiffFilesMeta = ({ commit, state }) => {
......
...@@ -191,3 +191,6 @@ export const isVirtualScrollingEnabled = (state) => { ...@@ -191,3 +191,6 @@ export const isVirtualScrollingEnabled = (state) => {
getParameterValues('virtual_scrolling')[0] === 'true') getParameterValues('virtual_scrolling')[0] === 'true')
); );
}; };
export const isBatchLoading = (state) => state.batchLoadingState === 'loading';
export const isBatchLoadingError = (state) => state.batchLoadingState === 'error';
...@@ -12,7 +12,7 @@ const defaultViewType = INLINE_DIFF_VIEW_TYPE; ...@@ -12,7 +12,7 @@ const defaultViewType = INLINE_DIFF_VIEW_TYPE;
export default () => ({ export default () => ({
isLoading: true, isLoading: true,
isTreeLoaded: false, isTreeLoaded: false,
isBatchLoading: false, batchLoadingState: null,
retrievingBatches: false, retrievingBatches: false,
addedLines: null, addedLines: null,
removedLines: null, removedLines: null,
......
export const SET_BASE_CONFIG = 'SET_BASE_CONFIG'; export const SET_BASE_CONFIG = 'SET_BASE_CONFIG';
export const SET_LOADING = 'SET_LOADING'; export const SET_LOADING = 'SET_LOADING';
export const SET_BATCH_LOADING = 'SET_BATCH_LOADING'; export const SET_BATCH_LOADING_STATE = 'SET_BATCH_LOADING_STATE';
export const SET_RETRIEVING_BATCHES = 'SET_RETRIEVING_BATCHES'; export const SET_RETRIEVING_BATCHES = 'SET_RETRIEVING_BATCHES';
export const SET_DIFF_METADATA = 'SET_DIFF_METADATA'; export const SET_DIFF_METADATA = 'SET_DIFF_METADATA';
......
...@@ -60,8 +60,8 @@ export default { ...@@ -60,8 +60,8 @@ export default {
Object.assign(state, { isLoading }); Object.assign(state, { isLoading });
}, },
[types.SET_BATCH_LOADING](state, isBatchLoading) { [types.SET_BATCH_LOADING_STATE](state, batchLoadingState) {
Object.assign(state, { isBatchLoading }); Object.assign(state, { batchLoadingState });
}, },
[types.SET_RETRIEVING_BATCHES](state, retrievingBatches) { [types.SET_RETRIEVING_BATCHES](state, retrievingBatches) {
......
...@@ -13268,6 +13268,9 @@ msgstr "" ...@@ -13268,6 +13268,9 @@ msgstr ""
msgid "Error: %{error_message}" msgid "Error: %{error_message}"
msgstr "" msgstr ""
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
msgid "Error: No AWS credentials were supplied" msgid "Error: No AWS credentials were supplied"
msgstr "" msgstr ""
...@@ -27793,6 +27796,9 @@ msgstr "" ...@@ -27793,6 +27796,9 @@ msgstr ""
msgid "Release|Something went wrong while saving the release details." msgid "Release|Something went wrong while saving the release details."
msgstr "" msgstr ""
msgid "Reload page"
msgstr ""
msgid "Remediations" msgid "Remediations"
msgstr "" msgstr ""
......
...@@ -183,7 +183,7 @@ describe('diffs/components/app', () => { ...@@ -183,7 +183,7 @@ describe('diffs/components/app', () => {
it('displays loading icon on batch loading', () => { it('displays loading icon on batch loading', () => {
createComponent({}, ({ state }) => { createComponent({}, ({ state }) => {
state.diffs.isBatchLoading = true; state.diffs.batchLoadingState = 'loading';
}); });
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
......
...@@ -186,15 +186,16 @@ describe('DiffsStoreActions', () => { ...@@ -186,15 +186,16 @@ describe('DiffsStoreActions', () => {
{}, {},
{ endpointBatch, diffViewType: 'inline' }, { endpointBatch, diffViewType: 'inline' },
[ [
{ type: types.SET_BATCH_LOADING, payload: true }, { type: types.SET_BATCH_LOADING_STATE, payload: 'loading' },
{ type: types.SET_RETRIEVING_BATCHES, payload: true }, { type: types.SET_RETRIEVING_BATCHES, payload: true },
{ type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res1.diff_files } }, { type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res1.diff_files } },
{ type: types.SET_BATCH_LOADING, payload: false }, { type: types.SET_BATCH_LOADING_STATE, payload: 'loaded' },
{ type: types.VIEW_DIFF_FILE, payload: 'test' }, { type: types.VIEW_DIFF_FILE, payload: 'test' },
{ type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res2.diff_files } }, { type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res2.diff_files } },
{ type: types.SET_BATCH_LOADING, payload: false }, { type: types.SET_BATCH_LOADING_STATE, payload: 'loaded' },
{ type: types.VIEW_DIFF_FILE, payload: 'test2' }, { type: types.VIEW_DIFF_FILE, payload: 'test2' },
{ type: types.SET_RETRIEVING_BATCHES, payload: false }, { type: types.SET_RETRIEVING_BATCHES, payload: false },
{ type: types.SET_BATCH_LOADING_STATE, payload: 'error' },
], ],
[{ type: 'startRenderDiffsQueue' }, { type: 'startRenderDiffsQueue' }], [{ type: 'startRenderDiffsQueue' }, { type: 'startRenderDiffsQueue' }],
done, done,
......
...@@ -31,13 +31,13 @@ describe('DiffsStoreMutations', () => { ...@@ -31,13 +31,13 @@ describe('DiffsStoreMutations', () => {
}); });
}); });
describe('SET_BATCH_LOADING', () => { describe('SET_BATCH_LOADING_STATE', () => {
it('should set loading state', () => { it('should set loading state', () => {
const state = {}; const state = {};
mutations[types.SET_BATCH_LOADING](state, false); mutations[types.SET_BATCH_LOADING_STATE](state, false);
expect(state.isBatchLoading).toEqual(false); expect(state.batchLoadingState).toEqual(false);
}); });
}); });
......
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