mirror of
https://github.com/strapi/strapi.git
synced 2025-09-24 16:04:54 +00:00
Add errors and prepare for submit request
This commit is contained in:
parent
10599cfab8
commit
fbcce82f8e
@ -37,6 +37,12 @@ class InputSelectWithErrors extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleBlur = ({ target }) => {
|
||||
if (!isEmpty(target.value)) {
|
||||
this.setState({ errors: [] });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
autoFocus,
|
||||
@ -86,7 +92,7 @@ class InputSelectWithErrors extends React.Component {
|
||||
disabled={disabled}
|
||||
error={!isEmpty(this.state.errors)}
|
||||
name={name}
|
||||
onBlur={isFunction(onBlur) ? onBlur : () => {}}
|
||||
onBlur={isFunction(onBlur) ? onBlur : this.handleBlur}
|
||||
onChange={onChange}
|
||||
onFocus={onFocus}
|
||||
selectOptions={selectOptions}
|
||||
@ -127,7 +133,7 @@ InputSelectWithErrors.defaultProps = {
|
||||
label: '',
|
||||
labelClassName: '',
|
||||
labelStyle: {},
|
||||
onBlur: () => {},
|
||||
onBlur: false,
|
||||
onFocus: () => {},
|
||||
selectOptions: [],
|
||||
style: {},
|
||||
|
@ -21,7 +21,7 @@ function PluginHeaderTitle({ description, title }) {
|
||||
{contentTitle}
|
||||
</h1>
|
||||
<p className={styles.pluginHeaderTitleDescription}>
|
||||
{contentDescription}
|
||||
{contentDescription}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
@ -7,7 +7,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
// findIndex,
|
||||
findIndex,
|
||||
get,
|
||||
isEmpty,
|
||||
isFunction,
|
||||
@ -69,6 +69,11 @@ class Edit extends React.PureComponent {
|
||||
this.setState({ currentLayout, displayedFields });
|
||||
}
|
||||
|
||||
getInputErrors = (attr) => {
|
||||
const index = findIndex(this.props.formErrors, ['name', attr]);
|
||||
return index !== -1 ? this.props.formErrors[index].errors : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Input layout
|
||||
* @param {String} attr [description]
|
||||
@ -83,6 +88,18 @@ class Edit extends React.PureComponent {
|
||||
}, {})
|
||||
)
|
||||
|
||||
/**
|
||||
* Retrieve the input's validations
|
||||
* @param {String} attr
|
||||
* @return {Object}
|
||||
*/
|
||||
getInputValidations = (attr) => {
|
||||
const { formValidations } = this.props;
|
||||
const index = findIndex(formValidations, ['name', attr]);
|
||||
|
||||
return get(formValidations, [index, 'validations'], {});
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div className={styles.form}>
|
||||
@ -97,6 +114,7 @@ class Edit extends React.PureComponent {
|
||||
autoFocus={key === 0}
|
||||
customBootstrapClass={get(layout, 'className')}
|
||||
didCheckErrors={this.props.didCheckErrors}
|
||||
errors={this.getInputErrors(attr)}
|
||||
key={attr}
|
||||
label={get(layout, 'label') || details.label || ''}
|
||||
name={attr}
|
||||
@ -104,6 +122,7 @@ class Edit extends React.PureComponent {
|
||||
selectOptions={get(this.props.attributes, [attr, 'enum'])}
|
||||
placeholder={get(layout, 'placeholder') || details.placeholder}
|
||||
type={get(layout, 'type', getInputType(details.type))}
|
||||
validations={this.getInputValidations(attr)}
|
||||
value={this.props.record[attr]}
|
||||
/>
|
||||
);
|
||||
@ -116,6 +135,8 @@ class Edit extends React.PureComponent {
|
||||
|
||||
Edit.defaultProps = {
|
||||
attributes: {},
|
||||
formErrors: [],
|
||||
formValidations: [],
|
||||
layout: {},
|
||||
onChange: () => {},
|
||||
record: {},
|
||||
@ -124,6 +145,8 @@ Edit.defaultProps = {
|
||||
Edit.propTypes = {
|
||||
attributes: PropTypes.object,
|
||||
didCheckErrors: PropTypes.bool.isRequired,
|
||||
formErrors: PropTypes.array,
|
||||
formValidations: PropTypes.array,
|
||||
layout: PropTypes.object,
|
||||
onChange: PropTypes.func,
|
||||
record: PropTypes.object,
|
||||
|
@ -4,12 +4,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import { get } from 'lodash';
|
||||
import { getValidationsFromForm } from 'utils/formValidations';
|
||||
|
||||
import {
|
||||
CHANGE_DATA,
|
||||
GET_DATA,
|
||||
GET_DATA_SUCCEEDED,
|
||||
INIT_MODEL_PROPS,
|
||||
ON_CANCEL,
|
||||
RESET_PROPS,
|
||||
SET_FORM_ERRORS,
|
||||
} from './constants';
|
||||
|
||||
export function changeData({ target }) {
|
||||
@ -38,17 +43,36 @@ export function getDataSucceeded(id, data, pluginHeaderTitle) {
|
||||
};
|
||||
}
|
||||
|
||||
export function initModelProps(modelName, isCreating, source) {
|
||||
export function initModelProps(modelName, isCreating, source, attributes) {
|
||||
const formValidations = getValidationsFromForm(
|
||||
Object.keys(attributes).map(attr => ({ name: attr, validations: get(attributes, attr, {}) })),
|
||||
[],
|
||||
);
|
||||
|
||||
return {
|
||||
type: INIT_MODEL_PROPS,
|
||||
modelName,
|
||||
formValidations,
|
||||
isCreating,
|
||||
modelName,
|
||||
source,
|
||||
};
|
||||
}
|
||||
|
||||
export function onCancel() {
|
||||
return {
|
||||
type: ON_CANCEL,
|
||||
};
|
||||
}
|
||||
|
||||
export function resetProps() {
|
||||
return {
|
||||
type: RESET_PROPS,
|
||||
};
|
||||
}
|
||||
|
||||
export function setFormErrors(formErrors) {
|
||||
return {
|
||||
type: SET_FORM_ERRORS,
|
||||
formErrors,
|
||||
};
|
||||
}
|
||||
|
@ -8,4 +8,6 @@ export const CHANGE_DATA = 'ContentManager/EditPage/CHANGE_DATA';
|
||||
export const GET_DATA = 'ContentManager/EditPage/GET_DATA';
|
||||
export const GET_DATA_SUCCEEDED = 'ContentManager/EditPage/GET_DATA_SUCCEEDED';
|
||||
export const INIT_MODEL_PROPS = 'ContentManager/EditPage/INIT_MODEL_PROPS';
|
||||
export const ON_CANCEL = 'ContentManager/EditPage/ON_CANCEL';
|
||||
export const RESET_PROPS = 'ContentManager/EditPage/RESET_PROPS';
|
||||
export const SET_FORM_ERRORS = 'ContentManager/EditPage/SET_FORM_ERRORS';
|
||||
|
@ -10,7 +10,7 @@ import { connect } from 'react-redux';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import PropTypes from 'prop-types';
|
||||
import { get, isObject, toNumber, toString, size } from 'lodash';
|
||||
import { get, isEmpty, isObject, toNumber, toString, size } from 'lodash';
|
||||
import cn from 'classnames';
|
||||
|
||||
// You can find these components in either
|
||||
@ -30,6 +30,7 @@ import injectReducer from 'utils/injectReducer';
|
||||
import injectSaga from 'utils/injectSaga';
|
||||
import getQueryParameters from 'utils/getQueryParameters';
|
||||
import { bindLayout } from 'utils/bindLayout';
|
||||
import { checkFormValidity } from 'utils/formValidations';
|
||||
|
||||
// Layout
|
||||
import layout from '../../../../config/layout';
|
||||
@ -38,7 +39,9 @@ import {
|
||||
changeData,
|
||||
getData,
|
||||
initModelProps,
|
||||
onCancel,
|
||||
resetProps,
|
||||
setFormErrors,
|
||||
} from './actions';
|
||||
|
||||
import reducer from './reducer';
|
||||
@ -115,6 +118,17 @@ export class EditPage extends React.Component {
|
||||
this.props.changeData({ target });
|
||||
}
|
||||
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
const formErrors = checkFormValidity(this.generateFormFromRecord(), this.props.editPage.formValidations);
|
||||
|
||||
if (isEmpty(formErrors)) {
|
||||
// this.props.submit()
|
||||
}
|
||||
|
||||
this.props.setFormErrors(formErrors);
|
||||
}
|
||||
|
||||
layout = bindLayout.call(this, layout);
|
||||
|
||||
componentDidCatch(error, info) {
|
||||
@ -126,11 +140,20 @@ export class EditPage extends React.Component {
|
||||
|
||||
isRelationComponentNull = () => size(get(this.getSchema(), 'relations')) === 0;
|
||||
|
||||
// NOTE: technical debt that needs to be redone
|
||||
generateFormFromRecord = () => (
|
||||
Object.keys(this.getModelAttributes()).reduce((acc, current) => {
|
||||
acc[current] = get(this.props.editPage.record, current, '');
|
||||
|
||||
return acc;
|
||||
}, {})
|
||||
)
|
||||
|
||||
pluginHeaderActions = [
|
||||
{
|
||||
label: 'content-manager.containers.Edit.reset',
|
||||
kind: 'secondary',
|
||||
onClick: () => {},
|
||||
onClick: this.props.onCancel,
|
||||
type: 'button',
|
||||
},
|
||||
{
|
||||
@ -146,7 +169,7 @@ export class EditPage extends React.Component {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={(e) => { e.preventDefault(); }}>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<BackHeader onClick={() => this.props.history.goBack()} />
|
||||
<div className={cn('container-fluid', styles.containerFluid)}>
|
||||
<PluginHeader
|
||||
@ -159,6 +182,8 @@ export class EditPage extends React.Component {
|
||||
<Edit
|
||||
attributes={this.getModelAttributes()}
|
||||
didCheckErrors={editPage.didCheckErrors}
|
||||
formValidations={editPage.formValidations}
|
||||
formErrors={editPage.formErrors}
|
||||
layout={this.layout}
|
||||
modelName={this.getModelName()}
|
||||
onChange={this.handleChange}
|
||||
@ -197,8 +222,10 @@ EditPage.propTypes = {
|
||||
location: PropTypes.object.isRequired,
|
||||
match: PropTypes.object.isRequired,
|
||||
models: PropTypes.object,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
resetProps: PropTypes.func.isRequired,
|
||||
schema: PropTypes.object.isRequired,
|
||||
setFormErrors: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
@ -207,7 +234,9 @@ function mapDispatchToProps(dispatch) {
|
||||
changeData,
|
||||
getData,
|
||||
initModelProps,
|
||||
onCancel,
|
||||
resetProps,
|
||||
setFormErrors,
|
||||
},
|
||||
dispatch,
|
||||
);
|
||||
|
@ -4,18 +4,23 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import { fromJS, Map } from 'immutable';
|
||||
import { fromJS, Map, List } from 'immutable';
|
||||
import {
|
||||
CHANGE_DATA,
|
||||
GET_DATA_SUCCEEDED,
|
||||
INIT_MODEL_PROPS,
|
||||
ON_CANCEL,
|
||||
RESET_PROPS,
|
||||
SET_FORM_ERRORS,
|
||||
} from './constants';
|
||||
|
||||
const initialState = fromJS({
|
||||
didCheckErrors: true,
|
||||
formErrors: List([]),
|
||||
formValidations: List([]),
|
||||
isCreating: false,
|
||||
id: '',
|
||||
initialRecord: Map({}),
|
||||
modelName: '',
|
||||
pluginHeaderTitle: 'New Entry',
|
||||
record: Map({}),
|
||||
@ -29,15 +34,26 @@ function editPageReducer(state = initialState, action) {
|
||||
case GET_DATA_SUCCEEDED:
|
||||
return state
|
||||
.update('id', () => action.id)
|
||||
.update('initialRecord', () => Map(action.data))
|
||||
.update('pluginHeaderTitle', () => action.pluginHeaderTitle)
|
||||
.update('record', () => Map(action.data));
|
||||
case INIT_MODEL_PROPS:
|
||||
return state
|
||||
.update('formValidations', () => List(action.formValidations))
|
||||
.update('isCreating', () => action.isCreating)
|
||||
.update('modelName', () => action.modelName)
|
||||
.update('source', () => action.source);
|
||||
case ON_CANCEL:
|
||||
return state
|
||||
.update('didCheckErrors', (v) => v = !v)
|
||||
.update('formErrors', () => List([]))
|
||||
.update('record', () => state.get('initialRecord'));
|
||||
case RESET_PROPS:
|
||||
return initialState;
|
||||
case SET_FORM_ERRORS:
|
||||
return state
|
||||
.update('didCheckErrors', (v) => v = !v)
|
||||
.update('formErrors', () => List(action.formErrors));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user