Flash an error on save when required fields are missed
- Add error type constants - Flash an error message when the user saves without completing all required fields - Surface presence errors
This commit is contained in:
committed by
Shawn Erquhart
parent
b501db7239
commit
c97856c71d
@ -7,6 +7,7 @@ import { getIntegrationProvider } from '../integrations';
|
||||
import { getAsset, selectIntegration } from '../reducers';
|
||||
import { selectFields } from '../reducers/collections';
|
||||
import { createEntry } from '../valueObjects/Entry';
|
||||
import ValidationErrorTypes from '../constants/validationErrorTypes';
|
||||
|
||||
const { notifSend } = notifActions;
|
||||
|
||||
@ -265,9 +266,23 @@ export function persistEntry(collection) {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const entryDraft = state.entryDraft;
|
||||
const fieldsErrors = entryDraft.get('fieldsErrors');
|
||||
|
||||
// Early return if draft contains validation errors
|
||||
if (!entryDraft.get('fieldsErrors').isEmpty()) return Promise.reject();
|
||||
if (!fieldsErrors.isEmpty()) {
|
||||
const hasPresenceErrors = fieldsErrors
|
||||
.some(errors => errors.some(error => error.type && error.type === ValidationErrorTypes.PRESENCE));
|
||||
|
||||
if (hasPresenceErrors) {
|
||||
dispatch(notifSend({
|
||||
message: 'Oops, you\'ve missed a required field. Please complete before saving.',
|
||||
kind: 'danger',
|
||||
dismissAfter: 8000,
|
||||
}));
|
||||
}
|
||||
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
const backend = currentBackend(state.config);
|
||||
const assetProxies = entryDraft.get('mediaFiles').map(path => getAsset(state, path));
|
||||
|
@ -37,9 +37,11 @@ export default class ControlPane extends Component {
|
||||
<label className={labelClass} htmlFor={fieldName}>{field.get('label')}</label>
|
||||
<ul className="nc-controlPane-errors">
|
||||
{
|
||||
errors && errors.map(error => (
|
||||
typeof error === 'string' && <li key={error.trim().replace(/[^a-z0-9]+/gi, '-')}>{error}</li>
|
||||
))
|
||||
errors && errors.map(error =>
|
||||
error.message &&
|
||||
typeof error.message === 'string' &&
|
||||
<li key={error.message.trim().replace(/[^a-z0-9]+/gi, '-')}>{error.message}</li>
|
||||
)
|
||||
}
|
||||
</ul>
|
||||
<ControlHOC
|
||||
|
@ -1,6 +1,7 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import ImmutablePropTypes from "react-immutable-proptypes";
|
||||
import ValidationErrorTypes from '../../constants/validationErrorTypes';
|
||||
|
||||
const truthy = () => ({ error: false });
|
||||
|
||||
@ -57,16 +58,27 @@ class ControlHOC extends Component {
|
||||
(value.hasOwnProperty('length') && value.length === 0) ||
|
||||
(value.constructor === Object && Object.keys(value).length === 0)
|
||||
)) {
|
||||
return { error: true };
|
||||
const error = {
|
||||
type: ValidationErrorTypes.PRESENCE,
|
||||
message: `${ field.get('label', field.get('name')) } is required.`,
|
||||
};
|
||||
|
||||
return { error };
|
||||
}
|
||||
return { error: false };
|
||||
return { error: false };
|
||||
}
|
||||
|
||||
validatePattern(field, value) {
|
||||
const pattern = field.get('pattern', false);
|
||||
if (pattern && !RegExp(pattern.first()).test(value)) {
|
||||
return { error: `${ field.get('label', field.get('name')) } didn't match the pattern: ${ pattern.last() }` };
|
||||
const error = {
|
||||
type: ValidationErrorTypes.PATTERN,
|
||||
message: `${ field.get('label', field.get('name')) } didn't match the pattern: ${ pattern.last() }`,
|
||||
};
|
||||
|
||||
return { error };
|
||||
}
|
||||
|
||||
return { error: false };
|
||||
}
|
||||
|
||||
@ -80,11 +92,22 @@ class ControlHOC extends Component {
|
||||
} else if (response instanceof Promise) {
|
||||
response.then(
|
||||
() => { this.validate({ error: false }); },
|
||||
(error) => {
|
||||
this.validate({ error: `${ field.get('label', field.get('name')) } - ${ error }.` });
|
||||
(err) => {
|
||||
const error = {
|
||||
type: ValidationErrorTypes.CUSTOM,
|
||||
message: `${ field.get('label', field.get('name')) } - ${ err }.`,
|
||||
};
|
||||
|
||||
this.validate({ error });
|
||||
}
|
||||
);
|
||||
return { error: `${ field.get('label', field.get('name')) } is processing.` };
|
||||
|
||||
const error = {
|
||||
type: ValidationErrorTypes.CUSTOM,
|
||||
message: `${ field.get('label', field.get('name')) } is processing.`,
|
||||
};
|
||||
|
||||
return { error };
|
||||
}
|
||||
return { error: false };
|
||||
};
|
||||
|
5
src/constants/validationErrorTypes.js
Normal file
5
src/constants/validationErrorTypes.js
Normal file
@ -0,0 +1,5 @@
|
||||
export default {
|
||||
PRESENCE: 'PRESENCE',
|
||||
PATTERN: 'PATTERN',
|
||||
CUSTOM: 'CUSTOM',
|
||||
};
|
Reference in New Issue
Block a user