diff --git a/packages/strapi-helper-plugin/lib/src/components/InputFile/index.js b/packages/strapi-helper-plugin/lib/src/components/InputFile/index.js index a65ba6f048..700524be89 100644 --- a/packages/strapi-helper-plugin/lib/src/components/InputFile/index.js +++ b/packages/strapi-helper-plugin/lib/src/components/InputFile/index.js @@ -8,7 +8,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; -import { cloneDeep } from 'lodash'; +import { cloneDeep, isArray, isObject } from 'lodash'; +import cn from 'classnames'; import ImgPreview from 'components/ImgPreview'; import InputFileDetails from 'components/InputFileDetails'; @@ -71,11 +72,12 @@ class InputFile extends React.Component { if (this.props.multiple) { value.splice(this.state.position, 1); } + // Update the parent's props const target = { name: this.props.name, type: 'file', - value, + value: Object.keys(value).length === 0 ? '' : value, }; this.props.onChange({ target }); @@ -94,6 +96,19 @@ class InputFile extends React.Component { this.setState({ position: newPosition }); } + isVisibleDetails = () => { + const {value} = this.props; + + if (!value || + (isArray(value) && value.length === 0) || + (isObject(value) && Object.keys(value).length === 0) + ) { + return false; + } + + return true; + } + render() { const { multiple, @@ -104,39 +119,43 @@ class InputFile extends React.Component { return (
- - +
+ {this.isVisibleDetails() && ( + + )} ); } @@ -146,9 +165,12 @@ InputFile.defaultProps = { multiple: false, setLabel: () => {}, value: [], + error: false, + }; InputFile.propTypes = { + error: PropTypes.bool, multiple: PropTypes.bool, name: PropTypes.string.isRequired, onChange: PropTypes.func.isRequired, diff --git a/packages/strapi-helper-plugin/lib/src/components/InputFile/styles.scss b/packages/strapi-helper-plugin/lib/src/components/InputFile/styles.scss index c6c81e3692..26799e7784 100644 --- a/packages/strapi-helper-plugin/lib/src/components/InputFile/styles.scss +++ b/packages/strapi-helper-plugin/lib/src/components/InputFile/styles.scss @@ -32,3 +32,7 @@ .copy { cursor: copy !important; } + +.inputFileControlForm { + padding: 0; +} \ No newline at end of file diff --git a/packages/strapi-helper-plugin/lib/src/components/InputFileWithErrors/index.js b/packages/strapi-helper-plugin/lib/src/components/InputFileWithErrors/index.js index 6ca7ac1ff8..f9a8afed46 100644 --- a/packages/strapi-helper-plugin/lib/src/components/InputFileWithErrors/index.js +++ b/packages/strapi-helper-plugin/lib/src/components/InputFileWithErrors/index.js @@ -14,22 +14,39 @@ import Label from 'components/Label'; import InputDescription from 'components/InputDescription'; import InputFile from 'components/InputFile'; import InputSpacer from 'components/InputSpacer'; +import InputErrors from 'components/InputErrors'; +// Styles import styles from './styles.scss'; class InputFileWithErrors extends React.Component { - state = { label: false, hasValue: false }; + state = { errors: [], label: false, hasValue: false }; componentDidMount() { + const { errors } = this.props; + let newState = Object.assign({}, this.state); + if (this.props.multiple && !isEmpty(this.props.value)) { - this.setState({ label: 1, hasValue: true }); + newState = Object.assign({}, newState, { label: 1, hasValue: true }); } + + if (!isEmpty(errors)) { + newState = Object.assign({}, newState, { errors }); + } + + this.setState(newState); } componentWillReceiveProps(nextProps) { if (!this.state.hasValue && !isEmpty(nextProps.value) && nextProps.multiple && differenceBy(nextProps.value, this.props.value, 'name').length > 0) { this.setState({ label: 1, hasValue: true }); } + // Check if errors have been updated during validations + if (nextProps.didCheckErrors !== this.props.didCheckErrors) { + // Remove from the state the errors that have already been set + const errors = isEmpty(nextProps.errors) ? [] : nextProps.errors; + this.setState({ errors }); + } } setLabel = (label) => { @@ -40,6 +57,9 @@ class InputFileWithErrors extends React.Component { const { className, customBootstrapClass, + errorsClassName, + errorsStyle, + noErrorsDescription, inputDescription, inputDescriptionClassName, inputDescriptionStyle, @@ -76,6 +96,7 @@ class InputFileWithErrors extends React.Component { )} + {spacer} ); @@ -93,8 +119,12 @@ class InputFileWithErrors extends React.Component { } InputFileWithErrors.defaultProps = { + errors: [], + errorsClassName: '', + errorsStyle: {}, className: '', customBootstrapClass: 'col-md-6', + didCheckErrors: false, inputDescription: '', inputDescriptionClassName: '', inputDescriptionStyle: {}, @@ -102,6 +132,7 @@ InputFileWithErrors.defaultProps = { labelClassName: '', labelStyle: {}, multiple: false, + noErrorsDescription: false, style: {}, value: [], }; @@ -109,6 +140,10 @@ InputFileWithErrors.defaultProps = { InputFileWithErrors.propTypes = { className: PropTypes.string, customBootstrapClass: PropTypes.string, + didCheckErrors: PropTypes.bool, + errors: PropTypes.array, + errorsClassName: PropTypes.string, + errorsStyle: PropTypes.object, inputDescription: PropTypes.oneOfType([ PropTypes.string, PropTypes.func, @@ -131,6 +166,7 @@ InputFileWithErrors.propTypes = { labelStyle: PropTypes.object, multiple: PropTypes.bool, name: PropTypes.string.isRequired, + noErrorsDescription: PropTypes.bool, onChange: PropTypes.func.isRequired, style: PropTypes.object, value: PropTypes.oneOfType([ diff --git a/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js b/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js index 2170bfec9b..6910be9dc8 100755 --- a/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js +++ b/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js @@ -178,7 +178,8 @@ module.exports = { if (params.plugin === 'upload' && relation.model || relation.collection === 'file') { params = { type: 'media', - multiple: params.collection ? true : false + multiple: params.collection ? true : false, + required: params.required }; } else { params = _.omit(params, ['collection', 'model', 'via']); @@ -288,7 +289,8 @@ module.exports = { attrs[attribute.name] = { [attribute.params.multiple ? 'collection' : 'model']: 'file', via, - plugin: 'upload' + plugin: 'upload', + required: attribute.params.required === true ? true : false }; } } else if (_.has(attribute, 'params.target')) {