370 lines
15 KiB
JavaScript
370 lines
15 KiB
JavaScript
import { jsxs, jsx } from 'react/jsx-runtime';
|
||
import * as React from 'react';
|
||
import { useNotification, useAPIErrorHandler, useAuth, Form, useForm, InputRenderer, useField } from '@strapi/admin/strapi-admin';
|
||
import { Modal, Button, useId, Tabs, Flex, Typography, Divider, Box, Grid, Field, SingleSelect, SingleSelectOption } from '@strapi/design-system';
|
||
import { Plus, Check } from '@strapi/icons';
|
||
import { useIntl } from 'react-intl';
|
||
import * as yup from 'yup';
|
||
import { useCreateLocaleMutation, useGetDefaultLocalesQuery } from '../services/locales.mjs';
|
||
import { isBaseQueryError } from '../utils/baseQuery.mjs';
|
||
import { getTranslation } from '../utils/getTranslation.mjs';
|
||
|
||
const CreateLocale = ({ disabled, variant = 'default' })=>{
|
||
const { formatMessage } = useIntl();
|
||
const [visible, setVisible] = React.useState(false);
|
||
return /*#__PURE__*/ jsxs(Modal.Root, {
|
||
open: visible,
|
||
onOpenChange: setVisible,
|
||
children: [
|
||
/*#__PURE__*/ jsx(Modal.Trigger, {
|
||
children: /*#__PURE__*/ jsx(Button, {
|
||
variant: variant,
|
||
disabled: disabled,
|
||
startIcon: /*#__PURE__*/ jsx(Plus, {}),
|
||
onClick: ()=>setVisible(true),
|
||
size: "S",
|
||
children: formatMessage({
|
||
id: getTranslation('Settings.list.actions.add'),
|
||
defaultMessage: 'Add new locale'
|
||
})
|
||
})
|
||
}),
|
||
/*#__PURE__*/ jsx(CreateModal, {
|
||
onClose: ()=>setVisible(false)
|
||
})
|
||
]
|
||
});
|
||
};
|
||
/* -------------------------------------------------------------------------------------------------
|
||
* CreateModal
|
||
* -----------------------------------------------------------------------------------------------*/ const LOCALE_SCHEMA = yup.object().shape({
|
||
code: yup.string().nullable().required({
|
||
id: 'Settings.locales.modal.create.code.error',
|
||
defaultMessage: 'Please select a locale'
|
||
}),
|
||
name: yup.string().nullable().max(50, {
|
||
id: 'Settings.locales.modal.create.name.error.min',
|
||
defaultMessage: 'The locale display name can only be less than 50 characters.'
|
||
}).required({
|
||
id: 'Settings.locales.modal.create.name.error.required',
|
||
defaultMessage: 'Please give the locale a display name'
|
||
}),
|
||
isDefault: yup.boolean()
|
||
});
|
||
const initialFormValues = {
|
||
code: '',
|
||
name: '',
|
||
isDefault: false
|
||
};
|
||
const CreateModal = ({ onClose })=>{
|
||
const titleId = useId();
|
||
const { toggleNotification } = useNotification();
|
||
const { _unstableFormatAPIError: formatAPIError, _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
||
const [createLocale] = useCreateLocaleMutation();
|
||
const { formatMessage } = useIntl();
|
||
const refetchPermissions = useAuth('CreateModal', (state)=>state.refetchPermissions);
|
||
const handleSubmit = async (values, helpers)=>{
|
||
try {
|
||
const res = await createLocale(values);
|
||
if ('error' in res) {
|
||
if (isBaseQueryError(res.error) && res.error.name === 'ValidationError') {
|
||
helpers.setErrors(formatValidationErrors(res.error));
|
||
} else {
|
||
toggleNotification({
|
||
type: 'danger',
|
||
message: formatAPIError(res.error)
|
||
});
|
||
}
|
||
return;
|
||
}
|
||
toggleNotification({
|
||
type: 'success',
|
||
message: formatMessage({
|
||
id: getTranslation('Settings.locales.modal.create.success'),
|
||
defaultMessage: 'Created locale'
|
||
})
|
||
});
|
||
refetchPermissions();
|
||
onClose();
|
||
} catch (err) {
|
||
toggleNotification({
|
||
type: 'danger',
|
||
message: formatMessage({
|
||
id: 'notification.error',
|
||
defaultMessage: 'An error occurred, please try again'
|
||
})
|
||
});
|
||
}
|
||
};
|
||
return /*#__PURE__*/ jsx(Modal.Content, {
|
||
children: /*#__PURE__*/ jsxs(Form, {
|
||
method: "POST",
|
||
initialValues: initialFormValues,
|
||
validationSchema: LOCALE_SCHEMA,
|
||
onSubmit: handleSubmit,
|
||
children: [
|
||
/*#__PURE__*/ jsx(Modal.Header, {
|
||
children: /*#__PURE__*/ jsx(Modal.Title, {
|
||
children: formatMessage({
|
||
id: getTranslation('Settings.list.actions.add'),
|
||
defaultMessage: 'Add new locale'
|
||
})
|
||
})
|
||
}),
|
||
/*#__PURE__*/ jsx(Modal.Body, {
|
||
children: /*#__PURE__*/ jsxs(Tabs.Root, {
|
||
variant: "simple",
|
||
defaultValue: "basic",
|
||
children: [
|
||
/*#__PURE__*/ jsxs(Flex, {
|
||
justifyContent: "space-between",
|
||
children: [
|
||
/*#__PURE__*/ jsx(Typography, {
|
||
tag: "h2",
|
||
variant: "beta",
|
||
id: titleId,
|
||
children: formatMessage({
|
||
id: getTranslation('Settings.locales.modal.title'),
|
||
defaultMessage: 'Configuration'
|
||
})
|
||
}),
|
||
/*#__PURE__*/ jsxs(Tabs.List, {
|
||
"aria-labelledby": titleId,
|
||
children: [
|
||
/*#__PURE__*/ jsx(Tabs.Trigger, {
|
||
value: "basic",
|
||
children: formatMessage({
|
||
id: getTranslation('Settings.locales.modal.base'),
|
||
defaultMessage: 'Basic settings'
|
||
})
|
||
}),
|
||
/*#__PURE__*/ jsx(Tabs.Trigger, {
|
||
value: "advanced",
|
||
children: formatMessage({
|
||
id: getTranslation('Settings.locales.modal.advanced'),
|
||
defaultMessage: 'Advanced settings'
|
||
})
|
||
})
|
||
]
|
||
})
|
||
]
|
||
}),
|
||
/*#__PURE__*/ jsx(Divider, {}),
|
||
/*#__PURE__*/ jsxs(Box, {
|
||
paddingTop: 7,
|
||
paddingBottom: 7,
|
||
children: [
|
||
/*#__PURE__*/ jsx(Tabs.Content, {
|
||
value: "basic",
|
||
children: /*#__PURE__*/ jsx(BaseForm, {})
|
||
}),
|
||
/*#__PURE__*/ jsx(Tabs.Content, {
|
||
value: "advanced",
|
||
children: /*#__PURE__*/ jsx(AdvancedForm, {})
|
||
})
|
||
]
|
||
})
|
||
]
|
||
})
|
||
}),
|
||
/*#__PURE__*/ jsxs(Modal.Footer, {
|
||
children: [
|
||
/*#__PURE__*/ jsx(Modal.Close, {
|
||
children: /*#__PURE__*/ jsx(Button, {
|
||
variant: "tertiary",
|
||
children: formatMessage({
|
||
id: 'app.components.Button.cancel',
|
||
defaultMessage: 'Cancel'
|
||
})
|
||
})
|
||
}),
|
||
/*#__PURE__*/ jsx(SubmitButton, {})
|
||
]
|
||
})
|
||
]
|
||
})
|
||
});
|
||
};
|
||
/* -------------------------------------------------------------------------------------------------
|
||
* SubmitButton
|
||
* -----------------------------------------------------------------------------------------------*/ const SubmitButton = ()=>{
|
||
const { formatMessage } = useIntl();
|
||
const isSubmitting = useForm('SubmitButton', (state)=>state.isSubmitting);
|
||
const modified = useForm('SubmitButton', (state)=>state.modified);
|
||
return /*#__PURE__*/ jsx(Button, {
|
||
type: "submit",
|
||
startIcon: /*#__PURE__*/ jsx(Check, {}),
|
||
disabled: isSubmitting || !modified,
|
||
children: formatMessage({
|
||
id: 'global.save',
|
||
defaultMessage: 'Save'
|
||
})
|
||
});
|
||
};
|
||
const BaseForm = ({ mode = 'create' })=>{
|
||
const { formatMessage } = useIntl();
|
||
const { toggleNotification } = useNotification();
|
||
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
||
const { data: defaultLocales, error } = useGetDefaultLocalesQuery();
|
||
React.useEffect(()=>{
|
||
if (error) {
|
||
toggleNotification({
|
||
type: 'danger',
|
||
message: formatAPIError(error)
|
||
});
|
||
}
|
||
}, [
|
||
error,
|
||
formatAPIError,
|
||
toggleNotification
|
||
]);
|
||
if (!Array.isArray(defaultLocales)) {
|
||
return null;
|
||
}
|
||
const options = defaultLocales.map((locale)=>({
|
||
label: locale.name,
|
||
value: locale.code
|
||
}));
|
||
const translatedForm = [
|
||
{
|
||
disabled: mode !== 'create',
|
||
label: {
|
||
id: getTranslation('Settings.locales.modal.create.code.label'),
|
||
defaultMessage: 'Locales'
|
||
},
|
||
name: 'code',
|
||
options,
|
||
placeholder: {
|
||
id: 'components.placeholder.select',
|
||
defaultMessage: 'Select'
|
||
},
|
||
required: true,
|
||
size: 6,
|
||
type: 'enumeration'
|
||
},
|
||
{
|
||
hint: {
|
||
id: getTranslation('Settings.locales.modal.create.name.label.description'),
|
||
defaultMessage: 'Locale will be displayed under that name in the administration panel'
|
||
},
|
||
label: {
|
||
id: getTranslation('Settings.locales.modal.create.name.label'),
|
||
defaultMessage: 'Locale display name'
|
||
},
|
||
name: 'name',
|
||
required: true,
|
||
size: 6,
|
||
type: 'string'
|
||
}
|
||
].map((field)=>({
|
||
...field,
|
||
hint: field.hint ? formatMessage(field.hint) : undefined,
|
||
label: formatMessage(field.label),
|
||
placeholder: field.placeholder ? formatMessage(field.placeholder) : undefined
|
||
}));
|
||
return /*#__PURE__*/ jsx(Grid.Root, {
|
||
gap: 4,
|
||
children: translatedForm.map(({ size, ...field })=>/*#__PURE__*/ jsx(Grid.Item, {
|
||
col: size,
|
||
direction: "column",
|
||
alignItems: "stretch",
|
||
children: /*#__PURE__*/ jsx(FormRenderer, {
|
||
...field
|
||
})
|
||
}, field.name))
|
||
});
|
||
};
|
||
const AdvancedForm = ({ isDefaultLocale })=>{
|
||
const { formatMessage } = useIntl();
|
||
const form = [
|
||
{
|
||
disabled: isDefaultLocale,
|
||
hint: {
|
||
id: getTranslation('Settings.locales.modal.advanced.setAsDefault.hint'),
|
||
defaultMessage: 'One default locale is required, change it by selecting another one'
|
||
},
|
||
label: {
|
||
id: getTranslation('Settings.locales.modal.advanced.setAsDefault'),
|
||
defaultMessage: 'Set as default locale'
|
||
},
|
||
name: 'isDefault',
|
||
size: 6,
|
||
type: 'boolean'
|
||
}
|
||
].map((field)=>({
|
||
...field,
|
||
hint: field.hint ? formatMessage(field.hint) : undefined,
|
||
label: formatMessage(field.label)
|
||
}));
|
||
return /*#__PURE__*/ jsx(Grid.Root, {
|
||
gap: 4,
|
||
children: form.map(({ size, ...field })=>/*#__PURE__*/ jsx(Grid.Item, {
|
||
col: size,
|
||
direction: "column",
|
||
alignItems: "stretch",
|
||
children: /*#__PURE__*/ jsx(FormRenderer, {
|
||
...field
|
||
})
|
||
}, field.name))
|
||
});
|
||
};
|
||
/* -------------------------------------------------------------------------------------------------
|
||
* FormRenderer
|
||
* -----------------------------------------------------------------------------------------------*/ const FormRenderer = (field)=>{
|
||
switch(field.type){
|
||
/**
|
||
* This will override the default input renderer
|
||
* choice for `enumeration`.
|
||
*/ case 'enumeration':
|
||
return /*#__PURE__*/ jsx(EnumerationInput, {
|
||
...field
|
||
});
|
||
default:
|
||
return /*#__PURE__*/ jsx(InputRenderer, {
|
||
...field
|
||
});
|
||
}
|
||
};
|
||
const EnumerationInput = ({ disabled, hint, label, name, options, placeholder, required })=>{
|
||
const { value, error, onChange } = useField(name);
|
||
const { data: defaultLocales = [] } = useGetDefaultLocalesQuery();
|
||
const handleChange = (value)=>{
|
||
if (Array.isArray(defaultLocales)) {
|
||
// We know it exists because the options are created from the list of default locales
|
||
const locale = defaultLocales.find((locale)=>locale.code === value);
|
||
onChange(name, value);
|
||
// This lets us automatically fill the name field with the locale name
|
||
onChange('name', locale.name);
|
||
} else {
|
||
onChange(name, value);
|
||
}
|
||
};
|
||
return /*#__PURE__*/ jsxs(Field.Root, {
|
||
error: error,
|
||
hint: hint,
|
||
name: name,
|
||
required: required,
|
||
children: [
|
||
/*#__PURE__*/ jsx(Field.Label, {
|
||
children: label
|
||
}),
|
||
/*#__PURE__*/ jsx(SingleSelect, {
|
||
disabled: disabled,
|
||
// @ts-expect-error – This will dissapear when the DS removes support for numbers to be returned by SingleSelect.
|
||
onChange: handleChange,
|
||
placeholder: placeholder,
|
||
value: value,
|
||
children: options.map((option)=>/*#__PURE__*/ jsx(SingleSelectOption, {
|
||
value: option.value,
|
||
children: option.label
|
||
}, option.value))
|
||
}),
|
||
/*#__PURE__*/ jsx(Field.Error, {}),
|
||
/*#__PURE__*/ jsx(Field.Hint, {})
|
||
]
|
||
});
|
||
};
|
||
|
||
export { AdvancedForm, BaseForm, CreateLocale, LOCALE_SCHEMA, SubmitButton };
|
||
//# sourceMappingURL=CreateLocale.mjs.map
|