mirror of
https://github.com/strapi/strapi.git
synced 2025-11-11 15:49:50 +00:00
fix: content manager error management
This commit is contained in:
parent
6529e2bd50
commit
068381c9c9
@ -670,45 +670,16 @@ const useField = <TValue = any,>(path: string): FieldValue<TValue | undefined> =
|
|||||||
|
|
||||||
const handleChange = useForm('useField', (state) => state.onChange);
|
const handleChange = useForm('useField', (state) => state.onChange);
|
||||||
|
|
||||||
const formatNestedErrorMessages = (stateErrors: FormErrors<FormValues>) => {
|
const error = useForm('useField', (state) => {
|
||||||
const nestedErrors: Record<string, any> = {};
|
const error = getIn(state.errors, path);
|
||||||
|
|
||||||
Object.entries(stateErrors).forEach(([key, value]) => {
|
if (isErrorMessageDescriptor(error)) {
|
||||||
let current = nestedErrors;
|
const { values, ...message } = error;
|
||||||
|
return formatMessage(message, values);
|
||||||
const pathParts = key.split('.');
|
|
||||||
pathParts.forEach((part, index) => {
|
|
||||||
const isLastPart = index === pathParts.length - 1;
|
|
||||||
|
|
||||||
if (isLastPart) {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
// If the value is a translation message object or a string, it should be nested as is
|
|
||||||
current[part] = value;
|
|
||||||
} else if (isErrorMessageDescriptor(value)) {
|
|
||||||
// If the value is a plain object, it should be converted to a string message
|
|
||||||
current[part] = formatMessage(value);
|
|
||||||
} else {
|
|
||||||
// If the value is not an object, it may be an array or a message
|
|
||||||
setIn(current, part, value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Ensure nested structure exists
|
|
||||||
if (!current[part]) {
|
|
||||||
const isArray = !isNaN(Number(pathParts[index + 1]));
|
|
||||||
current[part] = isArray ? [] : {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
current = current[part];
|
return error;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return nestedErrors;
|
|
||||||
};
|
|
||||||
|
|
||||||
const error = useForm('useField', (state) =>
|
|
||||||
getIn(formatNestedErrorMessages(state.errors), path)
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
initialValue,
|
initialValue,
|
||||||
|
|||||||
@ -46,11 +46,6 @@ const Initializer = ({ disabled, name, onClick }: InitializerProps) => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
{field.error && (
|
|
||||||
<Typography textColor="danger600" variant="pi">
|
|
||||||
{field.error}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
import { Box, Checkbox, Field, Flex, NumberInput, TextInput } from '@strapi/design-system';
|
import { Box, Checkbox, Field, Flex, NumberInput, TextInput } from '@strapi/design-system';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
|
||||||
@ -23,7 +21,6 @@ export const CheckboxWithNumberField = ({
|
|||||||
value = null,
|
value = null,
|
||||||
}: CheckboxWithNumberFieldProps) => {
|
}: CheckboxWithNumberFieldProps) => {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const [showInput, setShowInput] = useState(!!value || value === 0);
|
|
||||||
const label = intlLabel.id
|
const label = intlLabel.id
|
||||||
? formatMessage(
|
? formatMessage(
|
||||||
{ id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
|
{ id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
|
||||||
@ -46,13 +43,12 @@ export const CheckboxWithNumberField = ({
|
|||||||
const nextValue = value ? initValue : null;
|
const nextValue = value ? initValue : null;
|
||||||
|
|
||||||
onChange({ target: { name, value: nextValue } });
|
onChange({ target: { name, value: nextValue } });
|
||||||
setShowInput((prev) => !prev);
|
|
||||||
}}
|
}}
|
||||||
checked={showInput}
|
checked={value !== null}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
{showInput && (
|
{value !== null && (
|
||||||
<Box paddingLeft={6} style={{ maxWidth: '200px' }}>
|
<Box paddingLeft={6} style={{ maxWidth: '200px' }}>
|
||||||
{type === 'text' ? (
|
{type === 'text' ? (
|
||||||
<Field.Root error={errorMessage} name={name}>
|
<Field.Root error={errorMessage} name={name}>
|
||||||
@ -70,7 +66,7 @@ export const CheckboxWithNumberField = ({
|
|||||||
aria-label={label}
|
aria-label={label}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onValueChange={(value: any) => {
|
onValueChange={(value: any) => {
|
||||||
onChange({ target: { name, value, type } });
|
onChange({ target: { name, value: value ?? 0, type } });
|
||||||
}}
|
}}
|
||||||
value={value || 0}
|
value={value || 0}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -81,7 +81,7 @@ const validators = {
|
|||||||
yup
|
yup
|
||||||
.number()
|
.number()
|
||||||
.integer()
|
.integer()
|
||||||
.min(0)
|
.min(1)
|
||||||
.when('maxLength', (maxLength, schema) => {
|
.when('maxLength', (maxLength, schema) => {
|
||||||
if (maxLength) {
|
if (maxLength) {
|
||||||
return schema.max(maxLength, getTrad('error.validation.minSupMax'));
|
return schema.max(maxLength, getTrad('error.validation.minSupMax'));
|
||||||
@ -118,7 +118,11 @@ const createTextShape = (usedAttributeNames: Array<string>, reservedNames: Array
|
|||||||
name: 'isValidRegExpPattern',
|
name: 'isValidRegExpPattern',
|
||||||
message: getTrad('error.validation.regex'),
|
message: getTrad('error.validation.regex'),
|
||||||
test(value) {
|
test(value) {
|
||||||
|
try {
|
||||||
return new RegExp(value || '') !== null;
|
return new RegExp(value || '') !== null;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.nullable(),
|
.nullable(),
|
||||||
|
|||||||
@ -42,6 +42,7 @@ export const TabForm = ({
|
|||||||
<Grid.Root gap={4}>
|
<Grid.Root gap={4}>
|
||||||
{section.items.map((input: any, i: number) => {
|
{section.items.map((input: any, i: number) => {
|
||||||
const key = `${sectionIndex}.${i}`;
|
const key = `${sectionIndex}.${i}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use undefined as the default value because not every input wants a string e.g. Date pickers
|
* Use undefined as the default value because not every input wants a string e.g. Date pickers
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -64,7 +64,7 @@
|
|||||||
"error.validation.enum-duplicate": "Duplicate values are not allowed (only alphanumeric characters are taken into account).",
|
"error.validation.enum-duplicate": "Duplicate values are not allowed (only alphanumeric characters are taken into account).",
|
||||||
"error.validation.enum-empty-string": "Empty strings are not allowed",
|
"error.validation.enum-empty-string": "Empty strings are not allowed",
|
||||||
"error.validation.enum-regex": "At least one value is invalid. Values should have at least one alphabetical character preceding the first occurence of a number.",
|
"error.validation.enum-regex": "At least one value is invalid. Values should have at least one alphabetical character preceding the first occurence of a number.",
|
||||||
"error.validation.minSupMax": "Can't be superior",
|
"error.validation.minSupMax": "min can't be superior to max",
|
||||||
"error.validation.positive": "Must be a positive number",
|
"error.validation.positive": "Must be a positive number",
|
||||||
"error.validation.regex": "Regex pattern is invalid",
|
"error.validation.regex": "Regex pattern is invalid",
|
||||||
"error.validation.relation.targetAttribute-taken": "This name exists in the target",
|
"error.validation.relation.targetAttribute-taken": "This name exists in the target",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user