mirror of
https://github.com/strapi/strapi.git
synced 2025-07-14 12:32:35 +00:00
Merge pull request #20615 from strapi/v5/cm-fixes
fix: several UI issues a typos
This commit is contained in:
commit
d0b51fbf84
@ -619,7 +619,7 @@ const reducer = <TFormValues extends FormValues = FormValues>(
|
|||||||
draft.values = setIn(
|
draft.values = setIn(
|
||||||
state.values,
|
state.values,
|
||||||
action.payload.field,
|
action.payload.field,
|
||||||
newValue.length > 0 ? newValue : undefined
|
newValue.length > 0 ? newValue : []
|
||||||
);
|
);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -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,
|
||||||
|
@ -15,8 +15,22 @@ describe('useField hook', () => {
|
|||||||
it('formats and returns nested error messages correctly for field constraints', () => {
|
it('formats and returns nested error messages correctly for field constraints', () => {
|
||||||
const expectedError = 'This attribute must be unique';
|
const expectedError = 'This attribute must be unique';
|
||||||
const initialErrors = {
|
const initialErrors = {
|
||||||
'repeatable.0.nestedUnique.TextShort': 'Another error message',
|
repeatable: [
|
||||||
'repeatable.1.nestedUnique.nestedLevelOne.nestedLevelTwo.Unique': expectedError,
|
{
|
||||||
|
nestedUnique: {
|
||||||
|
TextShort: 'Another error message',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nestedUnique: {
|
||||||
|
nestedLevelOne: {
|
||||||
|
nestedLevelTwo: {
|
||||||
|
Unique: expectedError,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const { result } = renderHook(
|
const { result } = renderHook(
|
||||||
@ -35,7 +49,9 @@ describe('useField hook', () => {
|
|||||||
defaultMessage: 'This attribute must be unique',
|
defaultMessage: 'This attribute must be unique',
|
||||||
};
|
};
|
||||||
const initialErrors = {
|
const initialErrors = {
|
||||||
'nested.uniqueAttribute': messageDescriptor,
|
nested: {
|
||||||
|
uniqueAttribute: messageDescriptor,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const { result } = renderHook(() => useField('nested.uniqueAttribute'), {
|
const { result } = renderHook(() => useField('nested.uniqueAttribute'), {
|
||||||
@ -51,9 +67,11 @@ describe('useField hook', () => {
|
|||||||
defaultMessage: 'Mixed error message',
|
defaultMessage: 'Mixed error message',
|
||||||
};
|
};
|
||||||
const initialErrors = {
|
const initialErrors = {
|
||||||
'mixed.errorField': messageDescriptor,
|
mixed: {
|
||||||
'mixed.stringError': 'String error message',
|
errorField: messageDescriptor,
|
||||||
'mixed.otherError': 123, // Non-string, non-descriptor error
|
stringError: 'String error message',
|
||||||
|
otherError: 123, // Non-string, non-descriptor error
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const { result } = renderHook(() => useField('mixed.otherError'), {
|
const { result } = renderHook(() => useField('mixed.otherError'), {
|
||||||
@ -65,8 +83,14 @@ describe('useField hook', () => {
|
|||||||
|
|
||||||
it('handles errors associated with array indices', () => {
|
it('handles errors associated with array indices', () => {
|
||||||
const initialErrors = {
|
const initialErrors = {
|
||||||
'array.0.field': 'Error on first array item',
|
array: [
|
||||||
'array.1.field': 'Error on second array item',
|
{
|
||||||
|
field: 'Error on first array item',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'Error on second array item',
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const { result } = renderHook(() => useField('array.0.field'), {
|
const { result } = renderHook(() => useField('array.0.field'), {
|
||||||
@ -88,7 +112,9 @@ describe('useField hook', () => {
|
|||||||
|
|
||||||
it('returns undefined for non-existent error paths', () => {
|
it('returns undefined for non-existent error paths', () => {
|
||||||
const initialErrors = {
|
const initialErrors = {
|
||||||
'valid.path': 'Error message',
|
valid: {
|
||||||
|
path: 'Error message',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const { result } = renderHook(() => useField('invalid.path'), {
|
const { result } = renderHook(() => useField('invalid.path'), {
|
||||||
|
@ -5,6 +5,7 @@ import { IntlFormatters, useIntl } from 'react-intl';
|
|||||||
import { FetchError } from '../utils/getFetchClient';
|
import { FetchError } from '../utils/getFetchClient';
|
||||||
import { getPrefixedId } from '../utils/getPrefixedId';
|
import { getPrefixedId } from '../utils/getPrefixedId';
|
||||||
import { NormalizeErrorOptions, normalizeAPIError } from '../utils/normalizeAPIError';
|
import { NormalizeErrorOptions, normalizeAPIError } from '../utils/normalizeAPIError';
|
||||||
|
import { setIn } from '../utils/objects';
|
||||||
|
|
||||||
import type { errors } from '@strapi/utils';
|
import type { errors } from '@strapi/utils';
|
||||||
|
|
||||||
@ -156,10 +157,7 @@ export function useAPIErrorHandler(
|
|||||||
return validationErrors.reduce((acc, err) => {
|
return validationErrors.reduce((acc, err) => {
|
||||||
const { path, message } = err;
|
const { path, message } = err;
|
||||||
|
|
||||||
return {
|
return setIn(acc, path.join('.'), message);
|
||||||
...acc,
|
|
||||||
[path.join('.')]: message,
|
|
||||||
};
|
|
||||||
}, {});
|
}, {});
|
||||||
} else {
|
} else {
|
||||||
const details = error.details as Record<string, string[]>;
|
const details = error.details as Record<string, string[]>;
|
||||||
|
@ -286,6 +286,7 @@ const EventsRow = ({
|
|||||||
{events.map((event) => {
|
{events.map((event) => {
|
||||||
return (
|
return (
|
||||||
<Td key={event} textAlign="center">
|
<Td key={event} textAlign="center">
|
||||||
|
<Flex width="100%" justifyContent="center">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
disabled={disabledEvents.includes(event)}
|
disabled={disabledEvents.includes(event)}
|
||||||
aria-label={event}
|
aria-label={event}
|
||||||
@ -293,6 +294,7 @@ const EventsRow = ({
|
|||||||
checked={inputValue.includes(event)}
|
checked={inputValue.includes(event)}
|
||||||
onCheckedChange={(value) => handleSelect(event, !!value)}
|
onCheckedChange={(value) => handleSelect(event, !!value)}
|
||||||
/>
|
/>
|
||||||
|
</Flex>
|
||||||
</Td>
|
</Td>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -13,10 +13,15 @@ import {
|
|||||||
} from '@strapi/design-system';
|
} from '@strapi/design-system';
|
||||||
import { Minus, Plus } from '@strapi/icons';
|
import { Minus, Plus } from '@strapi/icons';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
import { styled } from 'styled-components';
|
||||||
|
|
||||||
import { useField, useForm } from '../../../../../components/Form';
|
import { useField, useForm } from '../../../../../components/Form';
|
||||||
import { StringInput } from '../../../../../components/FormInputs/String';
|
import { StringInput } from '../../../../../components/FormInputs/String';
|
||||||
|
|
||||||
|
const AddHeaderButton = styled(TextButton)`
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------------------------------
|
||||||
* HeadersInput
|
* HeadersInput
|
||||||
* -----------------------------------------------------------------------------------------------*/
|
* -----------------------------------------------------------------------------------------------*/
|
||||||
@ -44,7 +49,7 @@ const HeadersInput = () => {
|
|||||||
<Box padding={8} background="neutral100" hasRadius>
|
<Box padding={8} background="neutral100" hasRadius>
|
||||||
{value.map((_, index) => {
|
{value.map((_, index) => {
|
||||||
return (
|
return (
|
||||||
<Grid.Root key={index} gap={4}>
|
<Grid.Root key={index} gap={4} padding={2}>
|
||||||
<Grid.Item col={6}>
|
<Grid.Item col={6}>
|
||||||
<HeaderCombobox
|
<HeaderCombobox
|
||||||
name={`headers.${index}.key`}
|
name={`headers.${index}.key`}
|
||||||
@ -92,8 +97,11 @@ const HeadersInput = () => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Grid.Item>
|
</Grid.Item>
|
||||||
<Grid.Item col={12}>
|
</Grid.Root>
|
||||||
<TextButton
|
);
|
||||||
|
})}
|
||||||
|
<Box paddingTop={4}>
|
||||||
|
<AddHeaderButton
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
addFieldRow('headers', { key: '', value: '' });
|
addFieldRow('headers', { key: '', value: '' });
|
||||||
@ -104,11 +112,8 @@ const HeadersInput = () => {
|
|||||||
id: 'Settings.webhooks.create.header',
|
id: 'Settings.webhooks.create.header',
|
||||||
defaultMessage: 'Create new header',
|
defaultMessage: 'Create new header',
|
||||||
})}
|
})}
|
||||||
</TextButton>
|
</AddHeaderButton>
|
||||||
</Grid.Item>
|
</Box>
|
||||||
</Grid.Root>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
@ -72,14 +72,6 @@ const ListPage = () => {
|
|||||||
// In this case, the passed parameter cannot and shouldn't be something else than User
|
// In this case, the passed parameter cannot and shouldn't be something else than User
|
||||||
cellFormatter: ({ user }) => (user ? user.displayName : ''),
|
cellFormatter: ({ user }) => (user ? user.displayName : ''),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'actions',
|
|
||||||
label: formatMessage({
|
|
||||||
id: 'Settings.permissions.auditLogs.actions',
|
|
||||||
defaultMessage: 'Actions',
|
|
||||||
}),
|
|
||||||
sortable: false,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (hasError) {
|
if (hasError) {
|
||||||
@ -170,8 +162,6 @@ const ListPage = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
);
|
);
|
||||||
case 'actions':
|
|
||||||
return null;
|
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<Table.Cell key={name}>
|
<Table.Cell key={name}>
|
||||||
@ -202,8 +192,9 @@ const ListPage = () => {
|
|||||||
</Table.Body>
|
</Table.Body>
|
||||||
</Table.Content>
|
</Table.Content>
|
||||||
</Table.Root>
|
</Table.Root>
|
||||||
<Pagination.Root {...auditLogs?.pagination} defaultPageSize={24}>
|
|
||||||
<Pagination.PageSize options={['12', '24', '50', '100']} />
|
<Pagination.Root {...auditLogs?.pagination}>
|
||||||
|
<Pagination.PageSize />
|
||||||
<Pagination.Links />
|
<Pagination.Links />
|
||||||
</Pagination.Root>
|
</Pagination.Root>
|
||||||
</Layouts.Content>
|
</Layouts.Content>
|
||||||
|
@ -28,7 +28,6 @@ describe('ADMIN | Pages | AUDIT LOGS | ListPage', () => {
|
|||||||
'Action',
|
'Action',
|
||||||
'Date',
|
'Date',
|
||||||
'User',
|
'User',
|
||||||
'Actions',
|
|
||||||
'Admin logout',
|
'Admin logout',
|
||||||
'October 31, 2023, 15:56:54',
|
'October 31, 2023, 15:56:54',
|
||||||
'Create user',
|
'Create user',
|
||||||
|
@ -78,7 +78,11 @@ describe('useDocument', () => {
|
|||||||
postal_code: 'N2',
|
postal_code: 'N2',
|
||||||
notrepeat_req: {},
|
notrepeat_req: {},
|
||||||
city: 'London',
|
city: 'London',
|
||||||
repeat_req: [],
|
repeat_req: [
|
||||||
|
{
|
||||||
|
name: 'toto',
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
).toBeNull();
|
).toBeNull();
|
||||||
|
|
||||||
@ -89,7 +93,11 @@ describe('useDocument', () => {
|
|||||||
notrepeat_req: {},
|
notrepeat_req: {},
|
||||||
postal_code: 12,
|
postal_code: 12,
|
||||||
city: 'London',
|
city: 'London',
|
||||||
repeat_req: [],
|
repeat_req: [
|
||||||
|
{
|
||||||
|
name: 'toto',
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
|
@ -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>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -192,10 +192,7 @@ const DynamicZone = ({
|
|||||||
removeFieldRow(name, currentIndex);
|
removeFieldRow(name, currentIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasError =
|
const hasError = error !== undefined;
|
||||||
error !== undefined ||
|
|
||||||
dynamicDisplayedComponentsLength < min ||
|
|
||||||
dynamicDisplayedComponentsLength > max;
|
|
||||||
|
|
||||||
const renderButtonLabel = () => {
|
const renderButtonLabel = () => {
|
||||||
if (addComponentIsOpen) {
|
if (addComponentIsOpen) {
|
||||||
|
@ -179,7 +179,9 @@ const useFieldHint = (hint: ReactNode = undefined, attribute: Schema.Attribute.A
|
|||||||
return hint;
|
return hint;
|
||||||
}
|
}
|
||||||
|
|
||||||
const units = !['biginteger', 'integer', 'number'].includes(attribute.type)
|
const units = !['biginteger', 'integer', 'number', 'dynamiczone', 'component'].includes(
|
||||||
|
attribute.type
|
||||||
|
)
|
||||||
? formatMessage(
|
? formatMessage(
|
||||||
{
|
{
|
||||||
id: 'content-manager.form.Input.hint.character.unit',
|
id: 'content-manager.form.Input.hint.character.unit',
|
||||||
|
@ -216,11 +216,17 @@ type ValidationFn = (
|
|||||||
) => <TSchema extends AnySchema>(schema: TSchema) => TSchema;
|
) => <TSchema extends AnySchema>(schema: TSchema) => TSchema;
|
||||||
|
|
||||||
const addRequiredValidation: ValidationFn = (attribute) => (schema) => {
|
const addRequiredValidation: ValidationFn = (attribute) => (schema) => {
|
||||||
|
if (
|
||||||
|
((attribute.type === 'component' && attribute.repeatable) ||
|
||||||
|
attribute.type === 'dynamiczone') &&
|
||||||
|
attribute.required &&
|
||||||
|
'min' in schema
|
||||||
|
) {
|
||||||
|
return schema.min(1, translatedErrors.required);
|
||||||
|
}
|
||||||
|
|
||||||
if (attribute.required && attribute.type !== 'relation') {
|
if (attribute.required && attribute.type !== 'relation') {
|
||||||
return schema.required({
|
return schema.required(translatedErrors.required);
|
||||||
id: translatedErrors.required.id,
|
|
||||||
defaultMessage: 'This field is required.',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return schema?.nullable
|
return schema?.nullable
|
||||||
@ -277,6 +283,35 @@ const addMinValidation: ValidationFn =
|
|||||||
if ('min' in attribute) {
|
if ('min' in attribute) {
|
||||||
const min = toInteger(attribute.min);
|
const min = toInteger(attribute.min);
|
||||||
|
|
||||||
|
if (
|
||||||
|
(attribute.type === 'component' && attribute.repeatable) ||
|
||||||
|
attribute.type === 'dynamiczone'
|
||||||
|
) {
|
||||||
|
if (!attribute.required && 'test' in schema && min) {
|
||||||
|
// @ts-expect-error - We know the schema is an array here but ts doesn't know.
|
||||||
|
return schema.test(
|
||||||
|
'custom-min',
|
||||||
|
{
|
||||||
|
...translatedErrors.min,
|
||||||
|
values: {
|
||||||
|
min: attribute.min,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(value: Array<unknown>) => {
|
||||||
|
if (!value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(value) && value.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.length >= min;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ('min' in schema && min) {
|
if ('min' in schema && min) {
|
||||||
return schema.min(min, {
|
return schema.min(min, {
|
||||||
...translatedErrors.min,
|
...translatedErrors.min,
|
||||||
|
@ -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",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { Box, Checkbox, Flex, Typography, Grid, VisuallyHidden } from '@strapi/design-system';
|
import { Box, Checkbox, Flex, Typography, Grid, VisuallyHidden } from '@strapi/design-system';
|
||||||
import { Cog as CogIcon } from '@strapi/icons';
|
import { Cog } from '@strapi/icons';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
@ -103,7 +103,7 @@ const SubCategory = ({ subCategory }) => {
|
|||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
</VisuallyHidden>
|
</VisuallyHidden>
|
||||||
<CogIcon id="cog" />
|
<Cog id="cog" />
|
||||||
</button>
|
</button>
|
||||||
</CheckboxWrapper>
|
</CheckboxWrapper>
|
||||||
</Grid.Item>
|
</Grid.Item>
|
||||||
|
@ -63,7 +63,7 @@ export const ProvidersPage = () => {
|
|||||||
|
|
||||||
const submitMutation = useMutation((body) => put('/users-permissions/providers', body), {
|
const submitMutation = useMutation((body) => put('/users-permissions/providers', body), {
|
||||||
async onSuccess() {
|
async onSuccess() {
|
||||||
await queryClient.invalidateQueries(['users-permissions', 'providers']);
|
await queryClient.invalidateQueries(['users-permissions', 'get-providers']);
|
||||||
|
|
||||||
toggleNotification({
|
toggleNotification({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
|
@ -13,7 +13,7 @@ const EditLink = styled(Link)`
|
|||||||
width: 3.2rem;
|
width: 3.2rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: ${({ theme }) => `${theme.spaces[2]}}`};
|
padding: ${({ theme }) => `${theme.spaces[2]}`};
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
height: 1.6rem;
|
height: 1.6rem;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user