2018-02-21 15:33:58 +01:00
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* Edit
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import React from 'react';
|
2018-02-21 17:14:35 +01:00
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
|
import {
|
2018-02-21 18:45:18 +01:00
|
|
|
findIndex,
|
2018-02-21 17:14:35 +01:00
|
|
|
get,
|
2018-02-26 16:04:59 +01:00
|
|
|
has,
|
2018-02-21 17:14:35 +01:00
|
|
|
isEmpty,
|
|
|
|
|
isFunction,
|
|
|
|
|
merge,
|
|
|
|
|
omit,
|
2018-02-26 14:53:13 +01:00
|
|
|
upperFirst,
|
2018-02-21 17:14:35 +01:00
|
|
|
} from 'lodash';
|
|
|
|
|
|
|
|
|
|
// You can find these components in either
|
|
|
|
|
// ./node_modules/strapi-helper-plugin/lib/src
|
|
|
|
|
// or strapi/packages/strapi-helper-plugin/lib/src
|
|
|
|
|
import Input from 'components/InputsIndex';
|
|
|
|
|
|
2018-02-21 15:33:58 +01:00
|
|
|
import styles from './styles.scss';
|
|
|
|
|
|
2018-02-21 17:14:35 +01:00
|
|
|
const getInputType = (type = '') => {
|
|
|
|
|
switch (type.toLowerCase()) {
|
|
|
|
|
case 'boolean':
|
|
|
|
|
return 'checkbox';
|
|
|
|
|
case 'bigint':
|
|
|
|
|
case 'decimal':
|
|
|
|
|
case 'float':
|
|
|
|
|
case 'integer':
|
|
|
|
|
return 'number';
|
|
|
|
|
case 'date':
|
|
|
|
|
case 'datetime':
|
|
|
|
|
return 'date';
|
|
|
|
|
case 'email':
|
|
|
|
|
return 'email';
|
|
|
|
|
case 'enumeration':
|
|
|
|
|
return 'select';
|
|
|
|
|
case 'password':
|
|
|
|
|
return 'password';
|
|
|
|
|
case 'string':
|
|
|
|
|
return 'text';
|
|
|
|
|
case 'text':
|
|
|
|
|
return 'textarea';
|
2018-02-26 14:53:13 +01:00
|
|
|
case 'file':
|
|
|
|
|
case 'files':
|
|
|
|
|
return 'file';
|
2018-02-21 17:14:35 +01:00
|
|
|
default:
|
|
|
|
|
return 'text';
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class Edit extends React.PureComponent {
|
|
|
|
|
state = { currentLayout: {}, displayedFields: {} };
|
|
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
|
this.setLayout(this.props);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
|
|
if (isEmpty(this.props.layout) && !isEmpty(nextProps.layout)) {
|
|
|
|
|
this.setLayout(nextProps);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setLayout = (props) => {
|
|
|
|
|
const currentLayout = get(props.layout, [props.modelName, 'attributes']);
|
2018-02-26 14:53:13 +01:00
|
|
|
const displayedFields = merge(this.getUploadRelations(props), get(currentLayout), omit(props.schema.fields, 'id'));
|
2018-02-26 18:33:19 +01:00
|
|
|
|
2018-02-21 17:14:35 +01:00
|
|
|
this.setState({ currentLayout, displayedFields });
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-21 18:45:18 +01:00
|
|
|
getInputErrors = (attr) => {
|
|
|
|
|
const index = findIndex(this.props.formErrors, ['name', attr]);
|
|
|
|
|
return index !== -1 ? this.props.formErrors[index].errors : [];
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-21 17:14:35 +01:00
|
|
|
/**
|
|
|
|
|
* Retrieve the Input layout
|
|
|
|
|
* @param {String} attr [description]
|
|
|
|
|
* @return {Object} Object containing the Input's label customBootstrapClass, ...
|
|
|
|
|
*/
|
|
|
|
|
getInputLayout = (attr) => (
|
|
|
|
|
Object.keys(get(this.state.currentLayout, attr, {})).reduce((acc, current) => {
|
|
|
|
|
acc[current] = isFunction(this.state.currentLayout[attr][current]) ?
|
|
|
|
|
this.state.currentLayout[attr][current](this) :
|
|
|
|
|
this.state.currentLayout[attr][current];
|
|
|
|
|
return acc;
|
|
|
|
|
}, {})
|
|
|
|
|
)
|
|
|
|
|
|
2018-02-21 18:45:18 +01:00
|
|
|
/**
|
|
|
|
|
* 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'], {});
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-26 14:53:13 +01:00
|
|
|
/**
|
|
|
|
|
* Retrieve all relations made with the upload plugin
|
|
|
|
|
* @param {Object} props
|
|
|
|
|
* @return {Object}
|
|
|
|
|
*/
|
|
|
|
|
getUploadRelations = (props) => (
|
|
|
|
|
Object.keys(get(props.schema, 'relations', {})).reduce((acc, current) => {
|
|
|
|
|
if (get(props.schema, ['relations', current, 'plugin']) === 'upload') {
|
|
|
|
|
acc[current] = {
|
|
|
|
|
description: '',
|
|
|
|
|
label: upperFirst(current),
|
|
|
|
|
type: 'file',
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return acc;
|
|
|
|
|
}, {})
|
|
|
|
|
)
|
|
|
|
|
|
2018-02-26 16:04:59 +01:00
|
|
|
fileRelationAllowMultipleUpload = (relationName) => has(this.props.schema, ['relations', relationName, 'collection']);
|
|
|
|
|
|
2018-03-05 17:26:55 +01:00
|
|
|
// orderAttributes = (displayedFields) => Object.keys(displayedFields).sort(name => Object.keys(this.getUploadRelations(this.props)).includes(name));
|
|
|
|
|
orderAttributes = (displayedFields) => Object.keys(displayedFields);
|
2018-02-26 18:33:19 +01:00
|
|
|
|
2018-02-21 17:14:35 +01:00
|
|
|
render(){
|
|
|
|
|
return (
|
|
|
|
|
<div className={styles.form}>
|
|
|
|
|
<div className="row">
|
2018-02-26 18:33:19 +01:00
|
|
|
{this.orderAttributes(this.state.displayedFields).map((attr, key) => {
|
2018-02-21 17:14:35 +01:00
|
|
|
const details = this.state.displayedFields[attr];
|
|
|
|
|
// Retrieve the input's bootstrapClass from the layout
|
|
|
|
|
const layout = this.getInputLayout(attr);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Input
|
|
|
|
|
autoFocus={key === 0}
|
|
|
|
|
customBootstrapClass={get(layout, 'className')}
|
|
|
|
|
didCheckErrors={this.props.didCheckErrors}
|
2018-02-21 18:45:18 +01:00
|
|
|
errors={this.getInputErrors(attr)}
|
2018-02-21 17:14:35 +01:00
|
|
|
key={attr}
|
|
|
|
|
label={get(layout, 'label') || details.label || ''}
|
2018-02-26 16:04:59 +01:00
|
|
|
multiple={this.fileRelationAllowMultipleUpload(attr)}
|
2018-02-21 17:14:35 +01:00
|
|
|
name={attr}
|
|
|
|
|
onChange={this.props.onChange}
|
|
|
|
|
selectOptions={get(this.props.attributes, [attr, 'enum'])}
|
|
|
|
|
placeholder={get(layout, 'placeholder') || details.placeholder}
|
|
|
|
|
type={get(layout, 'type', getInputType(details.type))}
|
2018-02-21 18:45:18 +01:00
|
|
|
validations={this.getInputValidations(attr)}
|
2018-02-21 17:14:35 +01:00
|
|
|
value={this.props.record[attr]}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
2018-02-21 15:33:58 +01:00
|
|
|
</div>
|
2018-02-21 17:14:35 +01:00
|
|
|
);
|
|
|
|
|
}
|
2018-02-21 15:33:58 +01:00
|
|
|
}
|
|
|
|
|
|
2018-02-21 17:14:35 +01:00
|
|
|
Edit.defaultProps = {
|
|
|
|
|
attributes: {},
|
2018-02-21 18:45:18 +01:00
|
|
|
formErrors: [],
|
|
|
|
|
formValidations: [],
|
2018-02-21 17:14:35 +01:00
|
|
|
layout: {},
|
|
|
|
|
onChange: () => {},
|
|
|
|
|
record: {},
|
2018-02-26 16:04:59 +01:00
|
|
|
schema: {},
|
2018-02-21 17:14:35 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Edit.propTypes = {
|
|
|
|
|
attributes: PropTypes.object,
|
|
|
|
|
didCheckErrors: PropTypes.bool.isRequired,
|
2018-02-21 18:45:18 +01:00
|
|
|
formErrors: PropTypes.array,
|
|
|
|
|
formValidations: PropTypes.array,
|
2018-02-21 17:14:35 +01:00
|
|
|
layout: PropTypes.object,
|
|
|
|
|
onChange: PropTypes.func,
|
|
|
|
|
record: PropTypes.object,
|
2018-02-26 16:04:59 +01:00
|
|
|
schema: PropTypes.object,
|
2018-02-21 17:14:35 +01:00
|
|
|
};
|
|
|
|
|
|
2018-02-21 15:33:58 +01:00
|
|
|
export default Edit;
|