Commit 4d69c73d authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Fixes the flash of text after editing

Adds a loading icon when we are editing
a custom stage, the loader will disappear
once the updated stages have been fetched.

Adds set / clear actions for the saving state

Updates related specs
parent f8f9e71d
......@@ -296,7 +296,11 @@ export default {
/>
</template>
<template v-if="customStageFormActive" #content>
<div v-if="isEditingCustomStage && isSavingCustomStage">
<gl-loading-icon class="mt-4" size="md" />
</div>
<custom-stage-form
v-else
:events="formEvents"
:is-saving-custom-stage="isSavingCustomStage"
:initial-fields="formInitialData"
......
......@@ -179,12 +179,12 @@ export const requestUpdateStage = ({ commit }) => commit(types.REQUEST_UPDATE_ST
export const receiveUpdateStageSuccess = ({ commit, dispatch }, updatedData) => {
commit(types.RECEIVE_UPDATE_STAGE_SUCCESS);
createFlash(__('Stage data updated'), 'notice');
return Promise.all([
dispatch('fetchGroupStagesAndEvents'),
dispatch('customStages/showEditForm', updatedData),
]).catch(() => {
createFlash(__('There was a problem refreshing the data, please try again'));
});
return Promise.resolve()
.then(() => dispatch('fetchGroupStagesAndEvents'))
.then(() => dispatch('customStages/showEditForm', updatedData))
.catch(() => {
createFlash(__('There was a problem refreshing the data, please try again'));
});
};
export const receiveUpdateStageError = (
......@@ -209,6 +209,7 @@ export const updateStage = ({ dispatch, state }, { id, ...rest }) => {
} = state;
dispatch('requestUpdateStage');
dispatch('customStages/setSavingCustomStage');
return Api.cycleAnalyticsUpdateStage(id, fullPath, { ...rest })
.then(({ data }) => dispatch('receiveUpdateStageSuccess', data))
......
......@@ -31,6 +31,7 @@ export const showEditForm = ({ commit, dispatch }, selectedStage = {}) => {
commit(types.SET_FORM_INITIAL_DATA, selectedStage);
commit(types.SHOW_EDIT_FORM);
dispatch('setSelectedStage', selectedStage, { root: true });
dispatch('clearSavingCustomStage');
removeFlash();
};
......@@ -39,13 +40,16 @@ export const clearFormErrors = ({ commit }) => {
removeFlash();
};
export const requestCreateStage = ({ commit }) => commit(types.REQUEST_CREATE_STAGE);
export const setSavingCustomStage = ({ commit }) => commit(types.SET_SAVING_CUSTOM_STAGE);
export const clearSavingCustomStage = ({ commit }) => commit(types.CLEAR_SAVING_CUSTOM_STAGE);
export const receiveCreateStageSuccess = ({ commit, dispatch }, { data: { title } }) => {
commit(types.RECEIVE_CREATE_STAGE_SUCCESS);
createFlash(sprintf(__(`Your custom stage '%{title}' was created`), { title }), 'notice');
return Promise.resolve()
.then(() => dispatch('fetchGroupStagesAndEvents', null, { root: true }))
.then(() => dispatch('clearSavingCustomStage'))
.catch(() => {
createFlash(__('There was a problem refreshing the data, please try again'));
});
......@@ -71,7 +75,8 @@ export const createStage = ({ dispatch, rootState }, data) => {
selectedGroup: { fullPath },
} = rootState;
dispatch('requestCreateStage');
dispatch('clearFormErrors');
dispatch('setSavingCustomStage');
return Api.cycleAnalyticsCreateStage(fullPath, data)
.then(response => {
......@@ -80,7 +85,6 @@ export const createStage = ({ dispatch, rootState }, data) => {
})
.catch(({ response } = {}) => {
const { data: { message, errors } = null, status = 400 } = response;
dispatch('receiveCreateStageError', { data, message, errors, status });
});
};
export const SET_STAGE_EVENTS = 'SET_STAGE_EVENTS';
export const SET_STAGE_FORM_ERRORS = 'SET_STAGE_FORM_ERRORS';
export const SET_FORM_INITIAL_DATA = 'SET_FORM_INITIAL_DATA';
export const SET_SAVING_CUSTOM_STAGE = 'SET_SAVING_CUSTOM_STAGE';
export const CLEAR_SAVING_CUSTOM_STAGE = 'CLEAR_SAVING_CUSTOM_STAGE';
export const HIDE_FORM = 'SHOW_FORM';
export const SHOW_CREATE_FORM = 'SHOW_CREATE_FORM';
export const SHOW_EDIT_FORM = 'SHOW_EDIT_FORM';
export const CLEAR_FORM_ERRORS = 'CLEAR_FORM_ERRORS';
export const REQUEST_CREATE_STAGE = 'REQUEST_CREATE_STAGE';
export const RECEIVE_CREATE_STAGE_SUCCESS = 'RECEIVE_CREATE_STAGE_SUCCESS';
export const RECEIVE_CREATE_STAGE_ERROR = 'RECEIVE_CREATE_STAGE_ERROR';
......@@ -28,12 +28,17 @@ export default {
state.formEvents = data.map(ev => convertObjectPropsToCamelCase(ev, { deep: true }));
},
[types.SET_STAGE_FORM_ERRORS](state, errors) {
state.isSavingCustomStage = false;
state.formErrors = convertObjectPropsToCamelCase(errors, { deep: true });
},
[types.SET_FORM_INITIAL_DATA](state, rawStageData = null) {
state.formInitialData = extractFormFields(rawStageData);
},
[types.SET_SAVING_CUSTOM_STAGE](state) {
state.isSavingCustomStage = true;
},
[types.CLEAR_SAVING_CUSTOM_STAGE](state) {
state.isSavingCustomStage = false;
},
[types.SHOW_CREATE_FORM](state) {
state.isEditingCustomStage = false;
state.isCreatingCustomStage = true;
......@@ -46,7 +51,6 @@ export default {
state.formErrors = null;
},
[types.HIDE_FORM](state) {
state.isSavingCustomStage = false;
state.isEditingCustomStage = false;
state.isCreatingCustomStage = false;
state.formInitialData = null;
......@@ -55,15 +59,10 @@ export default {
[types.CLEAR_FORM_ERRORS](state) {
state.formErrors = null;
},
[types.REQUEST_CREATE_STAGE](state) {
state.isSavingCustomStage = true;
state.formErrors = {};
},
[types.RECEIVE_CREATE_STAGE_ERROR](state) {
state.isSavingCustomStage = false;
},
[types.RECEIVE_CREATE_STAGE_SUCCESS](state) {
state.isSavingCustomStage = false;
state.formErrors = null;
state.formInitialData = null;
},
......
......@@ -28,7 +28,7 @@ const stageEndpoint = ({ stageId }) =>
jest.mock('~/flash');
describe('Cycle analytics actions', () => {
describe.only('Cycle analytics actions', () => {
let state;
let mock;
......@@ -382,7 +382,7 @@ describe('Cycle analytics actions', () => {
state = { selectedGroup };
});
it('dispatches receiveUpdateStageSuccess with put request response data', () => {
it('dispatches receiveUpdateStageSuccess and customStages/setSavingCustomStage', () => {
return testAction(
actions.updateStage,
{
......@@ -393,6 +393,7 @@ describe('Cycle analytics actions', () => {
[],
[
{ type: 'requestUpdateStage' },
{ type: 'customStages/setSavingCustomStage' },
{
type: 'receiveUpdateStageSuccess',
payload,
......@@ -420,6 +421,7 @@ describe('Cycle analytics actions', () => {
[],
[
{ type: 'requestUpdateStage' },
{ type: 'customStages/setSavingCustomStage' },
{
type: 'receiveUpdateStageError',
payload: {
......@@ -703,7 +705,8 @@ describe('Cycle analytics actions', () => {
state,
[],
[
{ type: 'requestCreateStage' },
{ type: 'clearFormErrors' },
{ type: 'setSavingCustomStage' },
{
type: 'receiveCreateStageSuccess',
payload: { data: customStageData, status: 201 },
......@@ -740,7 +743,8 @@ describe('Cycle analytics actions', () => {
state,
[],
[
{ type: 'requestCreateStage' },
{ type: 'clearFormErrors' },
{ type: 'setSavingCustomStage' },
{
type: 'receiveCreateStageError',
payload: {
......@@ -768,7 +772,12 @@ describe('Cycle analytics actions', () => {
response,
state,
[{ type: customStageTypes.RECEIVE_CREATE_STAGE_ERROR }],
[{ type: 'setStageFormErrors', payload: {} }],
[
{
type: 'setStageFormErrors',
payload: {},
},
],
));
it('will flash an error message', () => {
......@@ -878,7 +887,7 @@ describe('Cycle analytics actions', () => {
response,
state,
[{ type: customStageTypes.RECEIVE_CREATE_STAGE_SUCCESS }],
[{ type: 'fetchGroupStagesAndEvents', payload: null }],
[{ type: 'fetchGroupStagesAndEvents', payload: null }, { type: 'clearSavingCustomStage' }],
));
describe('with an error', () => {
......
......@@ -80,21 +80,20 @@ describe('Cycle analytics mutations', () => {
});
it.each`
mutation | stateKey | value
${customStageTypes.HIDE_FORM} | ${'isCreatingCustomStage'} | ${false}
${customStageTypes.HIDE_FORM} | ${'isEditingCustomStage'} | ${false}
${customStageTypes.HIDE_FORM} | ${'formErrors'} | ${null}
${customStageTypes.HIDE_FORM} | ${'formInitialData'} | ${null}
${customStageTypes.SHOW_CREATE_FORM} | ${'isCreatingCustomStage'} | ${true}
${customStageTypes.SHOW_CREATE_FORM} | ${'isEditingCustomStage'} | ${false}
${customStageTypes.SHOW_CREATE_FORM} | ${'formErrors'} | ${null}
${customStageTypes.SHOW_EDIT_FORM} | ${'isEditingCustomStage'} | ${true}
${customStageTypes.SHOW_EDIT_FORM} | ${'isCreatingCustomStage'} | ${false}
${customStageTypes.SHOW_EDIT_FORM} | ${'formErrors'} | ${null}
${customStageTypes.REQUEST_CREATE_STAGE} | ${'isSavingCustomStage'} | ${true}
${customStageTypes.RECEIVE_CREATE_STAGE_SUCCESS} | ${'isSavingCustomStage'} | ${false}
${customStageTypes.RECEIVE_CREATE_STAGE_ERROR} | ${'isSavingCustomStage'} | ${false}
${customStageTypes.SET_STAGE_FORM_ERRORS} | ${'isSavingCustomStage'} | ${false}
mutation | stateKey | value
${customStageTypes.HIDE_FORM} | ${'isCreatingCustomStage'} | ${false}
${customStageTypes.HIDE_FORM} | ${'isEditingCustomStage'} | ${false}
${customStageTypes.HIDE_FORM} | ${'formErrors'} | ${null}
${customStageTypes.HIDE_FORM} | ${'formInitialData'} | ${null}
${customStageTypes.SHOW_CREATE_FORM} | ${'isCreatingCustomStage'} | ${true}
${customStageTypes.SHOW_CREATE_FORM} | ${'isEditingCustomStage'} | ${false}
${customStageTypes.SHOW_CREATE_FORM} | ${'formErrors'} | ${null}
${customStageTypes.SHOW_EDIT_FORM} | ${'isEditingCustomStage'} | ${true}
${customStageTypes.SHOW_EDIT_FORM} | ${'isCreatingCustomStage'} | ${false}
${customStageTypes.SHOW_EDIT_FORM} | ${'formErrors'} | ${null}
${customStageTypes.RECEIVE_CREATE_STAGE_ERROR} | ${'isSavingCustomStage'} | ${false}
${customStageTypes.SET_SAVING_CUSTOM_STAGE} | ${'isSavingCustomStage'} | ${true}
${customStageTypes.CLEAR_SAVING_CUSTOM_STAGE} | ${'isSavingCustomStage'} | ${false}
`('$mutation will set $stateKey=$value', ({ mutation, stateKey, value }) => {
customStageMutations[mutation](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