mirror of
https://github.com/strapi/strapi.git
synced 2025-09-25 16:29:34 +00:00
Split attributes yup validations
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
29e74e9f9f
commit
5366e8f930
@ -631,6 +631,8 @@ const FormModal = () => {
|
||||
toggleConfirmModal();
|
||||
}, [toggleConfirmModal]);
|
||||
|
||||
console.log({ modifiedData });
|
||||
|
||||
const handleSubmit = async (e, shouldContinue = isCreating) => {
|
||||
e.preventDefault();
|
||||
|
||||
|
@ -234,6 +234,35 @@ const baseForm = {
|
||||
],
|
||||
};
|
||||
},
|
||||
string: () => {
|
||||
return {
|
||||
items: [
|
||||
[nameField],
|
||||
[
|
||||
{
|
||||
label: { id: getTrad('modalForm.attribute.text.type-selection') },
|
||||
name: 'type',
|
||||
size: 12,
|
||||
type: 'booleanBox',
|
||||
options: [
|
||||
{
|
||||
headerId: getTrad('form.attribute.text.option.short-text'),
|
||||
descriptionId: getTrad('form.attribute.text.option.short-text.description'),
|
||||
value: 'string',
|
||||
},
|
||||
{
|
||||
headerId: getTrad('form.attribute.text.option.long-text'),
|
||||
descriptionId: getTrad('form.attribute.text.option.long-text.description'),
|
||||
value: 'text',
|
||||
},
|
||||
],
|
||||
validations: {},
|
||||
},
|
||||
],
|
||||
[uiHelpers.spacerMedium],
|
||||
],
|
||||
};
|
||||
},
|
||||
text: () => {
|
||||
return {
|
||||
items: [
|
||||
|
@ -1,3 +1,4 @@
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export { default as attributesForm } from './form';
|
||||
export { default as commonBaseForm } from './commonBaseForm';
|
||||
export { default as attributeTypes } from './types';
|
||||
|
@ -0,0 +1,321 @@
|
||||
import * as yup from 'yup';
|
||||
// import { get } from 'lodash';
|
||||
// import { isEmpty } from 'lodash';
|
||||
import { translatedErrors as errorsTrads } from 'strapi-helper-plugin';
|
||||
import getTrad from '../../../../utils/getTrad';
|
||||
import {
|
||||
alreadyUsedAttributeNames,
|
||||
createTextShape,
|
||||
getUsedContentTypeAttributeNames,
|
||||
isMinSuperiorThanMax,
|
||||
isNameAllowed,
|
||||
validators,
|
||||
NAME_REGEX,
|
||||
} from './validation/common';
|
||||
|
||||
const types = {
|
||||
date: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
datetime: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
time: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
default: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
biginteger: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
default: yup
|
||||
.string()
|
||||
.nullable()
|
||||
.matches(/^\d*$/),
|
||||
unique: validators.unique(),
|
||||
required: validators.required(),
|
||||
|
||||
max: yup
|
||||
.string()
|
||||
.nullable()
|
||||
.matches(/^\d*$/, errorsTrads.regex),
|
||||
min: yup
|
||||
.string()
|
||||
.nullable()
|
||||
.test(isMinSuperiorThanMax)
|
||||
.matches(/^\d*$/, errorsTrads.regex),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
boolean: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
default: yup.boolean().nullable(),
|
||||
required: validators.required(),
|
||||
unique: validators.unique(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
component: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
required: validators.required(),
|
||||
max: validators.max(),
|
||||
min: validators.min(),
|
||||
component: yup.string().required(errorsTrads.required),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
decimal: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
default: yup.number(),
|
||||
required: validators.required(),
|
||||
max: yup.number(),
|
||||
min: yup.number().test(isMinSuperiorThanMax),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
dynamiczone: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
required: validators.required(),
|
||||
max: validators.max(),
|
||||
min: validators.min(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
email: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
default: yup
|
||||
.string()
|
||||
.email()
|
||||
.nullable(),
|
||||
unique: validators.unique(),
|
||||
required: validators.required(),
|
||||
maxLength: validators.maxLength(),
|
||||
minLength: validators.minLength(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
enumeration: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const usedNames = getUsedContentTypeAttributeNames(
|
||||
contentTypeSchema,
|
||||
isEdition,
|
||||
initialData.name
|
||||
);
|
||||
|
||||
const ENUM_REGEX = new RegExp('^[_A-Za-z][_0-9A-Za-z]*$');
|
||||
|
||||
const shape = {
|
||||
name: yup
|
||||
.string()
|
||||
.test(alreadyUsedAttributeNames(usedNames))
|
||||
.test(isNameAllowed(reservedNames))
|
||||
.matches(ENUM_REGEX, errorsTrads.regex)
|
||||
.required(errorsTrads.required),
|
||||
type: validators.type(),
|
||||
default: validators.default(),
|
||||
unique: validators.unique(),
|
||||
required: validators.required(),
|
||||
enum: yup
|
||||
.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;
|
||||
},
|
||||
})
|
||||
.test({
|
||||
name: 'valuesMatchesRegex',
|
||||
message: errorsTrads.regex,
|
||||
test: values => {
|
||||
return values.every(val => val === '' || ENUM_REGEX.test(val));
|
||||
},
|
||||
})
|
||||
.test({
|
||||
name: 'doesNotHaveEmptyValues',
|
||||
message: getTrad('error.validation.enum-empty-string'),
|
||||
test: values => !values.some(val => val === ''),
|
||||
}),
|
||||
enumName: yup.string().nullable(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
float: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
required: validators.required(),
|
||||
default: yup.number(),
|
||||
max: yup.number(),
|
||||
min: yup.number().test(isMinSuperiorThanMax),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
integer: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
default: yup.number().integer(),
|
||||
unique: validators.unique(),
|
||||
required: validators.required(),
|
||||
max: validators.max(),
|
||||
min: validators.min(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
json: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
required: validators.required(),
|
||||
unique: validators.unique(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
media: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
multiple: yup.boolean(),
|
||||
required: validators.required(),
|
||||
allowedTypes: yup
|
||||
.array()
|
||||
.of(yup.string().oneOf(['images', 'videos', 'files']))
|
||||
.min(1)
|
||||
.nullable(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
password: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
default: validators.default(),
|
||||
unique: validators.unique(),
|
||||
required: validators.required(),
|
||||
maxLength: validators.maxLength(),
|
||||
minLength: validators.minLength(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
relation: (
|
||||
contentTypeSchema,
|
||||
initialData,
|
||||
isEdition,
|
||||
reservedNames,
|
||||
data,
|
||||
alreadyTakenTargetAttributes
|
||||
) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
target: yup.string().required(errorsTrads.required),
|
||||
nature: yup.string().required(),
|
||||
dominant: yup.boolean().nullable(),
|
||||
unique: yup.boolean().nullable(),
|
||||
targetAttribute: yup.lazy(() => {
|
||||
let schema = yup.string().test(isNameAllowed(reservedNames));
|
||||
const initialForbiddenName = [...alreadyTakenTargetAttributes, data.name];
|
||||
|
||||
let forbiddenTargetAttributeName = isEdition
|
||||
? initialForbiddenName.filter(val => val !== initialData.targetAttribute)
|
||||
: initialForbiddenName;
|
||||
|
||||
if (!['oneWay', 'manyWay'].includes(data.nature)) {
|
||||
schema = schema.matches(NAME_REGEX, errorsTrads.regex);
|
||||
}
|
||||
|
||||
return schema
|
||||
.test({
|
||||
name: 'forbiddenTargetAttributeName',
|
||||
message: getTrad('error.validation.relation.targetAttribute-taken'),
|
||||
test: value => {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !forbiddenTargetAttributeName.includes(value);
|
||||
},
|
||||
})
|
||||
.required(errorsTrads.required);
|
||||
}),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
richtext: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
default: validators.default(),
|
||||
unique: validators.unique(),
|
||||
required: validators.required(),
|
||||
maxLength: validators.maxLength(),
|
||||
minLength: validators.minLength(),
|
||||
};
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
string: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = createTextShape(contentTypeSchema, initialData, isEdition, reservedNames);
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
text: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = createTextShape(contentTypeSchema, initialData, isEdition, reservedNames);
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
uid: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = createTextShape(contentTypeSchema, initialData, isEdition, reservedNames);
|
||||
|
||||
return yup.object(shape);
|
||||
},
|
||||
};
|
||||
|
||||
export default types;
|
@ -0,0 +1,159 @@
|
||||
import * as yup from 'yup';
|
||||
import { get, toNumber } from 'lodash';
|
||||
import { translatedErrors as errorsTrads } from 'strapi-helper-plugin';
|
||||
import getTrad from '../../../../../utils/getTrad';
|
||||
|
||||
const NAME_REGEX = new RegExp('^[A-Za-z][_0-9A-Za-z]*$');
|
||||
|
||||
const alreadyUsedAttributeNames = usedNames => {
|
||||
return {
|
||||
name: 'attributeNameAlreadyUsed',
|
||||
message: errorsTrads.unique,
|
||||
test: value => {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !usedNames.includes(value);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const getUsedContentTypeAttributeNames = (ctShema, isEdition, attributeNameToEdit) => {
|
||||
const attributes = get(ctShema, ['schema', 'attributes'], {});
|
||||
|
||||
return Object.keys(attributes).filter(attr => {
|
||||
if (isEdition) {
|
||||
return attr !== attributeNameToEdit;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
const isNameAllowed = reservedNames => {
|
||||
return {
|
||||
name: 'forbiddenAttributeName',
|
||||
message: getTrad('error.attributeName.reserved-name'),
|
||||
test: value => {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !reservedNames.includes(value);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const validators = {
|
||||
default: () => yup.string().nullable(),
|
||||
max: () =>
|
||||
yup
|
||||
.number()
|
||||
.integer()
|
||||
.positive()
|
||||
.nullable(),
|
||||
min: () =>
|
||||
yup
|
||||
.number()
|
||||
.integer()
|
||||
.positive()
|
||||
.when('max', (max, schema) => {
|
||||
if (max) {
|
||||
return schema.max(max, getTrad('error.validation.minSupMax'));
|
||||
}
|
||||
|
||||
return schema;
|
||||
})
|
||||
.nullable(),
|
||||
maxLength: () =>
|
||||
yup
|
||||
.number()
|
||||
.integer()
|
||||
.nullable(),
|
||||
minLength: () =>
|
||||
yup
|
||||
.number()
|
||||
.integer()
|
||||
.when('maxLength', (maxLength, schema) => {
|
||||
if (maxLength) {
|
||||
return schema.max(maxLength, getTrad('error.validation.minSupMax'));
|
||||
}
|
||||
|
||||
return schema;
|
||||
})
|
||||
.nullable(),
|
||||
name: (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const usedNames = getUsedContentTypeAttributeNames(
|
||||
contentTypeSchema,
|
||||
isEdition,
|
||||
initialData.name
|
||||
);
|
||||
|
||||
return yup
|
||||
.string()
|
||||
.test(alreadyUsedAttributeNames(usedNames))
|
||||
.test(isNameAllowed(reservedNames))
|
||||
.matches(NAME_REGEX, errorsTrads.regex)
|
||||
.required(errorsTrads.required);
|
||||
},
|
||||
required: () => yup.boolean(),
|
||||
type: () => yup.string().required(errorsTrads.required),
|
||||
unique: () => yup.boolean().nullable(),
|
||||
};
|
||||
|
||||
const createTextShape = (contentTypeSchema, initialData, isEdition, reservedNames) => {
|
||||
const shape = {
|
||||
name: validators.name(contentTypeSchema, initialData, isEdition, reservedNames),
|
||||
type: validators.type(),
|
||||
default: validators.default(),
|
||||
unique: validators.unique(),
|
||||
required: validators.required(),
|
||||
maxLength: validators.maxLength(),
|
||||
minLength: validators.minLength(),
|
||||
regex: yup
|
||||
.string()
|
||||
.test({
|
||||
name: 'isValidRegExpPattern',
|
||||
message: getTrad('error.validation.regex'),
|
||||
test: value => {
|
||||
return new RegExp(value) !== null;
|
||||
},
|
||||
})
|
||||
.nullable(),
|
||||
};
|
||||
|
||||
return shape;
|
||||
};
|
||||
|
||||
const isMinSuperiorThanMax = {
|
||||
name: 'isMinSuperiorThanMax',
|
||||
message: getTrad('error.validation.minSupMax'),
|
||||
test(value) {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { max } = this.parent;
|
||||
|
||||
if (!max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Number.isNaN(toNumber(value))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return toNumber(max) >= toNumber(value);
|
||||
},
|
||||
};
|
||||
|
||||
export {
|
||||
alreadyUsedAttributeNames,
|
||||
createTextShape,
|
||||
getUsedContentTypeAttributeNames,
|
||||
isMinSuperiorThanMax,
|
||||
isNameAllowed,
|
||||
validators,
|
||||
NAME_REGEX,
|
||||
};
|
@ -1,85 +1,11 @@
|
||||
import * as yup from 'yup';
|
||||
import { get, isEmpty, toLower, trim, toNumber } from 'lodash';
|
||||
import { translatedErrors as errorsTrads } from 'strapi-helper-plugin';
|
||||
import getTrad from '../../../../utils/getTrad';
|
||||
import { get, toLower } from 'lodash';
|
||||
import { nameToSlug } from '../createUid';
|
||||
|
||||
import { attributesForm, commonBaseForm } from '../attributes';
|
||||
import { attributesForm, attributeTypes, commonBaseForm } from '../attributes';
|
||||
import { categoryForm, createCategorySchema } from '../category';
|
||||
import { contentTypeForm, createContentTypeSchema } from '../contentType';
|
||||
import { createComponentSchema, componentForm } from '../component';
|
||||
import { dynamiczoneForm } from '../dynamicZone';
|
||||
import { NAME_REGEX, ENUM_REGEX } from './regexes';
|
||||
|
||||
/* eslint-disable indent */
|
||||
/* eslint-disable prefer-arrow-callback */
|
||||
|
||||
yup.addMethod(yup.mixed, 'defined', function() {
|
||||
return this.test('defined', errorsTrads.required, value => value !== undefined);
|
||||
});
|
||||
|
||||
yup.addMethod(yup.string, 'unique', function(
|
||||
message,
|
||||
alreadyTakenAttributes,
|
||||
validator,
|
||||
category = ''
|
||||
) {
|
||||
return this.test('unique', message, function(string) {
|
||||
if (!string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !alreadyTakenAttributes.includes(
|
||||
typeof validator === 'function' ? validator(string, category) : string.toLowerCase()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
yup.addMethod(yup.array, 'hasNotEmptyValues', function(message) {
|
||||
return this.test('hasNotEmptyValues', message, function(array) {
|
||||
return !array.some(value => {
|
||||
return isEmpty(value);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
yup.addMethod(yup.string, 'isAllowed', function(message, reservedNames) {
|
||||
return this.test('isAllowed', message, function(string) {
|
||||
if (!string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !reservedNames.includes(toLower(trim(string)));
|
||||
});
|
||||
});
|
||||
|
||||
yup.addMethod(yup.string, 'isInferior', function(message, max) {
|
||||
return this.test('isInferior', message, function(min) {
|
||||
if (!min) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Number.isNaN(toNumber(min))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return toNumber(max) >= toNumber(min);
|
||||
});
|
||||
});
|
||||
|
||||
yup.addMethod(yup.array, 'matchesEnumRegex', function(message) {
|
||||
return this.test('matchesEnumRegex', message, function(array) {
|
||||
return array.every(value => {
|
||||
return ENUM_REGEX.test(value);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
yup.addMethod(yup.string, 'isValidRegExpPattern', function(message) {
|
||||
return this.test('isValidRegExpPattern', message, function(string) {
|
||||
return new RegExp(string) !== null;
|
||||
});
|
||||
});
|
||||
|
||||
const forms = {
|
||||
attribute: {
|
||||
@ -93,235 +19,25 @@ const forms = {
|
||||
alreadyTakenTargetContentTypeAttributes,
|
||||
reservedNames
|
||||
) {
|
||||
const alreadyTakenAttributes = Object.keys(
|
||||
get(currentSchema, ['schema', 'attributes'], {})
|
||||
).filter(attribute => {
|
||||
if (isEditing) {
|
||||
return attribute !== attributeToEditName;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// For relations
|
||||
let targetAttributeAlreadyTakenValue = dataToValidate.name
|
||||
? [...alreadyTakenAttributes, dataToValidate.name]
|
||||
: alreadyTakenAttributes;
|
||||
|
||||
if (
|
||||
isEditing &&
|
||||
attributeType === 'relation' &&
|
||||
dataToValidate.target === currentSchema.uid
|
||||
) {
|
||||
targetAttributeAlreadyTakenValue = targetAttributeAlreadyTakenValue.filter(
|
||||
attribute => attribute !== initialData.targetAttribute
|
||||
try {
|
||||
return attributeTypes[attributeType](
|
||||
currentSchema,
|
||||
initialData,
|
||||
isEditing,
|
||||
reservedNames.attributes,
|
||||
dataToValidate,
|
||||
alreadyTakenTargetContentTypeAttributes
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log(attributeType);
|
||||
|
||||
// Common yup shape for most attributes
|
||||
const commonShape = {
|
||||
name: yup
|
||||
.string()
|
||||
.unique(errorsTrads.unique, alreadyTakenAttributes)
|
||||
.matches(NAME_REGEX, errorsTrads.regex)
|
||||
.isAllowed(getTrad('error.attributeName.reserved-name'), reservedNames.attributes)
|
||||
.required(errorsTrads.required),
|
||||
type: yup.string().required(errorsTrads.required),
|
||||
default: yup.string().nullable(),
|
||||
unique: yup.boolean().nullable(),
|
||||
required: yup.boolean(),
|
||||
};
|
||||
const numberTypeShape = {
|
||||
max: yup.lazy(() => {
|
||||
let schema = yup.number();
|
||||
|
||||
if (
|
||||
attributeType === 'integer' ||
|
||||
attributeType === 'biginteger' ||
|
||||
attributeType === 'dynamiczone'
|
||||
) {
|
||||
schema = schema.integer();
|
||||
}
|
||||
|
||||
if (attributeType === 'dynamiczone') {
|
||||
schema = schema.positive();
|
||||
}
|
||||
|
||||
return schema.nullable();
|
||||
}),
|
||||
min: yup.lazy(() => {
|
||||
let schema = yup.number();
|
||||
|
||||
if (
|
||||
attributeType === 'integer' ||
|
||||
attributeType === 'biginteger' ||
|
||||
attributeType === 'dynamiczone'
|
||||
) {
|
||||
schema = schema.integer();
|
||||
}
|
||||
|
||||
if (attributeType === 'dynamiczone') {
|
||||
schema = schema.positive();
|
||||
}
|
||||
|
||||
return schema
|
||||
.nullable()
|
||||
.when('max', (max, schema) => {
|
||||
if (max) {
|
||||
return schema.max(max, getTrad('error.validation.minSupMax'));
|
||||
}
|
||||
|
||||
return schema;
|
||||
})
|
||||
.nullable();
|
||||
}),
|
||||
};
|
||||
const fieldsThatSupportMaxAndMinLengthShape = {
|
||||
maxLength: yup
|
||||
.number()
|
||||
.integer()
|
||||
.nullable(),
|
||||
minLength: yup
|
||||
.number()
|
||||
.integer()
|
||||
.when('maxLength', (maxLength, schema) => {
|
||||
if (maxLength) {
|
||||
return schema.max(maxLength, getTrad('error.validation.minSupMax'));
|
||||
}
|
||||
|
||||
return schema;
|
||||
})
|
||||
.nullable(),
|
||||
};
|
||||
|
||||
switch (attributeType) {
|
||||
case 'component':
|
||||
return yup.object().shape({
|
||||
...commonShape,
|
||||
component: yup.string().required(errorsTrads.required),
|
||||
...numberTypeShape,
|
||||
});
|
||||
case 'dynamiczone':
|
||||
return yup.object().shape({
|
||||
...commonShape,
|
||||
...numberTypeShape,
|
||||
});
|
||||
case 'enumeration':
|
||||
return yup.object().shape({
|
||||
name: yup
|
||||
.string()
|
||||
.isAllowed(getTrad('error.attributeName.reserved-name'), reservedNames.attributes)
|
||||
.unique(errorsTrads.unique, alreadyTakenAttributes)
|
||||
.matches(ENUM_REGEX, errorsTrads.regex)
|
||||
.required(errorsTrads.required),
|
||||
type: yup.string().required(errorsTrads.required),
|
||||
default: yup.string().nullable(),
|
||||
unique: yup.boolean().nullable(),
|
||||
required: yup.boolean(),
|
||||
enum: yup
|
||||
.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(),
|
||||
});
|
||||
case 'text':
|
||||
return yup.object().shape({
|
||||
...commonShape,
|
||||
...fieldsThatSupportMaxAndMinLengthShape,
|
||||
regex: yup
|
||||
.string()
|
||||
.isValidRegExpPattern(getTrad('error.validation.regex'))
|
||||
.nullable(),
|
||||
});
|
||||
case 'number':
|
||||
case 'integer':
|
||||
case 'biginteger':
|
||||
case 'float':
|
||||
case 'decimal': {
|
||||
if (dataToValidate.type === 'biginteger') {
|
||||
return yup.object().shape({
|
||||
...commonShape,
|
||||
default: yup
|
||||
.string()
|
||||
.nullable()
|
||||
.matches(/^\d*$/),
|
||||
min: yup
|
||||
.string()
|
||||
.nullable()
|
||||
.matches(/^\d*$/)
|
||||
.when('max', (max, schema) => {
|
||||
if (max) {
|
||||
return schema.isInferior(getTrad('error.validation.minSupMax'), max);
|
||||
}
|
||||
|
||||
return schema;
|
||||
}),
|
||||
|
||||
max: yup
|
||||
.string()
|
||||
.nullable()
|
||||
.matches(/^\d*$/),
|
||||
});
|
||||
}
|
||||
|
||||
let defaultType = yup.number();
|
||||
|
||||
if (dataToValidate.type === 'integer') {
|
||||
defaultType = yup.number().integer('component.Input.error.validation.integer');
|
||||
}
|
||||
|
||||
return yup.object().shape({
|
||||
...commonShape,
|
||||
default: defaultType.nullable(),
|
||||
...numberTypeShape,
|
||||
});
|
||||
}
|
||||
case 'relation':
|
||||
return yup.object().shape({
|
||||
name: yup
|
||||
.string()
|
||||
.isAllowed(getTrad('error.attributeName.reserved-name'), reservedNames.attributes)
|
||||
.matches(NAME_REGEX, errorsTrads.regex)
|
||||
.unique(errorsTrads.unique, alreadyTakenAttributes)
|
||||
.required(errorsTrads.required),
|
||||
targetAttribute: yup.lazy(() => {
|
||||
let schema = yup
|
||||
.string()
|
||||
.isAllowed(getTrad('error.attributeName.reserved-name'), reservedNames.attributes);
|
||||
|
||||
if (!['oneWay', 'manyWay'].includes(dataToValidate.nature)) {
|
||||
schema = schema.matches(NAME_REGEX, errorsTrads.regex);
|
||||
}
|
||||
|
||||
return schema
|
||||
.unique(errorsTrads.unique, targetAttributeAlreadyTakenValue)
|
||||
.unique(
|
||||
getTrad('error.validation.relation.targetAttribute-taken'),
|
||||
alreadyTakenTargetContentTypeAttributes
|
||||
)
|
||||
.required(errorsTrads.required);
|
||||
}),
|
||||
target: yup.string().required(errorsTrads.required),
|
||||
nature: yup.string().required(),
|
||||
dominant: yup.boolean().nullable(),
|
||||
unique: yup.boolean().nullable(),
|
||||
});
|
||||
default:
|
||||
return yup.object().shape({
|
||||
...commonShape,
|
||||
...fieldsThatSupportMaxAndMinLengthShape,
|
||||
});
|
||||
return attributeTypes.default(
|
||||
currentSchema,
|
||||
initialData,
|
||||
isEditing,
|
||||
reservedNames.attributes
|
||||
);
|
||||
}
|
||||
},
|
||||
form: {
|
||||
|
@ -54,6 +54,7 @@
|
||||
"error.validation.enum-duplicate": "Duplicate values are not allowed",
|
||||
"error.validation.minSupMax": "Can't be superior",
|
||||
"error.validation.regex": "Regex pattern is invalid",
|
||||
"error.validation.enum-empty-string": "Empty strings are not allowed",
|
||||
"error.validation.relation.targetAttribute-taken": "This name exists in the target",
|
||||
"form.attribute.component.option.add": "Add a component",
|
||||
"form.attribute.component.option.create": "Create a new component",
|
||||
|
Loading…
x
Reference in New Issue
Block a user