diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/Input/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/Input/index.js index 375b1ad799..cd51dfcad9 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/Input/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/Input/index.js @@ -5,7 +5,7 @@ */ import React from 'react'; -import { get, isEmpty, map, isObject } from 'lodash'; +import { get, isEmpty, map, mapKeys, isObject, reject, includes } from 'lodash'; import { FormattedMessage } from 'react-intl'; import styles from './styles.scss'; @@ -34,6 +34,65 @@ class Input extends React.Component { // eslint-disable-line react/prefer-statel } } + handleBlur = ({ target }) => { + // prevent error display if input is initially empty + if (!isEmpty(target.value) || this.state.hasInitialValue) { + // validates basic string validations + // add custom logic here such as alerts... + const errors = this.validate(target.value); + + this.setState({ errors, hasInitialValue: true }); + } + } + + validate = (value) => { + let errors = []; + // handle i18n + const requiredError = { id: 'error.validation.required' }; + mapKeys(this.props.validations, (validationValue, validationKey) => { + switch (validationKey) { + case 'max': + if (parseInt(value, 10) > validationValue) { + errors.push({ id: 'error.validation.max' }); + } + break; + case 'maxLength': + if (value.length > validationValue) { + errors.push({ id: 'error.validation.maxLength' }); + } + break; + case 'min': + if (parseInt(value, 10) < validationValue) { + errors.push({ id: 'error.validation.min' }); + } + break; + case 'minLength': + if (value.length < validationValue) { + errors.push({ id: 'error.validation.minLength' }); + } + break; + case 'required': + if (value.length === 0) { + errors.push({ id: 'error.validation.required' }); + } + break; + case 'regex': + if (!new RegExp(validationValue).test(value)) { + errors.push({ id: 'error.validation.regex' }); + } + break; + default: + errors = []; + } + }); + + if (includes(errors, requiredError)) { + errors = reject(errors, (error) => error !== requiredError); + } + return errors; + } + + handleChangeCheckbox = (e) => { const target = { type: e.target.type, @@ -239,7 +298,10 @@ Input.propTypes = { customBootstrapClass: React.PropTypes.string, deactivateErrorHighlight: React.PropTypes.bool, // errors: React.PropTypes.array, - handleBlur: React.PropTypes.func, + handleBlur: React.PropTypes.oneOfType([ + React.PropTypes.func, + React.PropTypes.bool, + ]), handleChange: React.PropTypes.func.isRequired, handleFocus: React.PropTypes.func, inputDescription: React.PropTypes.string, diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/PopUpForm/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/PopUpForm/index.js index cff28dbd9c..c00b196a9c 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/PopUpForm/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/PopUpForm/index.js @@ -19,8 +19,12 @@ class PopUpForm extends React.Component { // eslint-disable-line react/prefer-st 'col-md-8 offset-md-4 pull-md-4' : 'col-md-6 offset-md-6 pull-md-6'; const shouldOverrideRendering = this.props.overrideRenderInputCondition ? this.props.overrideRenderInputCondition(item) : false; + const shouldOverrideHandleBlur = this.props.overrideHandleBlurCondition ? this.props.overrideHandleBlurCondition(item) : false; + const value = !isEmpty(this.props.values) && includes(item.target, '.') ? get(this.props.values, [split(item.target, '.')[0], split(item.target, '.')[1]]) : this.props.values[item.target]; + const handleBlur = shouldOverrideHandleBlur ? this.props.handleBlur : false; + if (shouldOverrideRendering) { return this.props.overrideRenderInput(item, key); } @@ -30,7 +34,7 @@ class PopUpForm extends React.Component { // eslint-disable-line react/prefer-st key={key} type={item.type} handleChange={this.props.handleChange} - handleBlur={this.props.handleBlur} + handleBlur={handleBlur} name={item.name} target={item.target} validations={item.validations} @@ -116,6 +120,7 @@ PopUpForm.propTypes = { isOpen: React.PropTypes.bool, noButtons: React.PropTypes.bool, noNav: React.PropTypes.bool, + overrideHandleBlurCondition: React.PropTypes.func, overrideRenderInput: React.PropTypes.func, overrideRenderInputCondition: React.PropTypes.func, // popUpFormType: React.PropTypes.string.isRequired, diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js index de4e7cc1d0..33c4bd3f26 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js @@ -233,6 +233,16 @@ export class Form extends React.Component { // eslint-disable-line react/prefer- router.push(`${this.props.routePath}#create${this.props.modelName}::attribute${attributeType}::baseSettings`); } + checkForNestedInput = (item) => { + const hasNestedInput = item.items && item.type !== 'select'; + return hasNestedInput; + } + + checkInputContentType = (item) => { + const shouldOverrideHandleBlur = item.target === 'name' && includes(this.props.hash, 'contentType'); + return shouldOverrideHandleBlur; + } + handleBlur = ({ target }) => { if (target.name === 'name') { this.props.changeInput(target.name, camelCase(target.value), includes(this.props.hash, 'edit')); @@ -336,11 +346,6 @@ export class Form extends React.Component { // eslint-disable-line react/prefer- } } - checkForNestedInput = (item) => { - const hasNestedInput = item.items && item.type !== 'select'; - return hasNestedInput; - } - renderInput = (item, key) => ( ); diff --git a/packages/strapi-plugin-content-type-builder/admin/src/translations/en.json b/packages/strapi-plugin-content-type-builder/admin/src/translations/en.json index edd496045c..a7767fa65c 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/translations/en.json +++ b/packages/strapi-plugin-content-type-builder/admin/src/translations/en.json @@ -13,6 +13,13 @@ "button.contentType.add": "Add Content Type", "button.attributes.add": "Add New Field", + "error.validation.required": "This value input is required.", + "error.validation.regex": "The value not match the regex.", + "error.validation.max": "The value is too high.", + "error.validation.min": "The value is too low.", + "error.validation.maxLength": "The value is too long.", + "error.validation.minLength": "The value is too shot.", + "form.attribute.item.textarea.name": "Name", "form.attribute.item.date.name": "Name", "form.attribute.item.media.name": "Name", diff --git a/packages/strapi-plugin-content-type-builder/admin/src/translations/fr.json b/packages/strapi-plugin-content-type-builder/admin/src/translations/fr.json index bd67af2134..cadaec27e0 100755 --- a/packages/strapi-plugin-content-type-builder/admin/src/translations/fr.json +++ b/packages/strapi-plugin-content-type-builder/admin/src/translations/fr.json @@ -12,6 +12,13 @@ "button.contentType.add": "Ajouter un modèle", "button.attributes.add": "Ajouter un champs", + "error.validation.required": "Ce champ est obligatoire.", + "error.validation.regex": "La valeur ne correspond pas au format attendu.", + "error.validation.max": "La valeur est trop grande.", + "error.validation.min": "La valeur est trop basse.", + "error.validation.maxLength": "La valeur est trop longue.", + "error.validation.minLength": "La valeur est trop courte.", + "form.attribute.item.textarea.name": "Nom", "form.attribute.item.date.name": "Nom", "form.attribute.item.boolean.name": "Nom",