Add loading indicator to save button on scaffolded forms

This commit is contained in:
David Craig 2016-04-26 14:31:37 +12:00 committed by Ingo Schommer
parent 576e916504
commit 8af1ad09d0
8 changed files with 77 additions and 5 deletions

View File

@ -72,7 +72,7 @@ class FormAction extends SilverStripeComponent {
* @returns object|null
*/
getLoadingIcon() {
if (this.props.loading) {
if (this.props.loading === true) {
return (
<div className="btn__loading-icon" >
<svg viewBox="0 0 44 12">

View File

@ -316,6 +316,7 @@ export class FormBuilderComponent extends SilverStripeComponent {
*/
mapActionsToComponents(actions) {
const createFn = this.props.createFn;
const form = this.props.form[this.getFormId()];
return actions.map((action, i) => {
let props = deepFreeze(action);
@ -327,6 +328,7 @@ export class FormBuilderComponent extends SilverStripeComponent {
type: 'submit',
label: props.title,
icon: 'save',
loading: typeof form !== 'undefined' ? form.submitting : false,
bootstrapButtonStyle: 'success',
}, props));
break;
@ -401,7 +403,7 @@ export class FormBuilderComponent extends SilverStripeComponent {
// If there is structural and state data availabe merge those data for each field.
// Otherwise just use the structural data.
const fieldData = formSchema.schema && formState
const fieldData = formSchema.schema && formState && formState.fields
? formSchema.schema.fields.map((f, i) => this.mergeFieldData(f, formState.fields[i]))
: formSchema.schema.fields;

View File

@ -59,7 +59,7 @@ export function submitForm(submitApi, formId, fieldValues) {
return (dispatch) => {
dispatch({
type: ACTION_TYPES.SUBMIT_FORM_REQUEST,
payload: {},
payload: { formId },
});
submitApi(Object.assign({ ID: formId }, fieldValues), { 'X-Formschema-Request': 'state' })
@ -72,7 +72,7 @@ export function submitForm(submitApi, formId, fieldValues) {
.catch((error) => {
dispatch({
type: ACTION_TYPES.SUBMIT_FORM_FAILURE,
payload: { error },
payload: { formId, error },
});
});
};

View File

@ -6,6 +6,11 @@ const initialState = deepFreeze({});
function formReducer(state = initialState, action) {
switch (action.type) {
case ACTION_TYPES.SUBMIT_FORM_REQUEST:
return deepFreeze(Object.assign({}, state, {
[action.payload.formId]: { submitting: true },
}));
case ACTION_TYPES.REMOVE_FORM:
return deepFreeze(Object.keys(state).reduce((previous, current) => {
if (current === action.payload.formId) {
@ -18,7 +23,10 @@ function formReducer(state = initialState, action) {
case ACTION_TYPES.ADD_FORM:
return deepFreeze(Object.assign({}, state, {
[action.payload.formState.id]: { fields: action.payload.formState.fields },
[action.payload.formState.id]: {
fields: action.payload.formState.fields,
submitting: false,
},
}));
case ACTION_TYPES.UPDATE_FIELD:
@ -38,9 +46,15 @@ function formReducer(state = initialState, action) {
[action.payload.response.id]: {
fields: action.payload.response.state.fields,
messages: action.payload.response.state.messages,
submitting: false,
},
}));
case ACTION_TYPES.SUBMIT_FORM_FAILURE:
return deepFreeze(Object.assign({}, state, {
[action.payload.formId]: { submitting: false },
}));
default:
return state;

View File

@ -21,6 +21,7 @@ describe('formReducer', () => {
value: 'Test',
},
],
submitting: false,
},
});
@ -54,6 +55,7 @@ describe('formReducer', () => {
expect(nextState.EditForm.fields[0].messages).toBeDefined();
expect(nextState.EditForm.fields[0].valid).toBe(true);
expect(nextState.EditForm.fields[0].value).toBe('Test');
expect(nextState.EditForm.submitting).toBe(false);
});
});
@ -137,6 +139,7 @@ describe('formReducer', () => {
value: 'Test',
},
],
submitting: true,
},
});
@ -172,6 +175,59 @@ describe('formReducer', () => {
expect(nextState.DetailEditForm.messages.length).toBe(1);
expect(nextState.DetailEditForm.messages[0].type).toBe('good');
expect(nextState.DetailEditForm.messages[0].value).toBe('Saved.');
expect(nextState.DetailEditForm.submitting).toBe(false);
});
});
describe('SUBMIT_FORM_REQUEST', () => {
it('should set submitting to true', () => {
const initialState = deepFreeze({
DetailEditForm: {
fields: [
{
data: [],
id: 'Form_DetailEditForm_Name',
messages: [],
valid: true,
value: 'Test',
},
],
submitting: false,
},
});
const nextState = formReducer(initialState, {
type: ACTION_TYPES.SUBMIT_FORM_REQUEST,
payload: { formId: 'DetailEditForm' },
});
expect(nextState.DetailEditForm.submitting).toBe(true);
});
});
describe('SUBMIT_FORM_FAILURE', () => {
it('should set submitting to false', () => {
const initialState = deepFreeze({
DetailEditForm: {
fields: [
{
data: [],
id: 'Form_DetailEditForm_Name',
messages: [],
valid: true,
value: 'Test',
},
],
submitting: true,
},
});
const nextState = formReducer(initialState, {
type: ACTION_TYPES.SUBMIT_FORM_FAILURE,
payload: { formId: 'DetailEditForm' },
});
expect(nextState.DetailEditForm.submitting).toBe(false);
});
});
});