diff --git a/packages/strapi-plugin-content-manager/admin/src/components/InputUID/Options/index.js b/packages/strapi-plugin-content-manager/admin/src/components/InputUID/Options/index.js index 338004641e..ef1ac73955 100644 --- a/packages/strapi-plugin-content-manager/admin/src/components/InputUID/Options/index.js +++ b/packages/strapi-plugin-content-manager/admin/src/components/InputUID/Options/index.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; -import getTrad from '../../../utils/getTrad' +import getTrad from '../../../utils/getTrad'; import OptionsWrapper from './wrapper'; import Option from './Option'; import OptionsTitle from './OptionsTitle'; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js index aa8054e5f7..fc07065583 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/utils/forms.js @@ -215,6 +215,15 @@ const forms = { .array() .of(yup.string()) .min(1, errorsTrads.min) + .test({ + name: 'areEnumValuesUnique', + message: getTrad('error.validation.enum-duplicate'), + test: values => { + const filtered = [...new Set(values)]; + + return filtered.length === values.length; + }, + }) .matchesEnumRegex(errorsTrads.regex) .hasNotEmptyValues('Empty strings are not allowed', dataToValidate.enum), enumName: yup.string().nullable(), 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 0da3f498a7..342d50514b 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/translations/en.json +++ b/packages/strapi-plugin-content-type-builder/admin/src/translations/en.json @@ -48,6 +48,7 @@ "contentType.kind.change.warning": "You just changed the kind of a content type: API will be reset (routes, controllers, and services will be overwritten).", "contentType.UID.description": "The UID is used to generate the API routes and databases tables/collections", "error.contentTypeName.reserved-name": "This name cannot be used in your project as it might break other functionalities", + "error.validation.enum-duplicate": "Duplicate values are not allowed", "error.validation.minSupMax": "Can't be superior", "error.validation.relation.targetAttribute-taken": "This name exists in the target", "form.attribute.component.option.add": "Add a component", diff --git a/packages/strapi-plugin-content-type-builder/controllers/validation/common.js b/packages/strapi-plugin-content-type-builder/controllers/validation/common.js index 7c235370a5..797a013603 100644 --- a/packages/strapi-plugin-content-type-builder/controllers/validation/common.js +++ b/packages/strapi-plugin-content-type-builder/controllers/validation/common.js @@ -64,9 +64,19 @@ const isValidEnum = { test: val => val === '' || ENUM_REGEX.test(val), }; +const areEnumValuesUnique = { + name: 'areEnumValuesUnique', + message: '${path} cannot contain duplicate values', + test: values => { + const filtered = [...new Set(values)]; + + return filtered.length === values.length; + }, +}; + module.exports = { validators, - + areEnumValuesUnique, isValidCollectionName, isValidCategoryName, isValidName, diff --git a/packages/strapi-plugin-content-type-builder/controllers/validation/types.js b/packages/strapi-plugin-content-type-builder/controllers/validation/types.js index 6269d32f00..b895796305 100644 --- a/packages/strapi-plugin-content-type-builder/controllers/validation/types.js +++ b/packages/strapi-plugin-content-type-builder/controllers/validation/types.js @@ -5,6 +5,7 @@ const yup = require('yup'); const { validators, + areEnumValuesUnique, isValidName, isValidEnum, isValidUID, @@ -17,11 +18,7 @@ const maxLengthIsGreaterThanOrEqualToMinLength = { message: 'maxLength must be greater or equal to minLength', test: function(value) { const { minLength } = this.parent; - if ( - !_.isUndefined(minLength) && - !_.isUndefined(value) && - value < minLength - ) { + if (!_.isUndefined(minLength) && !_.isUndefined(value) && value < minLength) { return false; } @@ -82,9 +79,7 @@ const getTypeShape = (attribute, { modelType, attributes } = {}) => { ) .test(isValidUID), minLength: validators.minLength, - maxLength: validators.maxLength - .max(256) - .test(maxLengthIsGreaterThanOrEqualToMinLength), + maxLength: validators.maxLength.max(256).test(maxLengthIsGreaterThanOrEqualToMinLength), }; } @@ -126,10 +121,9 @@ const getTypeShape = (attribute, { modelType, attributes } = {}) => { .required() ) .min(1) + .test(areEnumValuesUnique) .required(), - default: yup - .string() - .when('enum', enumVal => yup.string().oneOf(enumVal)), + default: yup.string().when('enum', enumVal => yup.string().oneOf(enumVal)), enumName: yup.string().test(isValidName), required: validators.required, unique: validators.unique, @@ -225,10 +219,7 @@ const getTypeShape = (attribute, { modelType, attributes } = {}) => { const targetCompo = strapi.components[compoUID]; if (!targetCompo) return true; // ignore this error as it will fail beforehand - if ( - modelType === modelTypes.COMPONENT && - hasComponent(targetCompo) - ) { + if (modelType === modelTypes.COMPONENT && hasComponent(targetCompo)) { return this.createError({ path: this.path, message: `${targetCompo.modelName} already as a nested compoent. You cannot have more than one level of nesting inside your components.`, @@ -249,9 +240,7 @@ const getTypeShape = (attribute, { modelType, attributes } = {}) => { components: yup .array() .of(yup.string().required()) - .test('isArray', '${path} must be an array', value => - Array.isArray(value) - ), + .test('isArray', '${path} must be an array', value => Array.isArray(value)), min: yup.number(), max: yup.number(), };