node_modules ignore

This commit is contained in:
oier committed 2025-05-08 23:43:47 +02:00
1 parent e19d52f172
commit 4574544c9f
65041 files changed
+10593536

No files matched your search

@@ -0,0 +1,262 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
require('react');
var strapiAdmin = require('@strapi/admin/strapi-admin');
var designSystem = require('@strapi/design-system');
var icons = require('@strapi/icons');
var qs = require('qs');
var reactIntl = require('react-intl');
var reactRouterDom = require('react-router-dom');
var getTranslation = require('../utils/getTranslation.js');
var strings = require('../utils/strings.js');
const isErrorMessageDescriptor = (object)=>{
return typeof object === 'object' && object !== null && 'id' in object && 'defaultMessage' in object;
};
const EntryValidationText = ({ status = 'draft', validationErrors, action })=>{
const { formatMessage } = reactIntl.useIntl();
/**
* TODO: Should this be extracted an made into a factory to recursively get
* error messages??
*/ const getErrorStr = (key, value)=>{
if (typeof value === 'string') {
return `${key}: ${value}`;
} else if (isErrorMessageDescriptor(value)) {
return `${key}: ${formatMessage(value)}`;
} else if (Array.isArray(value)) {
return value.map((v)=>getErrorStr(key, v)).join(' ');
} else if (typeof value === 'object' && !Array.isArray(value)) {
return Object.entries(value).map(([k, v])=>getErrorStr(k, v)).join(' ');
} else {
/**
* unlikely to happen, but we need to return something
*/ return '';
}
};
if (validationErrors) {
const validationErrorsMessages = Object.entries(validationErrors).map(([key, value])=>{
return getErrorStr(key, value);
}).join(' ');
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
gap: 2,
children: [
/*#__PURE__*/ jsxRuntime.jsx(icons.CrossCircle, {
fill: "danger600"
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Tooltip, {
label: validationErrorsMessages,
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
maxWidth: '30rem',
textColor: "danger600",
variant: "omega",
fontWeight: "semiBold",
ellipsis: true,
children: validationErrorsMessages
})
})
]
});
}
const getStatusMessage = ()=>{
if (action === 'bulk-publish') {
if (status === 'published') {
return {
icon: /*#__PURE__*/ jsxRuntime.jsx(icons.CheckCircle, {
fill: "success600"
}),
text: formatMessage({
id: 'content-manager.bulk-publish.already-published',
defaultMessage: 'Already Published'
}),
textColor: 'success600',
fontWeight: 'bold'
};
} else if (status === 'modified') {
return {
icon: /*#__PURE__*/ jsxRuntime.jsx(icons.ArrowsCounterClockwise, {
fill: "alternative600"
}),
text: formatMessage({
id: 'app.utils.ready-to-publish-changes',
defaultMessage: 'Ready to publish changes'
})
};
} else {
return {
icon: /*#__PURE__*/ jsxRuntime.jsx(icons.CheckCircle, {
fill: "success600"
}),
text: formatMessage({
id: 'app.utils.ready-to-publish',
defaultMessage: 'Ready to publish'
})
};
}
} else {
if (status === 'draft') {
return {
icon: /*#__PURE__*/ jsxRuntime.jsx(icons.CheckCircle, {
fill: "success600"
}),
text: formatMessage({
id: 'content-manager.bulk-unpublish.already-unpublished',
defaultMessage: 'Already Unpublished'
}),
textColor: 'success600',
fontWeight: 'bold'
};
} else {
return {
icon: /*#__PURE__*/ jsxRuntime.jsx(icons.CheckCircle, {
fill: "success600"
}),
text: formatMessage({
id: 'app.utils.ready-to-unpublish-changes',
defaultMessage: 'Ready to unpublish'
}),
textColor: 'success600',
fontWeight: 'bold'
};
}
}
};
const { icon, text, textColor = 'success600', fontWeight = 'normal' } = getStatusMessage();
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
gap: 2,
children: [
icon,
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
textColor: textColor,
fontWeight: fontWeight,
children: text
})
]
});
};
/* -------------------------------------------------------------------------------------------------
* BoldChunk
* -----------------------------------------------------------------------------------------------*/ const BoldChunk = (chunks)=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
fontWeight: "bold",
children: chunks
});
const BulkLocaleActionModal = ({ headers, rows, localesMetadata, validationErrors = {}, action })=>{
const { formatMessage } = reactIntl.useIntl();
const selectedRows = strapiAdmin.useTable('BulkLocaleActionModal', (state)=>state.selectedRows);
const getFormattedCountMessage = ()=>{
const currentStatusByLocale = rows.reduce((acc, { locale, status })=>{
acc[locale] = status;
return acc;
}, {});
const localesWithErrors = Object.keys(validationErrors);
const publishedCount = selectedRows.filter(({ locale })=>currentStatusByLocale[locale] === 'published').length;
const draftCount = selectedRows.filter(({ locale })=>(currentStatusByLocale[locale] === 'draft' || currentStatusByLocale[locale] === 'modified') && !localesWithErrors.includes(locale)).length;
const withErrorsCount = localesWithErrors.length;
const messageId = action === 'bulk-publish' ? 'content-manager.containers.list.selectedEntriesModal.selectedCount.publish' : 'content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish';
const defaultMessage = action === 'bulk-publish' ? '<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action.' : '<b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} already unpublished. <b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} ready to unpublish.';
return formatMessage({
id: messageId,
defaultMessage
}, {
withErrorsCount,
draftCount,
publishedCount,
b: BoldChunk
});
};
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Body, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
children: getFormattedCountMessage()
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
marginTop: 5,
children: /*#__PURE__*/ jsxRuntime.jsxs(strapiAdmin.Table.Content, {
children: [
/*#__PURE__*/ jsxRuntime.jsxs(strapiAdmin.Table.Head, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Table.HeaderCheckboxCell, {}),
headers.map((head)=>/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Table.HeaderCell, {
...head
}, head.name))
]
}),
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Table.Body, {
children: rows.map(({ locale, status }, index)=>{
const error = validationErrors?.[locale] ?? null;
const statusVariant = status === 'draft' ? 'primary' : status === 'published' ? 'success' : 'alternative';
return /*#__PURE__*/ jsxRuntime.jsxs(strapiAdmin.Table.Row, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, {
id: locale,
"aria-label": `Select ${locale}`
}),
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Table.Cell, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
variant: "sigma",
textColor: "neutral600",
children: Array.isArray(localesMetadata) ? localesMetadata.find((localeEntry)=>localeEntry.code === locale)?.name : locale
})
}),
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Table.Cell, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
display: "flex",
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Status, {
display: "flex",
paddingLeft: "6px",
paddingRight: "6px",
paddingTop: "2px",
paddingBottom: "2px",
size: 'S',
variant: statusVariant,
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
tag: "span",
variant: "pi",
fontWeight: "bold",
children: strings.capitalize(status)
})
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Table.Cell, {
children: /*#__PURE__*/ jsxRuntime.jsx(EntryValidationText, {
validationErrors: error,
status: status,
action: action
})
}),
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Table.Cell, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
tag: reactRouterDom.Link,
to: {
search: qs.stringify({
plugins: {
i18n: {
locale
}
}
})
},
label: formatMessage({
id: getTranslation.getTranslation('Settings.list.actions.edit'),
defaultMessage: 'Edit {name} locale'
}, {
name: locale
}),
variant: "ghost",
children: /*#__PURE__*/ jsxRuntime.jsx(icons.Pencil, {})
})
})
]
}, index);
})
})
]
})
})
]
});
};
exports.BulkLocaleActionModal = BulkLocaleActionModal;
//# sourceMappingURL=BulkLocaleActionModal.js.map
@@ -0,0 +1 @@
{"version":3,"file":"BulkLocaleActionModal.js","sources":["../../../admin/src/components/BulkLocaleActionModal.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { FormErrors, Table, useTable } from '@strapi/admin/strapi-admin';\nimport { Box, Typography, IconButton, Flex, Tooltip, Status, Modal } from '@strapi/design-system';\nimport { Pencil, CheckCircle, CrossCircle, ArrowsCounterClockwise } from '@strapi/icons';\nimport { stringify } from 'qs';\nimport { type MessageDescriptor, useIntl, PrimitiveType } from 'react-intl';\nimport { Link } from 'react-router-dom';\n\nimport { Locale } from '../../../shared/contracts/locales';\nimport { getTranslation } from '../utils/getTranslation';\nimport { capitalize } from '../utils/strings';\n\nimport { LocaleStatus } from './CMHeaderActions';\n\nimport type { Modules } from '@strapi/types';\n\ntype Status = Modules.Documents.Params.PublicationStatus.Kind | 'modified';\n\n/* -------------------------------------------------------------------------------------------------\n * EntryValidationText\n * -----------------------------------------------------------------------------------------------*/\n\ninterface EntryValidationTextProps {\n status: Status;\n validationErrors: FormErrors[string] | null;\n action: 'bulk-publish' | 'bulk-unpublish';\n}\n\ninterface TranslationMessage extends MessageDescriptor {\n values?: Record<string, PrimitiveType>;\n}\n\nconst isErrorMessageDescriptor = (object?: string | object): object is TranslationMessage => {\n return (\n typeof object === 'object' && object !== null && 'id' in object && 'defaultMessage' in object\n );\n};\n\nconst EntryValidationText = ({\n status = 'draft',\n validationErrors,\n action,\n}: EntryValidationTextProps) => {\n const { formatMessage } = useIntl();\n\n /**\n * TODO: Should this be extracted an made into a factory to recursively get\n * error messages??\n */\n const getErrorStr = (key: string, value?: FormErrors[string]): string => {\n if (typeof value === 'string') {\n return `${key}: ${value}`;\n } else if (isErrorMessageDescriptor(value)) {\n return `${key}: ${formatMessage(value)}`;\n } else if (Array.isArray(value)) {\n return value.map((v) => getErrorStr(key, v)).join(' ');\n } else if (typeof value === 'object' && !Array.isArray(value)) {\n return Object.entries(value)\n .map(([k, v]) => getErrorStr(k, v))\n .join(' ');\n } else {\n /**\n * unlikely to happen, but we need to return something\n */\n return '';\n }\n };\n\n if (validationErrors) {\n const validationErrorsMessages = Object.entries(validationErrors)\n .map(([key, value]) => {\n return getErrorStr(key, value);\n })\n .join(' ');\n\n return (\n <Flex gap={2}>\n <CrossCircle fill=\"danger600\" />\n <Tooltip label={validationErrorsMessages}>\n <Typography\n maxWidth={'30rem'}\n textColor=\"danger600\"\n variant=\"omega\"\n fontWeight=\"semiBold\"\n ellipsis\n >\n {validationErrorsMessages}\n </Typography>\n </Tooltip>\n </Flex>\n );\n }\n\n const getStatusMessage = () => {\n if (action === 'bulk-publish') {\n if (status === 'published') {\n return {\n icon: <CheckCircle fill=\"success600\" />,\n text: formatMessage({\n id: 'content-manager.bulk-publish.already-published',\n defaultMessage: 'Already Published',\n }),\n textColor: 'success600',\n fontWeight: 'bold',\n };\n } else if (status === 'modified') {\n return {\n icon: <ArrowsCounterClockwise fill=\"alternative600\" />,\n text: formatMessage({\n id: 'app.utils.ready-to-publish-changes',\n defaultMessage: 'Ready to publish changes',\n }),\n };\n } else {\n return {\n icon: <CheckCircle fill=\"success600\" />,\n text: formatMessage({\n id: 'app.utils.ready-to-publish',\n defaultMessage: 'Ready to publish',\n }),\n };\n }\n } else {\n if (status === 'draft') {\n return {\n icon: <CheckCircle fill=\"success600\" />,\n text: formatMessage({\n id: 'content-manager.bulk-unpublish.already-unpublished',\n defaultMessage: 'Already Unpublished',\n }),\n textColor: 'success600',\n fontWeight: 'bold',\n };\n } else {\n return {\n icon: <CheckCircle fill=\"success600\" />,\n text: formatMessage({\n id: 'app.utils.ready-to-unpublish-changes',\n defaultMessage: 'Ready to unpublish',\n }),\n textColor: 'success600',\n fontWeight: 'bold',\n };\n }\n }\n };\n\n const { icon, text, textColor = 'success600', fontWeight = 'normal'Line truncated
@@ -0,0 +1,260 @@
import { jsxs, jsx } from 'react/jsx-runtime';
import 'react';
import { useTable, Table } from '@strapi/admin/strapi-admin';
import { Modal, Typography, Box, Status, IconButton, Flex, Tooltip } from '@strapi/design-system';
import { Pencil, CrossCircle, CheckCircle, ArrowsCounterClockwise } from '@strapi/icons';
import { stringify } from 'qs';
import { useIntl } from 'react-intl';
import { Link } from 'react-router-dom';
import { getTranslation } from '../utils/getTranslation.mjs';
import { capitalize } from '../utils/strings.mjs';
const isErrorMessageDescriptor = (object)=>{
return typeof object === 'object' && object !== null && 'id' in object && 'defaultMessage' in object;
};
const EntryValidationText = ({ status = 'draft', validationErrors, action })=>{
const { formatMessage } = useIntl();
/**
* TODO: Should this be extracted an made into a factory to recursively get
* error messages??
*/ const getErrorStr = (key, value)=>{
if (typeof value === 'string') {
return `${key}: ${value}`;
} else if (isErrorMessageDescriptor(value)) {
return `${key}: ${formatMessage(value)}`;
} else if (Array.isArray(value)) {
return value.map((v)=>getErrorStr(key, v)).join(' ');
} else if (typeof value === 'object' && !Array.isArray(value)) {
return Object.entries(value).map(([k, v])=>getErrorStr(k, v)).join(' ');
} else {
/**
* unlikely to happen, but we need to return something
*/ return '';
}
};
if (validationErrors) {
const validationErrorsMessages = Object.entries(validationErrors).map(([key, value])=>{
return getErrorStr(key, value);
}).join(' ');
return /*#__PURE__*/ jsxs(Flex, {
gap: 2,
children: [
/*#__PURE__*/ jsx(CrossCircle, {
fill: "danger600"
}),
/*#__PURE__*/ jsx(Tooltip, {
label: validationErrorsMessages,
children: /*#__PURE__*/ jsx(Typography, {
maxWidth: '30rem',
textColor: "danger600",
variant: "omega",
fontWeight: "semiBold",
ellipsis: true,
children: validationErrorsMessages
})
})
]
});
}
const getStatusMessage = ()=>{
if (action === 'bulk-publish') {
if (status === 'published') {
return {
icon: /*#__PURE__*/ jsx(CheckCircle, {
fill: "success600"
}),
text: formatMessage({
id: 'content-manager.bulk-publish.already-published',
defaultMessage: 'Already Published'
}),
textColor: 'success600',
fontWeight: 'bold'
};
} else if (status === 'modified') {
return {
icon: /*#__PURE__*/ jsx(ArrowsCounterClockwise, {
fill: "alternative600"
}),
text: formatMessage({
id: 'app.utils.ready-to-publish-changes',
defaultMessage: 'Ready to publish changes'
})
};
} else {
return {
icon: /*#__PURE__*/ jsx(CheckCircle, {
fill: "success600"
}),
text: formatMessage({
id: 'app.utils.ready-to-publish',
defaultMessage: 'Ready to publish'
})
};
}
} else {
if (status === 'draft') {
return {
icon: /*#__PURE__*/ jsx(CheckCircle, {
fill: "success600"
}),
text: formatMessage({
id: 'content-manager.bulk-unpublish.already-unpublished',
defaultMessage: 'Already Unpublished'
}),
textColor: 'success600',
fontWeight: 'bold'
};
} else {
return {
icon: /*#__PURE__*/ jsx(CheckCircle, {
fill: "success600"
}),
text: formatMessage({
id: 'app.utils.ready-to-unpublish-changes',
defaultMessage: 'Ready to unpublish'
}),
textColor: 'success600',
fontWeight: 'bold'
};
}
}
};
const { icon, text, textColor = 'success600', fontWeight = 'normal' } = getStatusMessage();
return /*#__PURE__*/ jsxs(Flex, {
gap: 2,
children: [
icon,
/*#__PURE__*/ jsx(Typography, {
textColor: textColor,
fontWeight: fontWeight,
children: text
})
]
});
};
/* -------------------------------------------------------------------------------------------------
* BoldChunk
* -----------------------------------------------------------------------------------------------*/ const BoldChunk = (chunks)=>/*#__PURE__*/ jsx(Typography, {
fontWeight: "bold",
children: chunks
});
const BulkLocaleActionModal = ({ headers, rows, localesMetadata, validationErrors = {}, action })=>{
const { formatMessage } = useIntl();
const selectedRows = useTable('BulkLocaleActionModal', (state)=>state.selectedRows);
const getFormattedCountMessage = ()=>{
const currentStatusByLocale = rows.reduce((acc, { locale, status })=>{
acc[locale] = status;
return acc;
}, {});
const localesWithErrors = Object.keys(validationErrors);
const publishedCount = selectedRows.filter(({ locale })=>currentStatusByLocale[locale] === 'published').length;
const draftCount = selectedRows.filter(({ locale })=>(currentStatusByLocale[locale] === 'draft' || currentStatusByLocale[locale] === 'modified') && !localesWithErrors.includes(locale)).length;
const withErrorsCount = localesWithErrors.length;
const messageId = action === 'bulk-publish' ? 'content-manager.containers.list.selectedEntriesModal.selectedCount.publish' : 'content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish';
const defaultMessage = action === 'bulk-publish' ? '<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action.' : '<b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} already unpublished. <b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} ready to unpublish.';
return formatMessage({
id: messageId,
defaultMessage
}, {
withErrorsCount,
draftCount,
publishedCount,
b: BoldChunk
});
};
return /*#__PURE__*/ jsxs(Modal.Body, {
children: [
/*#__PURE__*/ jsx(Typography, {
children: getFormattedCountMessage()
}),
/*#__PURE__*/ jsx(Box, {
marginTop: 5,
children: /*#__PURE__*/ jsxs(Table.Content, {
children: [
/*#__PURE__*/ jsxs(Table.Head, {
children: [
/*#__PURE__*/ jsx(Table.HeaderCheckboxCell, {}),
headers.map((head)=>/*#__PURE__*/ jsx(Table.HeaderCell, {
...head
}, head.name))
]
}),
/*#__PURE__*/ jsx(Table.Body, {
children: rows.map(({ locale, status }, index)=>{
const error = validationErrors?.[locale] ?? null;
const statusVariant = status === 'draft' ? 'primary' : status === 'published' ? 'success' : 'alternative';
return /*#__PURE__*/ jsxs(Table.Row, {
children: [
/*#__PURE__*/ jsx(Table.CheckboxCell, {
id: locale,
"aria-label": `Select ${locale}`
}),
/*#__PURE__*/ jsx(Table.Cell, {
children: /*#__PURE__*/ jsx(Typography, {
variant: "sigma",
textColor: "neutral600",
children: Array.isArray(localesMetadata) ? localesMetadata.find((localeEntry)=>localeEntry.code === locale)?.name : locale
})
}),
/*#__PURE__*/ jsx(Table.Cell, {
children: /*#__PURE__*/ jsx(Box, {
display: "flex",
children: /*#__PURE__*/ jsx(Status, {
display: "flex",
paddingLeft: "6px",
paddingRight: "6px",
paddingTop: "2px",
paddingBottom: "2px",
size: 'S',
variant: statusVariant,
children: /*#__PURE__*/ jsx(Typography, {
tag: "span",
variant: "pi",
fontWeight: "bold",
children: capitalize(status)
})
})
})
}),
/*#__PURE__*/ jsx(Table.Cell, {
children: /*#__PURE__*/ jsx(EntryValidationText, {
validationErrors: error,
status: status,
action: action
})
}),
/*#__PURE__*/ jsx(Table.Cell, {
children: /*#__PURE__*/ jsx(IconButton, {
tag: Link,
to: {
search: stringify({
plugins: {
i18n: {
locale
}
}
})
},
label: formatMessage({
id: getTranslation('Settings.list.actions.edit'),
defaultMessage: 'Edit {name} locale'
}, {
name: locale
}),
variant: "ghost",
children: /*#__PURE__*/ jsx(Pencil, {})
})
})
]
}, index);
})
})
]
})
})
]
});
};
export { BulkLocaleActionModal };
//# sourceMappingURL=BulkLocaleActionModal.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"BulkLocaleActionModal.mjs","sources":["../../../admin/src/components/BulkLocaleActionModal.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { FormErrors, Table, useTable } from '@strapi/admin/strapi-admin';\nimport { Box, Typography, IconButton, Flex, Tooltip, Status, Modal } from '@strapi/design-system';\nimport { Pencil, CheckCircle, CrossCircle, ArrowsCounterClockwise } from '@strapi/icons';\nimport { stringify } from 'qs';\nimport { type MessageDescriptor, useIntl, PrimitiveType } from 'react-intl';\nimport { Link } from 'react-router-dom';\n\nimport { Locale } from '../../../shared/contracts/locales';\nimport { getTranslation } from '../utils/getTranslation';\nimport { capitalize } from '../utils/strings';\n\nimport { LocaleStatus } from './CMHeaderActions';\n\nimport type { Modules } from '@strapi/types';\n\ntype Status = Modules.Documents.Params.PublicationStatus.Kind | 'modified';\n\n/* -------------------------------------------------------------------------------------------------\n * EntryValidationText\n * -----------------------------------------------------------------------------------------------*/\n\ninterface EntryValidationTextProps {\n status: Status;\n validationErrors: FormErrors[string] | null;\n action: 'bulk-publish' | 'bulk-unpublish';\n}\n\ninterface TranslationMessage extends MessageDescriptor {\n values?: Record<string, PrimitiveType>;\n}\n\nconst isErrorMessageDescriptor = (object?: string | object): object is TranslationMessage => {\n return (\n typeof object === 'object' && object !== null && 'id' in object && 'defaultMessage' in object\n );\n};\n\nconst EntryValidationText = ({\n status = 'draft',\n validationErrors,\n action,\n}: EntryValidationTextProps) => {\n const { formatMessage } = useIntl();\n\n /**\n * TODO: Should this be extracted an made into a factory to recursively get\n * error messages??\n */\n const getErrorStr = (key: string, value?: FormErrors[string]): string => {\n if (typeof value === 'string') {\n return `${key}: ${value}`;\n } else if (isErrorMessageDescriptor(value)) {\n return `${key}: ${formatMessage(value)}`;\n } else if (Array.isArray(value)) {\n return value.map((v) => getErrorStr(key, v)).join(' ');\n } else if (typeof value === 'object' && !Array.isArray(value)) {\n return Object.entries(value)\n .map(([k, v]) => getErrorStr(k, v))\n .join(' ');\n } else {\n /**\n * unlikely to happen, but we need to return something\n */\n return '';\n }\n };\n\n if (validationErrors) {\n const validationErrorsMessages = Object.entries(validationErrors)\n .map(([key, value]) => {\n return getErrorStr(key, value);\n })\n .join(' ');\n\n return (\n <Flex gap={2}>\n <CrossCircle fill=\"danger600\" />\n <Tooltip label={validationErrorsMessages}>\n <Typography\n maxWidth={'30rem'}\n textColor=\"danger600\"\n variant=\"omega\"\n fontWeight=\"semiBold\"\n ellipsis\n >\n {validationErrorsMessages}\n </Typography>\n </Tooltip>\n </Flex>\n );\n }\n\n const getStatusMessage = () => {\n if (action === 'bulk-publish') {\n if (status === 'published') {\n return {\n icon: <CheckCircle fill=\"success600\" />,\n text: formatMessage({\n id: 'content-manager.bulk-publish.already-published',\n defaultMessage: 'Already Published',\n }),\n textColor: 'success600',\n fontWeight: 'bold',\n };\n } else if (status === 'modified') {\n return {\n icon: <ArrowsCounterClockwise fill=\"alternative600\" />,\n text: formatMessage({\n id: 'app.utils.ready-to-publish-changes',\n defaultMessage: 'Ready to publish changes',\n }),\n };\n } else {\n return {\n icon: <CheckCircle fill=\"success600\" />,\n text: formatMessage({\n id: 'app.utils.ready-to-publish',\n defaultMessage: 'Ready to publish',\n }),\n };\n }\n } else {\n if (status === 'draft') {\n return {\n icon: <CheckCircle fill=\"success600\" />,\n text: formatMessage({\n id: 'content-manager.bulk-unpublish.already-unpublished',\n defaultMessage: 'Already Unpublished',\n }),\n textColor: 'success600',\n fontWeight: 'bold',\n };\n } else {\n return {\n icon: <CheckCircle fill=\"success600\" />,\n text: formatMessage({\n id: 'app.utils.ready-to-unpublish-changes',\n defaultMessage: 'Ready to unpublish',\n }),\n textColor: 'success600',\n fontWeight: 'bold',\n };\n }\n }\n };\n\n const { icon, text, textColor = 'success600', fontWeight = 'normalLine truncated
@@ -0,0 +1,721 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var query = require('@reduxjs/toolkit/query');
var strapiAdmin = require('@strapi/admin/strapi-admin');
var strapiAdmin$1 = require('@strapi/content-manager/strapi-admin');
var designSystem = require('@strapi/design-system');
var icons = require('@strapi/icons');
var reactIntl = require('react-intl');
var reactRouterDom = require('react-router-dom');
var styledComponents = require('styled-components');
var useI18n = require('../hooks/useI18n.js');
var locales = require('../services/locales.js');
var relations = require('../services/relations.js');
var clean = require('../utils/clean.js');
var getTranslation = require('../utils/getTranslation.js');
var strings = require('../utils/strings.js');
var BulkLocaleActionModal = require('./BulkLocaleActionModal.js');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
const statusVariants = {
draft: 'secondary',
published: 'success',
modified: 'alternative'
};
const LocaleOption = ({ isDraftAndPublishEnabled, locale, status, entryExists })=>{
const { formatMessage } = reactIntl.useIntl();
if (!entryExists) {
return formatMessage({
id: getTranslation.getTranslation('CMEditViewLocalePicker.locale.create'),
defaultMessage: 'Create <bold>{locale}</bold> locale'
}, {
bold: (locale)=>/*#__PURE__*/ jsxRuntime.jsx("b", {
children: locale
}),
locale: locale.name
});
}
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
width: "100%",
gap: 1,
justifyContent: "space-between",
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
children: locale.name
}),
isDraftAndPublishEnabled ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Status, {
display: "flex",
paddingLeft: "6px",
paddingRight: "6px",
paddingTop: "2px",
paddingBottom: "2px",
size: "S",
variant: statusVariants[status],
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
tag: "span",
variant: "pi",
fontWeight: "bold",
children: strings.capitalize(status)
})
}) : null
]
});
};
const LocalePickerAction = ({ document, meta, model, collectionType, documentId })=>{
const { formatMessage } = reactIntl.useIntl();
const [{ query }, setQuery] = strapiAdmin.useQueryParams();
const { hasI18n, canCreate, canRead } = useI18n.useI18n();
const { data: locales$1 = [] } = locales.useGetLocalesQuery();
const currentDesiredLocale = query.plugins?.i18n?.locale;
const { schema } = strapiAdmin$1.unstable_useDocument({
model,
collectionType,
documentId,
params: {
locale: currentDesiredLocale
}
});
const handleSelect = React__namespace.useCallback((value)=>{
setQuery({
plugins: {
...query.plugins,
i18n: {
locale: value
}
}
});
}, [
query.plugins,
setQuery
]);
React__namespace.useEffect(()=>{
if (!Array.isArray(locales$1) || !hasI18n) {
return;
}
/**
* Handle the case where the current locale query param doesn't exist
* in the list of available locales, so we redirect to the default locale.
*/ const doesLocaleExist = locales$1.find((loc)=>loc.code === currentDesiredLocale);
const defaultLocale = locales$1.find((locale)=>locale.isDefault);
if (!doesLocaleExist && defaultLocale?.code) {
handleSelect(defaultLocale.code);
}
}, [
handleSelect,
hasI18n,
locales$1,
currentDesiredLocale
]);
const currentLocale = Array.isArray(locales$1) ? locales$1.find((locale)=>locale.code === currentDesiredLocale) : undefined;
const allCurrentLocales = [
{
status: getDocumentStatus(document, meta),
locale: currentLocale?.code
},
...document?.localizations ?? []
];
if (!hasI18n || !Array.isArray(locales$1) || locales$1.length === 0) {
return null;
}
const displayedLocales = locales$1.filter((locale)=>{
/**
* If you can read we allow you to see the locale exists
* otherwise the locale is hidden.
*/ return canRead.includes(locale.code);
});
return {
label: formatMessage({
id: getTranslation.getTranslation('Settings.locales.modal.locales.label'),
defaultMessage: 'Locales'
}),
options: displayedLocales.map((locale)=>{
const entryWithLocaleExists = allCurrentLocales.some((doc)=>doc.locale === locale.code);
const currentLocaleDoc = allCurrentLocales.find((doc)=>'locale' in doc ? doc.locale === locale.code : false);
const permissionsToCheck = currentLocaleDoc ? canRead : canCreate;
return {
disabled: !permissionsToCheck.includes(locale.code),
value: locale.code,
label: /*#__PURE__*/ jsxRuntime.jsx(LocaleOption, {
isDraftAndPublishEnabled: !!schema?.options?.draftAndPublish,
locale: locale,
status: currentLocaleDoc?.status,
entryExists: entryWithLocaleExists
}),
startIcon: !entryWithLocaleExists ? /*#__PURE__*/ jsxRuntime.jsx(icons.Plus, {}) : null
};
}),
customizeContent: ()=>currentLocale?.name,
onSelect: handleSelect,
value: currentLocale
};
};
const getDocumentStatus = (document, meta)=>{
const docStatus = document?.status;
const statuses = meta?.availableStatus ?? [];
/**
* Creating an entry
*/ if (!docStatus) {
return 'draft';
}
/**
* We're viewing a draft, but the document could have a published version
*/ if (docStatus === 'draft' && statuses.find((doc)=>doc.publishedAt !== null)) {
return 'published';
}
return docStatus;
};
/* -------------------------------------------------------------------------------------------------
* FillFromAnotherLocaleAction
* -----------------------------------------------------------------------------------------------*/ const FillFromAnotherLocaleAction = ({ documentId, meta, model, collectionType })=>{
const { formatMessage } = reactIntl.useIntl();
const [{ query }] = strapiAdmin.useQueryParams();
const { hasI18n } = useI18n.useI18n();
const currentDesiredLocale = query.plugins?.i18n?.locale;
const [localeSelected, setLocaleSelected] = React__namespace.useState(null);
const setValues = strapiAdmin.useForm('FillFromAnotherLocale', (state)=>state.setValues);
const { getDocument } = strapiAdmin$1.unstable_useDocumentActions();
const { schema, components } = strapiAdmin$1.unstable_useDocument({
model,
documentId,
collectionType,
params: {
locale: currentDesiredLocale
}
});
const { data: locales$1 = [] } = locales.useGetLocalesQuery();
const availableLocales = Array.isArray(locales$1) ? locales$1.filter((locale)=>meta?.availableLocales.some((l)=>l.locale === locale.code)) : [];
const fillFromLocale = (onClose)=>async ()=>{
const response = await getDocument({
collectionType,
model,
documentId,
params: {
locale: localeSelected
}
});
if (!response || !schema) {
return;
}
const { data } = response;
const cleanedData = clean.cleanData(data, schema, components);
setValues(cleanedData);
onClose();
};
if (!hasI18n) {
return null;
}
return {
type: 'icon',
icon: /*#__PURE__*/ jsxRuntime.jsx(icons.Earth, {}),
disabled: availableLocales.length === 0,
label: formatMessage({
id: getTranslation.getTranslation('CMEditViewCopyLocale.copy-text'),
defaultMessage: 'Fill in from another locale'
}),
dialog: {
type: 'dialog',
title: formatMessage({
id: getTranslation.getTranslation('CMEditViewCopyLocale.dialog.title'),
defaultMessage: 'Confirmation'
}),
content: ({ onClose })=>/*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Body, {
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
direction: "column",
gap: 3,
children: [
/*#__PURE__*/ jsxRuntime.jsx(icons.WarningCircle, {
width: "24px",
height: "24px",
fill: "danger600"
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
textAlign: "center",
children: formatMessage({
id: getTranslation.getTranslation('CMEditViewCopyLocale.dialog.body'),
defaultMessage: 'Your current content will be erased and filled by the content of the selected locale:'
})
}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Field.Root, {
width: "100%",
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Label, {
children: formatMessage({
id: getTranslation.getTranslation('CMEditViewCopyLocale.dialog.field.label'),
defaultMessage: 'Locale'
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.SingleSelect, {
value: localeSelected,
placeholder: formatMessage({
id: getTranslation.getTranslation('CMEditViewCopyLocale.dialog.field.placeholder'),
defaultMessage: 'Select one locale...'
}),
// @ts-expect-error – the DS will handle numbers, but we're not allowing the API.
onChange: (value)=>setLocaleSelected(value),
children: availableLocales.map((locale)=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.SingleSelectOption, {
value: locale.code,
children: locale.name
}, locale.code))
})
]
})
]
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Footer, {
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
gap: 2,
width: "100%",
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
flex: "auto",
variant: "tertiary",
onClick: onClose,
children: formatMessage({
id: getTranslation.getTranslation('CMEditViewCopyLocale.cancel-text'),
defaultMessage: 'No, cancel'
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
flex: "auto",
variant: "success",
onClick: fillFromLocale(onClose),
children: formatMessage({
id: getTranslation.getTranslation('CMEditViewCopyLocale.submit-text'),
defaultMessage: 'Yes, fill in'
})
})
]
})
})
]
})
}
};
};
/* -------------------------------------------------------------------------------------------------
* DeleteLocaleAction
* -----------------------------------------------------------------------------------------------*/ const DeleteLocaleAction = ({ document, documentId, model, collectionType })=>{
const { formatMessage } = reactIntl.useIntl();
const navigate = reactRouterDom.useNavigate();
const { toggleNotification } = strapiAdmin.useNotification();
const { delete: deleteAction, isLoading } = strapiAdmin$1.unstable_useDocumentActions();
const { hasI18n, canDelete } = useI18n.useI18n();
// Get the current locale object, using the URL instead of document so it works while creating
const [{ query }] = strapiAdmin.useQueryParams();
const { data: locales$1 = [] } = locales.useGetLocalesQuery();
const currentDesiredLocale = query.plugins?.i18n?.locale;
const locale = !('error' in locales$1) && locales$1.find((loc)=>loc.code === currentDesiredLocale);
if (!hasI18n) {
return null;
}
return {
disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
position: [
'header',
'table-row'
],
label: formatMessage({
id: getTranslation.getTranslation('actions.delete.label'),
defaultMessage: 'Delete entry ({locale})'
}, {
locale: locale && locale.name
}),
icon: /*#__PURE__*/ jsxRuntime.jsx(StyledTrash, {}),
variant: 'danger',
dialog: {
type: 'dialog',
title: formatMessage({
id: getTranslation.getTranslation('actions.delete.dialog.title'),
defaultMessage: 'Confirmation'
}),
content: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
direction: "column",
gap: 2,
children: [
/*#__PURE__*/ jsxRuntime.jsx(icons.WarningCircle, {
width: "24px",
height: "24px",
fill: "danger600"
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
tag: "p",
variant: "omega",
textAlign: "center",
children: formatMessage({
id: getTranslation.getTranslation('actions.delete.dialog.body'),
defaultMessage: 'Are you sure?'
})
})
]
}),
loading: isLoading,
onConfirm: async ()=>{
const unableToDelete = // We are unable to delete a collection type without a document ID
// & unable to delete generally if there is no document locale
collectionType !== 'single-types' && !documentId || !document?.locale;
if (unableToDelete) {
console.error("You're trying to delete a document without an id or locale, this is likely a bug with Strapi. Please open an issue.");
toggleNotification({
message: formatMessage({
id: getTranslation.getTranslation('actions.delete.error'),
defaultMessage: 'An error occurred while trying to delete the document locale.'
}),
type: 'danger'
});
return;
}
const res = await deleteAction({
documentId,
model,
collectionType,
params: {
locale: document.locale
}
});
if (!('error' in res)) {
navigate({
pathname: `../${collectionType}/${model}`
}, {
replace: true
});
}
}
}
};
};
/* -------------------------------------------------------------------------------------------------
* BulkLocaleAction
*
* This component is used to handle bulk publish and unpublish actions on locales.
* -----------------------------------------------------------------------------------------------*/ const BulkLocaleAction = ({ document, documentId, model, collectionType, action })=>{
const locale = document?.locale ?? null;
const [{ query: query$1 }] = strapiAdmin.useQueryParams();
const params = React__namespace.useMemo(()=>strapiAdmin$1.buildValidParams(query$1), [
query$1
]);
const isOnPublishedTab = query$1.status === 'published';
const { formatMessage } = reactIntl.useIntl();
const { hasI18n, canPublish } = useI18n.useI18n();
const { toggleNotification } = strapiAdmin.useNotification();
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
const [selectedRows, setSelectedRows] = React__namespace.useState([]);
const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React__namespace.useState(false);
const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = strapiAdmin$1.unstable_useDocumentActions();
const { schema, validate } = strapiAdmin$1.unstable_useDocument({
model,
collectionType,
documentId,
params: {
locale
}
}, {
// No need to fetch the document, the data is already available in the `document` prop
skip: true
});
const { data: localesMetadata = [] } = locales.useGetLocalesQuery(hasI18n ? undefined : query.skipToken);
const headers = [
{
label: formatMessage({
id: 'global.name',
defaultMessage: 'Name'
}),
name: 'name'
},
{
label: formatMessage({
id: getTranslation.getTranslation('CMEditViewBulkLocale.status'),
defaultMessage: 'Status'
}),
name: 'status'
},
{
label: formatMessage({
id: getTranslation.getTranslation('CMEditViewBulkLocale.publication-status'),
defaultMessage: 'Publication Status'
}),
name: 'publication-status'
}
];
// Extract the rows for the bulk locale publish modal and any validation
// errors per locale
const [rows, validationErrors] = React__namespace.useMemo(()=>{
if (!document) {
return [
[],
{}
];
}
const localizations = document.localizations ?? [];
// Build the rows for the bulk locale publish modal by combining the current
// document with all the available locales from the document meta
const locales = localizations.map((doc)=>{
const { locale, status } = doc;
return {
locale,
status
};
});
// Add the current document locale
locales.unshift({
locale: document.locale,
status: document.status
});
// Build the validation errors for each locale.
const allDocuments = [
document,
...localizations
];
const errors = allDocuments.reduce((errs, document)=>{
if (!document) {
return errs;
}
// Validate each locale entry via the useDocument validate function and store any errors in a dictionary
const validation = validate(document);
if (validation !== null) {
errs[document.locale] = validation;
}
return errs;
}, {});
return [
locales,
errors
];
}, [
document,
validate
]);
const isBulkPublish = action === 'bulk-publish';
const localesForAction = selectedRows.reduce((acc, selectedRow)=>{
const isValidLocale = // Validation errors are irrelevant if we are trying to unpublish
!isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale);
const shouldAddLocale = isBulkPublish ? selectedRow.status !== 'published' && isValidLocale : selectedRow.status !== 'draft' && isValidLocale;
if (shouldAddLocale) {
acc.push(selectedRow.locale);
}
return acc;
}, []);
// TODO skipping this for now as there is a bug with the draft relation count that will be worked on separately
// see https://www.notion.so/strapi/Count-draft-relations-56901b492efb45ab90d42fe975b32bd8?pvs=4
const enableDraftRelationsCount = false;
const { data: draftRelationsCount = 0, isLoading: isDraftRelationsLoading, error: isDraftRelationsError } = relations.useGetManyDraftRelationCountQuery({
model,
documentIds: [
documentId
],
locale: localesForAction
}, {
skip: !enableDraftRelationsCount
});
React__namespace.useEffect(()=>{
if (isDraftRelationsError) {
toggleNotification({
type: 'danger',
message: formatAPIError(isDraftRelationsError)
});
}
}, [
isDraftRelationsError,
toggleNotification,
formatAPIError
]);
if (!schema?.options?.draftAndPublish) {
return null;
}
if (!hasI18n) {
return null;
}
if (!documentId) {
return null;
}
// This document action can be enabled given that draft and publish and i18n are
// enabled and we can publish the current locale.
const publish = async ()=>{
await publishManyAction({
model,
documentIds: [
documentId
],
params: {
...params,
locale: localesForAction
}
});
setSelectedRows([]);
};
const unpublish = async ()=>{
await unpublishManyAction({
model,
documentIds: [
documentId
],
params: {
...params,
locale: localesForAction
}
});
setSelectedRows([]);
};
const handleAction = async ()=>{
if (draftRelationsCount > 0) {
setIsDraftRelationConfirmationOpen(true);
} else if (isBulkPublish) {
await publish();
} else {
await unpublish();
}
};
if (isDraftRelationConfirmationOpen) {
return {
label: formatMessage({
id: 'app.components.ConfirmDialog.title',
defaultMessage: 'Confirmation'
}),
variant: 'danger',
dialog: {
onCancel: ()=>{
setIsDraftRelationConfirmationOpen(false);
},
onConfirm: async ()=>{
await publish();
setIsDraftRelationConfirmationOpen(false);
},
type: 'dialog',
title: formatMessage({
id: getTranslation.getTranslation('actions.publish.dialog.title'),
defaultMessage: 'Confirmation'
}),
content: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
direction: "column",
alignItems: "center",
gap: 2,
children: [
/*#__PURE__*/ jsxRuntime.jsx(icons.WarningCircle, {
width: "2.4rem",
height: "2.4rem",
fill: "danger600"
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
textAlign: "center",
children: formatMessage({
id: getTranslation.getTranslation('CMEditViewBulkLocale.draft-relation-warning'),
defaultMessage: 'Some locales are related to draft entries. Publishing them could leave broken links in your app.'
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
textAlign: "center",
children: formatMessage({
id: getTranslation.getTranslation('CMEditViewBulkLocale.continue-confirmation'),
defaultMessage: 'Are you sure you want to continue?'
})
})
]
})
}
};
}
const hasPermission = selectedRows.map(({ locale })=>locale).every((locale)=>canPublish.includes(locale));
return {
label: formatMessage({
id: getTranslation.getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? 'publish' : 'unpublish'}-title`),
defaultMessage: `${isBulkPublish ? 'Publish' : 'Unpublish'} Multiple Locales`
}),
variant: isBulkPublish ? 'secondary' : 'danger',
icon: isBulkPublish ? /*#__PURE__*/ jsxRuntime.jsx(icons.ListPlus, {}) : /*#__PURE__*/ jsxRuntime.jsx(icons.Cross, {}),
disabled: isOnPublishedTab || canPublish.length === 0,
position: [
'panel'
],
dialog: {
type: 'modal',
title: formatMessage({
id: getTranslation.getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? 'publish' : 'unpublish'}-title`),
defaultMessage: `${isBulkPublish ? 'Publish' : 'Unpublish'} Multiple Locales`
}),
content: ()=>{
return /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Table.Root, {
headers: headers,
rows: rows.map((row)=>({
...row,
id: row.locale
})),
selectedRows: selectedRows,
onSelectedRowsChange: (tableSelectedRows)=>setSelectedRows(tableSelectedRows),
children: /*#__PURE__*/ jsxRuntime.jsx(BulkLocaleActionModal.BulkLocaleActionModal, {
validationErrors: validationErrors,
headers: headers,
rows: rows,
localesMetadata: localesMetadata,
action: action ?? 'bulk-publish'
})
});
},
footer: ()=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Footer, {
justifyContent: "flex-end",
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
loading: isDraftRelationsLoading,
disabled: !hasPermission || localesForAction.length === 0,
variant: "default",
onClick: handleAction,
children: formatMessage({
id: isBulkPublish ? 'app.utils.publish' : 'app.utils.unpublish',
defaultMessage: isBulkPublish ? 'Publish' : 'Unpublish'
})
})
})
}
};
};
/* -------------------------------------------------------------------------------------------------
* BulkLocalePublishAction
* -----------------------------------------------------------------------------------------------*/ const BulkLocalePublishAction = (props)=>{
return BulkLocaleAction({
action: 'bulk-publish',
...props
});
};
/* -------------------------------------------------------------------------------------------------
* BulkLocaleUnpublishAction
* -----------------------------------------------------------------------------------------------*/ const BulkLocaleUnpublishAction = (props)=>{
return BulkLocaleAction({
action: 'bulk-unpublish',
...props
});
};
/**
* Because the icon system is completely broken, we have to do
* this to remove the fill from the cog.
*/ const StyledTrash = styledComponents.styled(icons.Trash)`
path {
fill: currentColor;
}
`;
exports.BulkLocalePublishAction = BulkLocalePublishAction;
exports.BulkLocaleUnpublishAction = BulkLocaleUnpublishAction;
exports.DeleteLocaleAction = DeleteLocaleAction;
exports.FillFromAnotherLocaleAction = FillFromAnotherLocaleAction;
exports.LocalePickerAction = LocalePickerAction;
//# sourceMappingURL=CMHeaderActions.js.map
@@ -0,0 +1 @@
{"version":3,"file":"CMHeaderActions.js","sources":["../../../admin/src/components/CMHeaderActions.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { skipToken } from '@reduxjs/toolkit/query';\nimport {\n useNotification,\n useQueryParams,\n Table,\n useAPIErrorHandler,\n FormErrors,\n useForm,\n} from '@strapi/admin/strapi-admin';\nimport {\n type DocumentActionComponent,\n type DocumentActionProps,\n unstable_useDocument as useDocument,\n unstable_useDocumentActions as useDocumentActions,\n buildValidParams,\n HeaderActionProps,\n} from '@strapi/content-manager/strapi-admin';\nimport {\n Flex,\n Status,\n Typography,\n Button,\n Modal,\n Field,\n SingleSelect,\n SingleSelectOption,\n Dialog,\n type StatusVariant,\n} from '@strapi/design-system';\nimport { WarningCircle, ListPlus, Trash, Earth, Cross, Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { useNavigate } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { useI18n } from '../hooks/useI18n';\nimport { useGetLocalesQuery } from '../services/locales';\nimport { useGetManyDraftRelationCountQuery } from '../services/relations';\nimport { cleanData } from '../utils/clean';\nimport { getTranslation } from '../utils/getTranslation';\nimport { capitalize } from '../utils/strings';\n\nimport { BulkLocaleActionModal } from './BulkLocaleActionModal';\n\nimport type { Locale } from '../../../shared/contracts/locales';\nimport type { I18nBaseQuery } from '../types';\nimport type { Modules } from '@strapi/types';\n\n/* -------------------------------------------------------------------------------------------------\n * LocalePickerAction\n * -----------------------------------------------------------------------------------------------*/\n\ninterface LocaleOptionProps {\n isDraftAndPublishEnabled: boolean;\n locale: Locale;\n status: 'draft' | 'published' | 'modified';\n entryExists: boolean;\n}\n\nconst statusVariants: Record<LocaleOptionProps['status'], StatusVariant> = {\n draft: 'secondary',\n published: 'success',\n modified: 'alternative',\n};\n\nconst LocaleOption = ({\n isDraftAndPublishEnabled,\n locale,\n status,\n entryExists,\n}: LocaleOptionProps) => {\n const { formatMessage } = useIntl();\n\n if (!entryExists) {\n return formatMessage(\n {\n id: getTranslation('CMEditViewLocalePicker.locale.create'),\n defaultMessage: 'Create <bold>{locale}</bold> locale',\n },\n {\n bold: (locale: React.ReactNode) => <b>{locale}</b>,\n locale: locale.name,\n }\n );\n }\n\n return (\n <Flex width=\"100%\" gap={1} justifyContent=\"space-between\">\n <Typography>{locale.name}</Typography>\n {isDraftAndPublishEnabled ? (\n <Status\n display=\"flex\"\n paddingLeft=\"6px\"\n paddingRight=\"6px\"\n paddingTop=\"2px\"\n paddingBottom=\"2px\"\n size=\"S\"\n variant={statusVariants[status]}\n >\n <Typography tag=\"span\" variant=\"pi\" fontWeight=\"bold\">\n {capitalize(status)}\n </Typography>\n </Status>\n ) : null}\n </Flex>\n );\n};\n\nconst LocalePickerAction = ({\n document,\n meta,\n model,\n collectionType,\n documentId,\n}: HeaderActionProps) => {\n const { formatMessage } = useIntl();\n const [{ query }, setQuery] = useQueryParams<I18nBaseQuery>();\n const { hasI18n, canCreate, canRead } = useI18n();\n const { data: locales = [] } = useGetLocalesQuery();\n const currentDesiredLocale = query.plugins?.i18n?.locale;\n const { schema } = useDocument({\n model,\n collectionType,\n documentId,\n params: { locale: currentDesiredLocale },\n });\n\n const handleSelect = React.useCallback(\n (value: string) => {\n setQuery({\n plugins: {\n ...query.plugins,\n i18n: {\n locale: value,\n },\n },\n });\n },\n [query.plugins, setQuery]\n );\n\n React.useEffect(() => {\n if (!Array.isArray(locales) || !hasI18n) {\n return;\n }\n /**\n * Handle the case where the current locale query param doesn't exist\n * in the list of available locales, so we redirect to the default locale.\n */\n const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);\n const defaultLocale = locales.find((locale) => locale.isDefault);\n if (!doesLocaleExist && defaultLocale?.code) {\n handleSelect(defaultLocale.code);\n }\n }, [handleSelect, hasI18n, locales, currentDesiredLocale]);\n\n const currentLocale = Array.isArray(locales)\n ? locales.find((locale) => locale.code === currentDesiredLocale)\n : undefined;\n\n const allCurrentLocales = [\n { status: getDocumentStatus(document, meta), locale: currentLocale?.code },\n ...(document?.localizations ?? []),\n ];\n\n if (!hasI18n || !Array.isArray(locales) || locales.length === 0) Line truncated
@@ -0,0 +1,696 @@
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import * as React from 'react';
import { skipToken } from '@reduxjs/toolkit/query';
import { useQueryParams, useForm, useNotification, useAPIErrorHandler, Table } from '@strapi/admin/strapi-admin';
import { unstable_useDocument, unstable_useDocumentActions, buildValidParams } from '@strapi/content-manager/strapi-admin';
import { Dialog, Flex, Typography, Field, SingleSelect, SingleSelectOption, Button, Status, Modal } from '@strapi/design-system';
import { Trash, Plus, Earth, WarningCircle, ListPlus, Cross } from '@strapi/icons';
import { useIntl } from 'react-intl';
import { useNavigate } from 'react-router-dom';
import { styled } from 'styled-components';
import { useI18n } from '../hooks/useI18n.mjs';
import { useGetLocalesQuery } from '../services/locales.mjs';
import { useGetManyDraftRelationCountQuery } from '../services/relations.mjs';
import { cleanData } from '../utils/clean.mjs';
import { getTranslation } from '../utils/getTranslation.mjs';
import { capitalize } from '../utils/strings.mjs';
import { BulkLocaleActionModal } from './BulkLocaleActionModal.mjs';
const statusVariants = {
draft: 'secondary',
published: 'success',
modified: 'alternative'
};
const LocaleOption = ({ isDraftAndPublishEnabled, locale, status, entryExists })=>{
const { formatMessage } = useIntl();
if (!entryExists) {
return formatMessage({
id: getTranslation('CMEditViewLocalePicker.locale.create'),
defaultMessage: 'Create <bold>{locale}</bold> locale'
}, {
bold: (locale)=>/*#__PURE__*/ jsx("b", {
children: locale
}),
locale: locale.name
});
}
return /*#__PURE__*/ jsxs(Flex, {
width: "100%",
gap: 1,
justifyContent: "space-between",
children: [
/*#__PURE__*/ jsx(Typography, {
children: locale.name
}),
isDraftAndPublishEnabled ? /*#__PURE__*/ jsx(Status, {
display: "flex",
paddingLeft: "6px",
paddingRight: "6px",
paddingTop: "2px",
paddingBottom: "2px",
size: "S",
variant: statusVariants[status],
children: /*#__PURE__*/ jsx(Typography, {
tag: "span",
variant: "pi",
fontWeight: "bold",
children: capitalize(status)
})
}) : null
]
});
};
const LocalePickerAction = ({ document, meta, model, collectionType, documentId })=>{
const { formatMessage } = useIntl();
const [{ query }, setQuery] = useQueryParams();
const { hasI18n, canCreate, canRead } = useI18n();
const { data: locales = [] } = useGetLocalesQuery();
const currentDesiredLocale = query.plugins?.i18n?.locale;
const { schema } = unstable_useDocument({
model,
collectionType,
documentId,
params: {
locale: currentDesiredLocale
}
});
const handleSelect = React.useCallback((value)=>{
setQuery({
plugins: {
...query.plugins,
i18n: {
locale: value
}
}
});
}, [
query.plugins,
setQuery
]);
React.useEffect(()=>{
if (!Array.isArray(locales) || !hasI18n) {
return;
}
/**
* Handle the case where the current locale query param doesn't exist
* in the list of available locales, so we redirect to the default locale.
*/ const doesLocaleExist = locales.find((loc)=>loc.code === currentDesiredLocale);
const defaultLocale = locales.find((locale)=>locale.isDefault);
if (!doesLocaleExist && defaultLocale?.code) {
handleSelect(defaultLocale.code);
}
}, [
handleSelect,
hasI18n,
locales,
currentDesiredLocale
]);
const currentLocale = Array.isArray(locales) ? locales.find((locale)=>locale.code === currentDesiredLocale) : undefined;
const allCurrentLocales = [
{
status: getDocumentStatus(document, meta),
locale: currentLocale?.code
},
...document?.localizations ?? []
];
if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
return null;
}
const displayedLocales = locales.filter((locale)=>{
/**
* If you can read we allow you to see the locale exists
* otherwise the locale is hidden.
*/ return canRead.includes(locale.code);
});
return {
label: formatMessage({
id: getTranslation('Settings.locales.modal.locales.label'),
defaultMessage: 'Locales'
}),
options: displayedLocales.map((locale)=>{
const entryWithLocaleExists = allCurrentLocales.some((doc)=>doc.locale === locale.code);
const currentLocaleDoc = allCurrentLocales.find((doc)=>'locale' in doc ? doc.locale === locale.code : false);
const permissionsToCheck = currentLocaleDoc ? canRead : canCreate;
return {
disabled: !permissionsToCheck.includes(locale.code),
value: locale.code,
label: /*#__PURE__*/ jsx(LocaleOption, {
isDraftAndPublishEnabled: !!schema?.options?.draftAndPublish,
locale: locale,
status: currentLocaleDoc?.status,
entryExists: entryWithLocaleExists
}),
startIcon: !entryWithLocaleExists ? /*#__PURE__*/ jsx(Plus, {}) : null
};
}),
customizeContent: ()=>currentLocale?.name,
onSelect: handleSelect,
value: currentLocale
};
};
const getDocumentStatus = (document, meta)=>{
const docStatus = document?.status;
const statuses = meta?.availableStatus ?? [];
/**
* Creating an entry
*/ if (!docStatus) {
return 'draft';
}
/**
* We're viewing a draft, but the document could have a published version
*/ if (docStatus === 'draft' && statuses.find((doc)=>doc.publishedAt !== null)) {
return 'published';
}
return docStatus;
};
/* -------------------------------------------------------------------------------------------------
* FillFromAnotherLocaleAction
* -----------------------------------------------------------------------------------------------*/ const FillFromAnotherLocaleAction = ({ documentId, meta, model, collectionType })=>{
const { formatMessage } = useIntl();
const [{ query }] = useQueryParams();
const { hasI18n } = useI18n();
const currentDesiredLocale = query.plugins?.i18n?.locale;
const [localeSelected, setLocaleSelected] = React.useState(null);
const setValues = useForm('FillFromAnotherLocale', (state)=>state.setValues);
const { getDocument } = unstable_useDocumentActions();
const { schema, components } = unstable_useDocument({
model,
documentId,
collectionType,
params: {
locale: currentDesiredLocale
}
});
const { data: locales = [] } = useGetLocalesQuery();
const availableLocales = Array.isArray(locales) ? locales.filter((locale)=>meta?.availableLocales.some((l)=>l.locale === locale.code)) : [];
const fillFromLocale = (onClose)=>async ()=>{
const response = await getDocument({
collectionType,
model,
documentId,
params: {
locale: localeSelected
}
});
if (!response || !schema) {
return;
}
const { data } = response;
const cleanedData = cleanData(data, schema, components);
setValues(cleanedData);
onClose();
};
if (!hasI18n) {
return null;
}
return {
type: 'icon',
icon: /*#__PURE__*/ jsx(Earth, {}),
disabled: availableLocales.length === 0,
label: formatMessage({
id: getTranslation('CMEditViewCopyLocale.copy-text'),
defaultMessage: 'Fill in from another locale'
}),
dialog: {
type: 'dialog',
title: formatMessage({
id: getTranslation('CMEditViewCopyLocale.dialog.title'),
defaultMessage: 'Confirmation'
}),
content: ({ onClose })=>/*#__PURE__*/ jsxs(Fragment, {
children: [
/*#__PURE__*/ jsx(Dialog.Body, {
children: /*#__PURE__*/ jsxs(Flex, {
direction: "column",
gap: 3,
children: [
/*#__PURE__*/ jsx(WarningCircle, {
width: "24px",
height: "24px",
fill: "danger600"
}),
/*#__PURE__*/ jsx(Typography, {
textAlign: "center",
children: formatMessage({
id: getTranslation('CMEditViewCopyLocale.dialog.body'),
defaultMessage: 'Your current content will be erased and filled by the content of the selected locale:'
})
}),
/*#__PURE__*/ jsxs(Field.Root, {
width: "100%",
children: [
/*#__PURE__*/ jsx(Field.Label, {
children: formatMessage({
id: getTranslation('CMEditViewCopyLocale.dialog.field.label'),
defaultMessage: 'Locale'
})
}),
/*#__PURE__*/ jsx(SingleSelect, {
value: localeSelected,
placeholder: formatMessage({
id: getTranslation('CMEditViewCopyLocale.dialog.field.placeholder'),
defaultMessage: 'Select one locale...'
}),
// @ts-expect-error – the DS will handle numbers, but we're not allowing the API.
onChange: (value)=>setLocaleSelected(value),
children: availableLocales.map((locale)=>/*#__PURE__*/ jsx(SingleSelectOption, {
value: locale.code,
children: locale.name
}, locale.code))
})
]
})
]
})
}),
/*#__PURE__*/ jsx(Dialog.Footer, {
children: /*#__PURE__*/ jsxs(Flex, {
gap: 2,
width: "100%",
children: [
/*#__PURE__*/ jsx(Button, {
flex: "auto",
variant: "tertiary",
onClick: onClose,
children: formatMessage({
id: getTranslation('CMEditViewCopyLocale.cancel-text'),
defaultMessage: 'No, cancel'
})
}),
/*#__PURE__*/ jsx(Button, {
flex: "auto",
variant: "success",
onClick: fillFromLocale(onClose),
children: formatMessage({
id: getTranslation('CMEditViewCopyLocale.submit-text'),
defaultMessage: 'Yes, fill in'
})
})
]
})
})
]
})
}
};
};
/* -------------------------------------------------------------------------------------------------
* DeleteLocaleAction
* -----------------------------------------------------------------------------------------------*/ const DeleteLocaleAction = ({ document, documentId, model, collectionType })=>{
const { formatMessage } = useIntl();
const navigate = useNavigate();
const { toggleNotification } = useNotification();
const { delete: deleteAction, isLoading } = unstable_useDocumentActions();
const { hasI18n, canDelete } = useI18n();
// Get the current locale object, using the URL instead of document so it works while creating
const [{ query }] = useQueryParams();
const { data: locales = [] } = useGetLocalesQuery();
const currentDesiredLocale = query.plugins?.i18n?.locale;
const locale = !('error' in locales) && locales.find((loc)=>loc.code === currentDesiredLocale);
if (!hasI18n) {
return null;
}
return {
disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
position: [
'header',
'table-row'
],
label: formatMessage({
id: getTranslation('actions.delete.label'),
defaultMessage: 'Delete entry ({locale})'
}, {
locale: locale && locale.name
}),
icon: /*#__PURE__*/ jsx(StyledTrash, {}),
variant: 'danger',
dialog: {
type: 'dialog',
title: formatMessage({
id: getTranslation('actions.delete.dialog.title'),
defaultMessage: 'Confirmation'
}),
content: /*#__PURE__*/ jsxs(Flex, {
direction: "column",
gap: 2,
children: [
/*#__PURE__*/ jsx(WarningCircle, {
width: "24px",
height: "24px",
fill: "danger600"
}),
/*#__PURE__*/ jsx(Typography, {
tag: "p",
variant: "omega",
textAlign: "center",
children: formatMessage({
id: getTranslation('actions.delete.dialog.body'),
defaultMessage: 'Are you sure?'
})
})
]
}),
loading: isLoading,
onConfirm: async ()=>{
const unableToDelete = // We are unable to delete a collection type without a document ID
// & unable to delete generally if there is no document locale
collectionType !== 'single-types' && !documentId || !document?.locale;
if (unableToDelete) {
console.error("You're trying to delete a document without an id or locale, this is likely a bug with Strapi. Please open an issue.");
toggleNotification({
message: formatMessage({
id: getTranslation('actions.delete.error'),
defaultMessage: 'An error occurred while trying to delete the document locale.'
}),
type: 'danger'
});
return;
}
const res = await deleteAction({
documentId,
model,
collectionType,
params: {
locale: document.locale
}
});
if (!('error' in res)) {
navigate({
pathname: `../${collectionType}/${model}`
}, {
replace: true
});
}
}
}
};
};
/* -------------------------------------------------------------------------------------------------
* BulkLocaleAction
*
* This component is used to handle bulk publish and unpublish actions on locales.
* -----------------------------------------------------------------------------------------------*/ const BulkLocaleAction = ({ document, documentId, model, collectionType, action })=>{
const locale = document?.locale ?? null;
const [{ query }] = useQueryParams();
const params = React.useMemo(()=>buildValidParams(query), [
query
]);
const isOnPublishedTab = query.status === 'published';
const { formatMessage } = useIntl();
const { hasI18n, canPublish } = useI18n();
const { toggleNotification } = useNotification();
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
const [selectedRows, setSelectedRows] = React.useState([]);
const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
const { schema, validate } = unstable_useDocument({
model,
collectionType,
documentId,
params: {
locale
}
}, {
// No need to fetch the document, the data is already available in the `document` prop
skip: true
});
const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? undefined : skipToken);
const headers = [
{
label: formatMessage({
id: 'global.name',
defaultMessage: 'Name'
}),
name: 'name'
},
{
label: formatMessage({
id: getTranslation('CMEditViewBulkLocale.status'),
defaultMessage: 'Status'
}),
name: 'status'
},
{
label: formatMessage({
id: getTranslation('CMEditViewBulkLocale.publication-status'),
defaultMessage: 'Publication Status'
}),
name: 'publication-status'
}
];
// Extract the rows for the bulk locale publish modal and any validation
// errors per locale
const [rows, validationErrors] = React.useMemo(()=>{
if (!document) {
return [
[],
{}
];
}
const localizations = document.localizations ?? [];
// Build the rows for the bulk locale publish modal by combining the current
// document with all the available locales from the document meta
const locales = localizations.map((doc)=>{
const { locale, status } = doc;
return {
locale,
status
};
});
// Add the current document locale
locales.unshift({
locale: document.locale,
status: document.status
});
// Build the validation errors for each locale.
const allDocuments = [
document,
...localizations
];
const errors = allDocuments.reduce((errs, document)=>{
if (!document) {
return errs;
}
// Validate each locale entry via the useDocument validate function and store any errors in a dictionary
const validation = validate(document);
if (validation !== null) {
errs[document.locale] = validation;
}
return errs;
}, {});
return [
locales,
errors
];
}, [
document,
validate
]);
const isBulkPublish = action === 'bulk-publish';
const localesForAction = selectedRows.reduce((acc, selectedRow)=>{
const isValidLocale = // Validation errors are irrelevant if we are trying to unpublish
!isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale);
const shouldAddLocale = isBulkPublish ? selectedRow.status !== 'published' && isValidLocale : selectedRow.status !== 'draft' && isValidLocale;
if (shouldAddLocale) {
acc.push(selectedRow.locale);
}
return acc;
}, []);
// TODO skipping this for now as there is a bug with the draft relation count that will be worked on separately
// see https://www.notion.so/strapi/Count-draft-relations-56901b492efb45ab90d42fe975b32bd8?pvs=4
const enableDraftRelationsCount = false;
const { data: draftRelationsCount = 0, isLoading: isDraftRelationsLoading, error: isDraftRelationsError } = useGetManyDraftRelationCountQuery({
model,
documentIds: [
documentId
],
locale: localesForAction
}, {
skip: !enableDraftRelationsCount
});
React.useEffect(()=>{
if (isDraftRelationsError) {
toggleNotification({
type: 'danger',
message: formatAPIError(isDraftRelationsError)
});
}
}, [
isDraftRelationsError,
toggleNotification,
formatAPIError
]);
if (!schema?.options?.draftAndPublish) {
return null;
}
if (!hasI18n) {
return null;
}
if (!documentId) {
return null;
}
// This document action can be enabled given that draft and publish and i18n are
// enabled and we can publish the current locale.
const publish = async ()=>{
await publishManyAction({
model,
documentIds: [
documentId
],
params: {
...params,
locale: localesForAction
}
});
setSelectedRows([]);
};
const unpublish = async ()=>{
await unpublishManyAction({
model,
documentIds: [
documentId
],
params: {
...params,
locale: localesForAction
}
});
setSelectedRows([]);
};
const handleAction = async ()=>{
if (draftRelationsCount > 0) {
setIsDraftRelationConfirmationOpen(true);
} else if (isBulkPublish) {
await publish();
} else {
await unpublish();
}
};
if (isDraftRelationConfirmationOpen) {
return {
label: formatMessage({
id: 'app.components.ConfirmDialog.title',
defaultMessage: 'Confirmation'
}),
variant: 'danger',
dialog: {
onCancel: ()=>{
setIsDraftRelationConfirmationOpen(false);
},
onConfirm: async ()=>{
await publish();
setIsDraftRelationConfirmationOpen(false);
},
type: 'dialog',
title: formatMessage({
id: getTranslation('actions.publish.dialog.title'),
defaultMessage: 'Confirmation'
}),
content: /*#__PURE__*/ jsxs(Flex, {
direction: "column",
alignItems: "center",
gap: 2,
children: [
/*#__PURE__*/ jsx(WarningCircle, {
width: "2.4rem",
height: "2.4rem",
fill: "danger600"
}),
/*#__PURE__*/ jsx(Typography, {
textAlign: "center",
children: formatMessage({
id: getTranslation('CMEditViewBulkLocale.draft-relation-warning'),
defaultMessage: 'Some locales are related to draft entries. Publishing them could leave broken links in your app.'
})
}),
/*#__PURE__*/ jsx(Typography, {
textAlign: "center",
children: formatMessage({
id: getTranslation('CMEditViewBulkLocale.continue-confirmation'),
defaultMessage: 'Are you sure you want to continue?'
})
})
]
})
}
};
}
const hasPermission = selectedRows.map(({ locale })=>locale).every((locale)=>canPublish.includes(locale));
return {
label: formatMessage({
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? 'publish' : 'unpublish'}-title`),
defaultMessage: `${isBulkPublish ? 'Publish' : 'Unpublish'} Multiple Locales`
}),
variant: isBulkPublish ? 'secondary' : 'danger',
icon: isBulkPublish ? /*#__PURE__*/ jsx(ListPlus, {}) : /*#__PURE__*/ jsx(Cross, {}),
disabled: isOnPublishedTab || canPublish.length === 0,
position: [
'panel'
],
dialog: {
type: 'modal',
title: formatMessage({
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? 'publish' : 'unpublish'}-title`),
defaultMessage: `${isBulkPublish ? 'Publish' : 'Unpublish'} Multiple Locales`
}),
content: ()=>{
return /*#__PURE__*/ jsx(Table.Root, {
headers: headers,
rows: rows.map((row)=>({
...row,
id: row.locale
})),
selectedRows: selectedRows,
onSelectedRowsChange: (tableSelectedRows)=>setSelectedRows(tableSelectedRows),
children: /*#__PURE__*/ jsx(BulkLocaleActionModal, {
validationErrors: validationErrors,
headers: headers,
rows: rows,
localesMetadata: localesMetadata,
action: action ?? 'bulk-publish'
})
});
},
footer: ()=>/*#__PURE__*/ jsx(Modal.Footer, {
justifyContent: "flex-end",
children: /*#__PURE__*/ jsx(Button, {
loading: isDraftRelationsLoading,
disabled: !hasPermission || localesForAction.length === 0,
variant: "default",
onClick: handleAction,
children: formatMessage({
id: isBulkPublish ? 'app.utils.publish' : 'app.utils.unpublish',
defaultMessage: isBulkPublish ? 'Publish' : 'Unpublish'
})
})
})
}
};
};
/* -------------------------------------------------------------------------------------------------
* BulkLocalePublishAction
* -----------------------------------------------------------------------------------------------*/ const BulkLocalePublishAction = (props)=>{
return BulkLocaleAction({
action: 'bulk-publish',
...props
});
};
/* -------------------------------------------------------------------------------------------------
* BulkLocaleUnpublishAction
* -----------------------------------------------------------------------------------------------*/ const BulkLocaleUnpublishAction = (props)=>{
return BulkLocaleAction({
action: 'bulk-unpublish',
...props
});
};
/**
* Because the icon system is completely broken, we have to do
* this to remove the fill from the cog.
*/ const StyledTrash = styled(Trash)`
path {
fill: currentColor;
}
`;
export { BulkLocalePublishAction, BulkLocaleUnpublishAction, DeleteLocaleAction, FillFromAnotherLocaleAction, LocalePickerAction };
//# sourceMappingURL=CMHeaderActions.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"CMHeaderActions.mjs","sources":["../../../admin/src/components/CMHeaderActions.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { skipToken } from '@reduxjs/toolkit/query';\nimport {\n useNotification,\n useQueryParams,\n Table,\n useAPIErrorHandler,\n FormErrors,\n useForm,\n} from '@strapi/admin/strapi-admin';\nimport {\n type DocumentActionComponent,\n type DocumentActionProps,\n unstable_useDocument as useDocument,\n unstable_useDocumentActions as useDocumentActions,\n buildValidParams,\n HeaderActionProps,\n} from '@strapi/content-manager/strapi-admin';\nimport {\n Flex,\n Status,\n Typography,\n Button,\n Modal,\n Field,\n SingleSelect,\n SingleSelectOption,\n Dialog,\n type StatusVariant,\n} from '@strapi/design-system';\nimport { WarningCircle, ListPlus, Trash, Earth, Cross, Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { useNavigate } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { useI18n } from '../hooks/useI18n';\nimport { useGetLocalesQuery } from '../services/locales';\nimport { useGetManyDraftRelationCountQuery } from '../services/relations';\nimport { cleanData } from '../utils/clean';\nimport { getTranslation } from '../utils/getTranslation';\nimport { capitalize } from '../utils/strings';\n\nimport { BulkLocaleActionModal } from './BulkLocaleActionModal';\n\nimport type { Locale } from '../../../shared/contracts/locales';\nimport type { I18nBaseQuery } from '../types';\nimport type { Modules } from '@strapi/types';\n\n/* -------------------------------------------------------------------------------------------------\n * LocalePickerAction\n * -----------------------------------------------------------------------------------------------*/\n\ninterface LocaleOptionProps {\n isDraftAndPublishEnabled: boolean;\n locale: Locale;\n status: 'draft' | 'published' | 'modified';\n entryExists: boolean;\n}\n\nconst statusVariants: Record<LocaleOptionProps['status'], StatusVariant> = {\n draft: 'secondary',\n published: 'success',\n modified: 'alternative',\n};\n\nconst LocaleOption = ({\n isDraftAndPublishEnabled,\n locale,\n status,\n entryExists,\n}: LocaleOptionProps) => {\n const { formatMessage } = useIntl();\n\n if (!entryExists) {\n return formatMessage(\n {\n id: getTranslation('CMEditViewLocalePicker.locale.create'),\n defaultMessage: 'Create <bold>{locale}</bold> locale',\n },\n {\n bold: (locale: React.ReactNode) => <b>{locale}</b>,\n locale: locale.name,\n }\n );\n }\n\n return (\n <Flex width=\"100%\" gap={1} justifyContent=\"space-between\">\n <Typography>{locale.name}</Typography>\n {isDraftAndPublishEnabled ? (\n <Status\n display=\"flex\"\n paddingLeft=\"6px\"\n paddingRight=\"6px\"\n paddingTop=\"2px\"\n paddingBottom=\"2px\"\n size=\"S\"\n variant={statusVariants[status]}\n >\n <Typography tag=\"span\" variant=\"pi\" fontWeight=\"bold\">\n {capitalize(status)}\n </Typography>\n </Status>\n ) : null}\n </Flex>\n );\n};\n\nconst LocalePickerAction = ({\n document,\n meta,\n model,\n collectionType,\n documentId,\n}: HeaderActionProps) => {\n const { formatMessage } = useIntl();\n const [{ query }, setQuery] = useQueryParams<I18nBaseQuery>();\n const { hasI18n, canCreate, canRead } = useI18n();\n const { data: locales = [] } = useGetLocalesQuery();\n const currentDesiredLocale = query.plugins?.i18n?.locale;\n const { schema } = useDocument({\n model,\n collectionType,\n documentId,\n params: { locale: currentDesiredLocale },\n });\n\n const handleSelect = React.useCallback(\n (value: string) => {\n setQuery({\n plugins: {\n ...query.plugins,\n i18n: {\n locale: value,\n },\n },\n });\n },\n [query.plugins, setQuery]\n );\n\n React.useEffect(() => {\n if (!Array.isArray(locales) || !hasI18n) {\n return;\n }\n /**\n * Handle the case where the current locale query param doesn't exist\n * in the list of available locales, so we redirect to the default locale.\n */\n const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);\n const defaultLocale = locales.find((locale) => locale.isDefault);\n if (!doesLocaleExist && defaultLocale?.code) {\n handleSelect(defaultLocale.code);\n }\n }, [handleSelect, hasI18n, locales, currentDesiredLocale]);\n\n const currentLocale = Array.isArray(locales)\n ? locales.find((locale) => locale.code === currentDesiredLocale)\n : undefined;\n\n const allCurrentLocales = [\n { status: getDocumentStatus(document, meta), locale: currentLocale?.code },\n ...(document?.localizations ?? []),\n ];\n\n if (!hasI18n || !Array.isArray(locales) || locales.length === 0)Line truncated
@@ -0,0 +1,69 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
require('react');
var designSystem = require('@strapi/design-system');
var reactIntl = require('react-intl');
var useI18n = require('../hooks/useI18n.js');
var getTranslation = require('../utils/getTranslation.js');
const Emphasis = (chunks)=>{
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
fontWeight: "semiBold",
textColor: "danger500",
children: chunks
});
};
const DeleteModalAdditionalInfo = ()=>{
const { hasI18n } = useI18n.useI18n();
const { formatMessage } = reactIntl.useIntl();
if (!hasI18n) {
return null;
}
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
textColor: "danger500",
children: formatMessage({
id: getTranslation.getTranslation('Settings.list.actions.deleteAdditionalInfos'),
defaultMessage: 'This will delete the active locale versions <em>(from Internationalization)</em>'
}, {
em: Emphasis
})
});
};
const PublishModalAdditionalInfo = ()=>{
const { hasI18n } = useI18n.useI18n();
const { formatMessage } = reactIntl.useIntl();
if (!hasI18n) {
return null;
}
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
textColor: "danger500",
children: formatMessage({
id: getTranslation.getTranslation('Settings.list.actions.publishAdditionalInfos'),
defaultMessage: 'This will publish the active locale versions <em>(from Internationalization)</em>'
}, {
em: Emphasis
})
});
};
const UnpublishModalAdditionalInfo = ()=>{
const { hasI18n } = useI18n.useI18n();
const { formatMessage } = reactIntl.useIntl();
if (!hasI18n) {
return null;
}
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
textColor: "danger500",
children: formatMessage({
id: getTranslation.getTranslation('Settings.list.actions.unpublishAdditionalInfos'),
defaultMessage: 'This will unpublish the active locale versions <em>(from Internationalization)</em>'
}, {
em: Emphasis
})
});
};
exports.DeleteModalAdditionalInfo = DeleteModalAdditionalInfo;
exports.PublishModalAdditionalInfo = PublishModalAdditionalInfo;
exports.UnpublishModalAdditionalInfo = UnpublishModalAdditionalInfo;
//# sourceMappingURL=CMListViewModalsAdditionalInformation.js.map
@@ -0,0 +1 @@
{"version":3,"file":"CMListViewModalsAdditionalInformation.js","sources":["../../../admin/src/components/CMListViewModalsAdditionalInformation.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Typography } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { useI18n } from '../hooks/useI18n';\nimport { getTranslation } from '../utils/getTranslation';\n\nconst Emphasis = (chunks: React.ReactNode) => {\n return (\n <Typography fontWeight=\"semiBold\" textColor=\"danger500\">\n {chunks}\n </Typography>\n );\n};\n\nconst DeleteModalAdditionalInfo = () => {\n const { hasI18n } = useI18n();\n const { formatMessage } = useIntl();\n\n if (!hasI18n) {\n return null;\n }\n\n return (\n <Typography textColor=\"danger500\">\n {formatMessage(\n {\n id: getTranslation('Settings.list.actions.deleteAdditionalInfos'),\n defaultMessage:\n 'This will delete the active locale versions <em>(from Internationalization)</em>',\n },\n {\n em: Emphasis,\n }\n )}\n </Typography>\n );\n};\n\nconst PublishModalAdditionalInfo = () => {\n const { hasI18n } = useI18n();\n const { formatMessage } = useIntl();\n\n if (!hasI18n) {\n return null;\n }\n\n return (\n <Typography textColor=\"danger500\">\n {formatMessage(\n {\n id: getTranslation('Settings.list.actions.publishAdditionalInfos'),\n defaultMessage:\n 'This will publish the active locale versions <em>(from Internationalization)</em>',\n },\n {\n em: Emphasis,\n }\n )}\n </Typography>\n );\n};\n\nconst UnpublishModalAdditionalInfo = () => {\n const { hasI18n } = useI18n();\n const { formatMessage } = useIntl();\n\n if (!hasI18n) {\n return null;\n }\n\n return (\n <Typography textColor=\"danger500\">\n {formatMessage(\n {\n id: getTranslation('Settings.list.actions.unpublishAdditionalInfos'),\n defaultMessage:\n 'This will unpublish the active locale versions <em>(from Internationalization)</em>',\n },\n {\n em: Emphasis,\n }\n )}\n </Typography>\n );\n};\n\nexport { DeleteModalAdditionalInfo, PublishModalAdditionalInfo, UnpublishModalAdditionalInfo };\n"],"names":["Emphasis","chunks","_jsx","Typography","fontWeight","textColor","DeleteModalAdditionalInfo","hasI18n","useI18n","formatMessage","useIntl","id","getTranslation","defaultMessage","em","PublishModalAdditionalInfo","UnpublishModalAdditionalInfo"],"mappings":";;;;;;;;;AAQA,MAAMA,WAAW,CAACC,MAAAA,GAAAA;AAChB,IAAA,qBACEC,cAACC,CAAAA,uBAAAA,EAAAA;QAAWC,UAAW,EAAA,UAAA;QAAWC,SAAU,EAAA,WAAA;AACzCJ,QAAAA,QAAAA,EAAAA;;AAGP,CAAA;AAEA,MAAMK,yBAA4B,GAAA,IAAA;IAChC,MAAM,EAAEC,OAAO,EAAE,GAAGC,eAAAA,EAAAA;IACpB,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,IAAI,CAACH,OAAS,EAAA;QACZ,OAAO,IAAA;AACT;AAEA,IAAA,qBACEL,cAACC,CAAAA,uBAAAA,EAAAA;QAAWE,SAAU,EAAA,WAAA;kBACnBI,aACC,CAAA;AACEE,YAAAA,EAAAA,EAAIC,6BAAe,CAAA,6CAAA,CAAA;YACnBC,cACE,EAAA;SAEJ,EAAA;YACEC,EAAId,EAAAA;AACN,SAAA;;AAIR;AAEA,MAAMe,0BAA6B,GAAA,IAAA;IACjC,MAAM,EAAER,OAAO,EAAE,GAAGC,eAAAA,EAAAA;IACpB,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,IAAI,CAACH,OAAS,EAAA;QACZ,OAAO,IAAA;AACT;AAEA,IAAA,qBACEL,cAACC,CAAAA,uBAAAA,EAAAA;QAAWE,SAAU,EAAA,WAAA;kBACnBI,aACC,CAAA;AACEE,YAAAA,EAAAA,EAAIC,6BAAe,CAAA,8CAAA,CAAA;YACnBC,cACE,EAAA;SAEJ,EAAA;YACEC,EAAId,EAAAA;AACN,SAAA;;AAIR;AAEA,MAAMgB,4BAA+B,GAAA,IAAA;IACnC,MAAM,EAAET,OAAO,EAAE,GAAGC,eAAAA,EAAAA;IACpB,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,IAAI,CAACH,OAAS,EAAA;QACZ,OAAO,IAAA;AACT;AAEA,IAAA,qBACEL,cAACC,CAAAA,uBAAAA,EAAAA;QAAWE,SAAU,EAAA,WAAA;kBACnBI,aACC,CAAA;AACEE,YAAAA,EAAAA,EAAIC,6BAAe,CAAA,gDAAA,CAAA;YACnBC,cACE,EAAA;SAEJ,EAAA;YACEC,EAAId,EAAAA;AACN,SAAA;;AAIR;;;;;;"}
@@ -0,0 +1,65 @@
import { jsx } from 'react/jsx-runtime';
import 'react';
import { Typography } from '@strapi/design-system';
import { useIntl } from 'react-intl';
import { useI18n } from '../hooks/useI18n.mjs';
import { getTranslation } from '../utils/getTranslation.mjs';
const Emphasis = (chunks)=>{
return /*#__PURE__*/ jsx(Typography, {
fontWeight: "semiBold",
textColor: "danger500",
children: chunks
});
};
const DeleteModalAdditionalInfo = ()=>{
const { hasI18n } = useI18n();
const { formatMessage } = useIntl();
if (!hasI18n) {
return null;
}
return /*#__PURE__*/ jsx(Typography, {
textColor: "danger500",
children: formatMessage({
id: getTranslation('Settings.list.actions.deleteAdditionalInfos'),
defaultMessage: 'This will delete the active locale versions <em>(from Internationalization)</em>'
}, {
em: Emphasis
})
});
};
const PublishModalAdditionalInfo = ()=>{
const { hasI18n } = useI18n();
const { formatMessage } = useIntl();
if (!hasI18n) {
return null;
}
return /*#__PURE__*/ jsx(Typography, {
textColor: "danger500",
children: formatMessage({
id: getTranslation('Settings.list.actions.publishAdditionalInfos'),
defaultMessage: 'This will publish the active locale versions <em>(from Internationalization)</em>'
}, {
em: Emphasis
})
});
};
const UnpublishModalAdditionalInfo = ()=>{
const { hasI18n } = useI18n();
const { formatMessage } = useIntl();
if (!hasI18n) {
return null;
}
return /*#__PURE__*/ jsx(Typography, {
textColor: "danger500",
children: formatMessage({
id: getTranslation('Settings.list.actions.unpublishAdditionalInfos'),
defaultMessage: 'This will unpublish the active locale versions <em>(from Internationalization)</em>'
}, {
em: Emphasis
})
});
};
export { DeleteModalAdditionalInfo, PublishModalAdditionalInfo, UnpublishModalAdditionalInfo };
//# sourceMappingURL=CMListViewModalsAdditionalInformation.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"CMListViewModalsAdditionalInformation.mjs","sources":["../../../admin/src/components/CMListViewModalsAdditionalInformation.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Typography } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { useI18n } from '../hooks/useI18n';\nimport { getTranslation } from '../utils/getTranslation';\n\nconst Emphasis = (chunks: React.ReactNode) => {\n return (\n <Typography fontWeight=\"semiBold\" textColor=\"danger500\">\n {chunks}\n </Typography>\n );\n};\n\nconst DeleteModalAdditionalInfo = () => {\n const { hasI18n } = useI18n();\n const { formatMessage } = useIntl();\n\n if (!hasI18n) {\n return null;\n }\n\n return (\n <Typography textColor=\"danger500\">\n {formatMessage(\n {\n id: getTranslation('Settings.list.actions.deleteAdditionalInfos'),\n defaultMessage:\n 'This will delete the active locale versions <em>(from Internationalization)</em>',\n },\n {\n em: Emphasis,\n }\n )}\n </Typography>\n );\n};\n\nconst PublishModalAdditionalInfo = () => {\n const { hasI18n } = useI18n();\n const { formatMessage } = useIntl();\n\n if (!hasI18n) {\n return null;\n }\n\n return (\n <Typography textColor=\"danger500\">\n {formatMessage(\n {\n id: getTranslation('Settings.list.actions.publishAdditionalInfos'),\n defaultMessage:\n 'This will publish the active locale versions <em>(from Internationalization)</em>',\n },\n {\n em: Emphasis,\n }\n )}\n </Typography>\n );\n};\n\nconst UnpublishModalAdditionalInfo = () => {\n const { hasI18n } = useI18n();\n const { formatMessage } = useIntl();\n\n if (!hasI18n) {\n return null;\n }\n\n return (\n <Typography textColor=\"danger500\">\n {formatMessage(\n {\n id: getTranslation('Settings.list.actions.unpublishAdditionalInfos'),\n defaultMessage:\n 'This will unpublish the active locale versions <em>(from Internationalization)</em>',\n },\n {\n em: Emphasis,\n }\n )}\n </Typography>\n );\n};\n\nexport { DeleteModalAdditionalInfo, PublishModalAdditionalInfo, UnpublishModalAdditionalInfo };\n"],"names":["Emphasis","chunks","_jsx","Typography","fontWeight","textColor","DeleteModalAdditionalInfo","hasI18n","useI18n","formatMessage","useIntl","id","getTranslation","defaultMessage","em","PublishModalAdditionalInfo","UnpublishModalAdditionalInfo"],"mappings":";;;;;;;AAQA,MAAMA,WAAW,CAACC,MAAAA,GAAAA;AAChB,IAAA,qBACEC,GAACC,CAAAA,UAAAA,EAAAA;QAAWC,UAAW,EAAA,UAAA;QAAWC,SAAU,EAAA,WAAA;AACzCJ,QAAAA,QAAAA,EAAAA;;AAGP,CAAA;AAEA,MAAMK,yBAA4B,GAAA,IAAA;IAChC,MAAM,EAAEC,OAAO,EAAE,GAAGC,OAAAA,EAAAA;IACpB,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAE1B,IAAA,IAAI,CAACH,OAAS,EAAA;QACZ,OAAO,IAAA;AACT;AAEA,IAAA,qBACEL,GAACC,CAAAA,UAAAA,EAAAA;QAAWE,SAAU,EAAA,WAAA;kBACnBI,aACC,CAAA;AACEE,YAAAA,EAAAA,EAAIC,cAAe,CAAA,6CAAA,CAAA;YACnBC,cACE,EAAA;SAEJ,EAAA;YACEC,EAAId,EAAAA;AACN,SAAA;;AAIR;AAEA,MAAMe,0BAA6B,GAAA,IAAA;IACjC,MAAM,EAAER,OAAO,EAAE,GAAGC,OAAAA,EAAAA;IACpB,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAE1B,IAAA,IAAI,CAACH,OAAS,EAAA;QACZ,OAAO,IAAA;AACT;AAEA,IAAA,qBACEL,GAACC,CAAAA,UAAAA,EAAAA;QAAWE,SAAU,EAAA,WAAA;kBACnBI,aACC,CAAA;AACEE,YAAAA,EAAAA,EAAIC,cAAe,CAAA,8CAAA,CAAA;YACnBC,cACE,EAAA;SAEJ,EAAA;YACEC,EAAId,EAAAA;AACN,SAAA;;AAIR;AAEA,MAAMgB,4BAA+B,GAAA,IAAA;IACnC,MAAM,EAAET,OAAO,EAAE,GAAGC,OAAAA,EAAAA;IACpB,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAE1B,IAAA,IAAI,CAACH,OAAS,EAAA;QACZ,OAAO,IAAA;AACT;AAEA,IAAA,qBACEL,GAACC,CAAAA,UAAAA,EAAAA;QAAWE,SAAU,EAAA,WAAA;kBACnBI,aACC,CAAA;AACEE,YAAAA,EAAAA,EAAIC,cAAe,CAAA,gDAAA,CAAA;YACnBC,cACE,EAAA;SAEJ,EAAA;YACEC,EAAId,EAAAA;AACN,SAAA;;AAIR;;;;"}
@@ -0,0 +1,155 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var designSystem = require('@strapi/design-system');
var icons = require('@strapi/icons');
var reactIntl = require('react-intl');
var styledComponents = require('styled-components');
var getTranslation = require('../utils/getTranslation.js');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
const TextAlignTypography = styledComponents.styled(designSystem.Typography)`
text-align: center;
`;
const CheckboxConfirmation = ({ description, isCreating = false, intlLabel, name, onChange, value })=>{
const { formatMessage } = reactIntl.useIntl();
const [isOpen, setIsOpen] = React__namespace.useState(false);
const handleChange = (value)=>{
if (isCreating || value) {
return onChange({
target: {
name,
value,
type: 'checkbox'
}
});
}
if (!value) {
return setIsOpen(true);
}
return null;
};
const handleConfirm = ()=>{
onChange({
target: {
name,
value: false,
type: 'checkbox'
}
});
};
const label = intlLabel.id ? formatMessage({
id: intlLabel.id,
defaultMessage: intlLabel.defaultMessage
}, {
...intlLabel.values
}) : name;
const hint = description ? formatMessage({
id: description.id,
defaultMessage: description.defaultMessage
}, {
...description.values
}) : '';
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Dialog.Root, {
open: isOpen,
onOpenChange: setIsOpen,
children: [
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Field.Root, {
hint: hint,
name: name,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Checkbox, {
onCheckedChange: handleChange,
checked: value,
children: label
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Hint, {})
]
}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Dialog.Content, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Header, {
children: formatMessage({
id: getTranslation.getTranslation('CheckboxConfirmation.Modal.title'),
defaultMessage: 'Disable localization'
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Body, {
icon: /*#__PURE__*/ jsxRuntime.jsx(icons.WarningCircle, {}),
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
direction: "column",
alignItems: "stretch",
gap: 2,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
justifyContent: "center",
children: /*#__PURE__*/ jsxRuntime.jsx(TextAlignTypography, {
children: formatMessage({
id: getTranslation.getTranslation('CheckboxConfirmation.Modal.content'),
defaultMessage: 'Disabling localization will engender the deletion of all your content but the one associated to your default locale (if existing).'
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
justifyContent: "center",
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
fontWeight: "semiBold",
children: formatMessage({
id: getTranslation.getTranslation('CheckboxConfirmation.Modal.body'),
defaultMessage: 'Do you want to disable it?'
})
})
})
]
})
}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Dialog.Footer, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Cancel, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
variant: "tertiary",
children: formatMessage({
id: 'components.popUpWarning.button.cancel',
defaultMessage: 'No, cancel'
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Action, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
variant: "danger-light",
onClick: handleConfirm,
children: formatMessage({
id: getTranslation.getTranslation('CheckboxConfirmation.Modal.button-confirm'),
defaultMessage: 'Yes, disable'
})
})
})
]
})
]
})
]
});
};
exports.CheckboxConfirmation = CheckboxConfirmation;
//# sourceMappingURL=CheckboxConfirmation.js.map
@@ -0,0 +1 @@
{"version":3,"file":"CheckboxConfirmation.js","sources":["../../../admin/src/components/CheckboxConfirmation.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Button, Checkbox, Dialog, Field, Flex, Typography } from '@strapi/design-system';\nimport { WarningCircle } from '@strapi/icons';\nimport { MessageDescriptor, useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslation } from '../utils/getTranslation';\n\nconst TextAlignTypography = styled(Typography)`\n text-align: center;\n`;\n\ninterface IntlMessage extends MessageDescriptor {\n values: object;\n}\n\ninterface CheckboxConfirmationProps {\n description: IntlMessage;\n intlLabel: IntlMessage;\n isCreating?: boolean;\n name: string;\n onChange: (event: { target: { name: string; value: boolean; type: string } }) => void;\n value: boolean;\n}\n\nconst CheckboxConfirmation = ({\n description,\n isCreating = false,\n intlLabel,\n name,\n onChange,\n value,\n}: CheckboxConfirmationProps) => {\n const { formatMessage } = useIntl();\n const [isOpen, setIsOpen] = React.useState(false);\n\n const handleChange = (value: boolean) => {\n if (isCreating || value) {\n return onChange({ target: { name, value, type: 'checkbox' } });\n }\n\n if (!value) {\n return setIsOpen(true);\n }\n\n return null;\n };\n\n const handleConfirm = () => {\n onChange({ target: { name, value: false, type: 'checkbox' } });\n };\n\n const label = intlLabel.id\n ? formatMessage(\n { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },\n { ...intlLabel.values }\n )\n : name;\n\n const hint = description\n ? formatMessage(\n { id: description.id, defaultMessage: description.defaultMessage },\n { ...description.values }\n )\n : '';\n\n return (\n <Dialog.Root open={isOpen} onOpenChange={setIsOpen}>\n <Field.Root hint={hint} name={name}>\n <Checkbox onCheckedChange={handleChange} checked={value}>\n {label}\n </Checkbox>\n <Field.Hint />\n </Field.Root>\n <Dialog.Content>\n <Dialog.Header>\n {formatMessage({\n id: getTranslation('CheckboxConfirmation.Modal.title'),\n defaultMessage: 'Disable localization',\n })}\n </Dialog.Header>\n <Dialog.Body icon={<WarningCircle />}>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={2}>\n <Flex justifyContent=\"center\">\n <TextAlignTypography>\n {formatMessage({\n id: getTranslation('CheckboxConfirmation.Modal.content'),\n defaultMessage:\n 'Disabling localization will engender the deletion of all your content but the one associated to your default locale (if existing).',\n })}\n </TextAlignTypography>\n </Flex>\n <Flex justifyContent=\"center\">\n <Typography fontWeight=\"semiBold\">\n {formatMessage({\n id: getTranslation('CheckboxConfirmation.Modal.body'),\n defaultMessage: 'Do you want to disable it?',\n })}\n </Typography>\n </Flex>\n </Flex>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Cancel>\n <Button variant=\"tertiary\">\n {formatMessage({\n id: 'components.popUpWarning.button.cancel',\n defaultMessage: 'No, cancel',\n })}\n </Button>\n </Dialog.Cancel>\n <Dialog.Action>\n <Button variant=\"danger-light\" onClick={handleConfirm}>\n {formatMessage({\n id: getTranslation('CheckboxConfirmation.Modal.button-confirm'),\n defaultMessage: 'Yes, disable',\n })}\n </Button>\n </Dialog.Action>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n );\n};\n\nexport { CheckboxConfirmation };\n"],"names":["TextAlignTypography","styled","Typography","CheckboxConfirmation","description","isCreating","intlLabel","name","onChange","value","formatMessage","useIntl","isOpen","setIsOpen","React","useState","handleChange","target","type","handleConfirm","label","id","defaultMessage","values","hint","_jsxs","Dialog","Root","open","onOpenChange","Field","_jsx","Checkbox","onCheckedChange","checked","Hint","Content","Header","getTranslation","Body","icon","WarningCircle","Flex","direction","alignItems","gap","justifyContent","fontWeight","Footer","Cancel","Button","variant","Action","onClick"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,MAAMA,mBAAAA,GAAsBC,uBAAOC,CAAAA,uBAAAA,CAAW;;AAE9C,CAAC;AAeD,MAAMC,oBAAuB,GAAA,CAAC,EAC5BC,WAAW,EACXC,UAAa,GAAA,KAAK,EAClBC,SAAS,EACTC,IAAI,EACJC,QAAQ,EACRC,KAAK,EACqB,GAAA;IAC1B,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAC1B,IAAA,MAAM,CAACC,MAAQC,EAAAA,SAAAA,CAAU,GAAGC,gBAAAALine truncated
@@ -0,0 +1,134 @@
import { jsxs, jsx } from 'react/jsx-runtime';
import * as React from 'react';
import { Typography, Dialog, Field, Checkbox, Flex, Button } from '@strapi/design-system';
import { WarningCircle } from '@strapi/icons';
import { useIntl } from 'react-intl';
import { styled } from 'styled-components';
import { getTranslation } from '../utils/getTranslation.mjs';
const TextAlignTypography = styled(Typography)`
text-align: center;
`;
const CheckboxConfirmation = ({ description, isCreating = false, intlLabel, name, onChange, value })=>{
const { formatMessage } = useIntl();
const [isOpen, setIsOpen] = React.useState(false);
const handleChange = (value)=>{
if (isCreating || value) {
return onChange({
target: {
name,
value,
type: 'checkbox'
}
});
}
if (!value) {
return setIsOpen(true);
}
return null;
};
const handleConfirm = ()=>{
onChange({
target: {
name,
value: false,
type: 'checkbox'
}
});
};
const label = intlLabel.id ? formatMessage({
id: intlLabel.id,
defaultMessage: intlLabel.defaultMessage
}, {
...intlLabel.values
}) : name;
const hint = description ? formatMessage({
id: description.id,
defaultMessage: description.defaultMessage
}, {
...description.values
}) : '';
return /*#__PURE__*/ jsxs(Dialog.Root, {
open: isOpen,
onOpenChange: setIsOpen,
children: [
/*#__PURE__*/ jsxs(Field.Root, {
hint: hint,
name: name,
children: [
/*#__PURE__*/ jsx(Checkbox, {
onCheckedChange: handleChange,
checked: value,
children: label
}),
/*#__PURE__*/ jsx(Field.Hint, {})
]
}),
/*#__PURE__*/ jsxs(Dialog.Content, {
children: [
/*#__PURE__*/ jsx(Dialog.Header, {
children: formatMessage({
id: getTranslation('CheckboxConfirmation.Modal.title'),
defaultMessage: 'Disable localization'
})
}),
/*#__PURE__*/ jsx(Dialog.Body, {
icon: /*#__PURE__*/ jsx(WarningCircle, {}),
children: /*#__PURE__*/ jsxs(Flex, {
direction: "column",
alignItems: "stretch",
gap: 2,
children: [
/*#__PURE__*/ jsx(Flex, {
justifyContent: "center",
children: /*#__PURE__*/ jsx(TextAlignTypography, {
children: formatMessage({
id: getTranslation('CheckboxConfirmation.Modal.content'),
defaultMessage: 'Disabling localization will engender the deletion of all your content but the one associated to your default locale (if existing).'
})
})
}),
/*#__PURE__*/ jsx(Flex, {
justifyContent: "center",
children: /*#__PURE__*/ jsx(Typography, {
fontWeight: "semiBold",
children: formatMessage({
id: getTranslation('CheckboxConfirmation.Modal.body'),
defaultMessage: 'Do you want to disable it?'
})
})
})
]
})
}),
/*#__PURE__*/ jsxs(Dialog.Footer, {
children: [
/*#__PURE__*/ jsx(Dialog.Cancel, {
children: /*#__PURE__*/ jsx(Button, {
variant: "tertiary",
children: formatMessage({
id: 'components.popUpWarning.button.cancel',
defaultMessage: 'No, cancel'
})
})
}),
/*#__PURE__*/ jsx(Dialog.Action, {
children: /*#__PURE__*/ jsx(Button, {
variant: "danger-light",
onClick: handleConfirm,
children: formatMessage({
id: getTranslation('CheckboxConfirmation.Modal.button-confirm'),
defaultMessage: 'Yes, disable'
})
})
})
]
})
]
})
]
});
};
export { CheckboxConfirmation };
//# sourceMappingURL=CheckboxConfirmation.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"CheckboxConfirmation.mjs","sources":["../../../admin/src/components/CheckboxConfirmation.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Button, Checkbox, Dialog, Field, Flex, Typography } from '@strapi/design-system';\nimport { WarningCircle } from '@strapi/icons';\nimport { MessageDescriptor, useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslation } from '../utils/getTranslation';\n\nconst TextAlignTypography = styled(Typography)`\n text-align: center;\n`;\n\ninterface IntlMessage extends MessageDescriptor {\n values: object;\n}\n\ninterface CheckboxConfirmationProps {\n description: IntlMessage;\n intlLabel: IntlMessage;\n isCreating?: boolean;\n name: string;\n onChange: (event: { target: { name: string; value: boolean; type: string } }) => void;\n value: boolean;\n}\n\nconst CheckboxConfirmation = ({\n description,\n isCreating = false,\n intlLabel,\n name,\n onChange,\n value,\n}: CheckboxConfirmationProps) => {\n const { formatMessage } = useIntl();\n const [isOpen, setIsOpen] = React.useState(false);\n\n const handleChange = (value: boolean) => {\n if (isCreating || value) {\n return onChange({ target: { name, value, type: 'checkbox' } });\n }\n\n if (!value) {\n return setIsOpen(true);\n }\n\n return null;\n };\n\n const handleConfirm = () => {\n onChange({ target: { name, value: false, type: 'checkbox' } });\n };\n\n const label = intlLabel.id\n ? formatMessage(\n { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },\n { ...intlLabel.values }\n )\n : name;\n\n const hint = description\n ? formatMessage(\n { id: description.id, defaultMessage: description.defaultMessage },\n { ...description.values }\n )\n : '';\n\n return (\n <Dialog.Root open={isOpen} onOpenChange={setIsOpen}>\n <Field.Root hint={hint} name={name}>\n <Checkbox onCheckedChange={handleChange} checked={value}>\n {label}\n </Checkbox>\n <Field.Hint />\n </Field.Root>\n <Dialog.Content>\n <Dialog.Header>\n {formatMessage({\n id: getTranslation('CheckboxConfirmation.Modal.title'),\n defaultMessage: 'Disable localization',\n })}\n </Dialog.Header>\n <Dialog.Body icon={<WarningCircle />}>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={2}>\n <Flex justifyContent=\"center\">\n <TextAlignTypography>\n {formatMessage({\n id: getTranslation('CheckboxConfirmation.Modal.content'),\n defaultMessage:\n 'Disabling localization will engender the deletion of all your content but the one associated to your default locale (if existing).',\n })}\n </TextAlignTypography>\n </Flex>\n <Flex justifyContent=\"center\">\n <Typography fontWeight=\"semiBold\">\n {formatMessage({\n id: getTranslation('CheckboxConfirmation.Modal.body'),\n defaultMessage: 'Do you want to disable it?',\n })}\n </Typography>\n </Flex>\n </Flex>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Cancel>\n <Button variant=\"tertiary\">\n {formatMessage({\n id: 'components.popUpWarning.button.cancel',\n defaultMessage: 'No, cancel',\n })}\n </Button>\n </Dialog.Cancel>\n <Dialog.Action>\n <Button variant=\"danger-light\" onClick={handleConfirm}>\n {formatMessage({\n id: getTranslation('CheckboxConfirmation.Modal.button-confirm'),\n defaultMessage: 'Yes, disable',\n })}\n </Button>\n </Dialog.Action>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n );\n};\n\nexport { CheckboxConfirmation };\n"],"names":["TextAlignTypography","styled","Typography","CheckboxConfirmation","description","isCreating","intlLabel","name","onChange","value","formatMessage","useIntl","isOpen","setIsOpen","React","useState","handleChange","target","type","handleConfirm","label","id","defaultMessage","values","hint","_jsxs","Dialog","Root","open","onOpenChange","Field","_jsx","Checkbox","onCheckedChange","checked","Hint","Content","Header","getTranslation","Body","icon","WarningCircle","Flex","direction","alignItems","gap","justifyContent","fontWeight","Footer","Cancel","Button","variant","Action","onClick"],"mappings":";;;;;;;;AASA,MAAMA,mBAAAA,GAAsBC,MAAOC,CAAAA,UAAAA,CAAW;;AAE9C,CAAC;AAeD,MAAMC,oBAAuB,GAAA,CAAC,EAC5BC,WAAW,EACXC,UAAa,GAAA,KAAK,EAClBC,SAAS,EACTC,IAAI,EACJC,QAAQ,EACRC,KAAK,EACqB,GAAA;IAC1B,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAC1B,IAAA,MAAM,CAACC,MAAQC,EAAAA,SAAAA,CAAU,GAAGC,KAAAA,CAAMC,QAAQ,CAAC,KAAA,CALine truncated
+395
View File
@@ -0,0 +1,395 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var strapiAdmin = require('@strapi/admin/strapi-admin');
var designSystem = require('@strapi/design-system');
var icons = require('@strapi/icons');
var reactIntl = require('react-intl');
var yup = require('yup');
var locales = require('../services/locales.js');
var baseQuery = require('../utils/baseQuery.js');
var getTranslation = require('../utils/getTranslation.js');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
var yup__namespace = /*#__PURE__*/_interopNamespaceDefault(yup);
const CreateLocale = ({ disabled, variant = 'default' })=>{
const { formatMessage } = reactIntl.useIntl();
const [visible, setVisible] = React__namespace.useState(false);
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Root, {
open: visible,
onOpenChange: setVisible,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Trigger, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
variant: variant,
disabled: disabled,
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Plus, {}),
onClick: ()=>setVisible(true),
size: "S",
children: formatMessage({
id: getTranslation.getTranslation('Settings.list.actions.add'),
defaultMessage: 'Add new locale'
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(CreateModal, {
onClose: ()=>setVisible(false)
})
]
});
};
/* -------------------------------------------------------------------------------------------------
* CreateModal
* -----------------------------------------------------------------------------------------------*/ const LOCALE_SCHEMA = yup__namespace.object().shape({
code: yup__namespace.string().nullable().required({
id: 'Settings.locales.modal.create.code.error',
defaultMessage: 'Please select a locale'
}),
name: yup__namespace.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__namespace.boolean()
});
const initialFormValues = {
code: '',
name: '',
isDefault: false
};
const CreateModal = ({ onClose })=>{
const titleId = designSystem.useId();
const { toggleNotification } = strapiAdmin.useNotification();
const { _unstableFormatAPIError: formatAPIError, _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
const [createLocale] = locales.useCreateLocaleMutation();
const { formatMessage } = reactIntl.useIntl();
const refetchPermissions = strapiAdmin.useAuth('CreateModal', (state)=>state.refetchPermissions);
const handleSubmit = async (values, helpers)=>{
try {
const res = await createLocale(values);
if ('error' in res) {
if (baseQuery.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.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__*/ jsxRuntime.jsx(designSystem.Modal.Content, {
children: /*#__PURE__*/ jsxRuntime.jsxs(strapiAdmin.Form, {
method: "POST",
initialValues: initialFormValues,
validationSchema: LOCALE_SCHEMA,
onSubmit: handleSubmit,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Header, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Title, {
children: formatMessage({
id: getTranslation.getTranslation('Settings.list.actions.add'),
defaultMessage: 'Add new locale'
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Body, {
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Tabs.Root, {
variant: "simple",
defaultValue: "basic",
children: [
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
justifyContent: "space-between",
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
tag: "h2",
variant: "beta",
id: titleId,
children: formatMessage({
id: getTranslation.getTranslation('Settings.locales.modal.title'),
defaultMessage: 'Configuration'
})
}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Tabs.List, {
"aria-labelledby": titleId,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Trigger, {
value: "basic",
children: formatMessage({
id: getTranslation.getTranslation('Settings.locales.modal.base'),
defaultMessage: 'Basic settings'
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Trigger, {
value: "advanced",
children: formatMessage({
id: getTranslation.getTranslation('Settings.locales.modal.advanced'),
defaultMessage: 'Advanced settings'
})
})
]
})
]
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Divider, {}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Box, {
paddingTop: 7,
paddingBottom: 7,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Content, {
value: "basic",
children: /*#__PURE__*/ jsxRuntime.jsx(BaseForm, {})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Content, {
value: "advanced",
children: /*#__PURE__*/ jsxRuntime.jsx(AdvancedForm, {})
})
]
})
]
})
}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Footer, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Close, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
variant: "tertiary",
children: formatMessage({
id: 'app.components.Button.cancel',
defaultMessage: 'Cancel'
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(SubmitButton, {})
]
})
]
})
});
};
/* -------------------------------------------------------------------------------------------------
* SubmitButton
* -----------------------------------------------------------------------------------------------*/ const SubmitButton = ()=>{
const { formatMessage } = reactIntl.useIntl();
const isSubmitting = strapiAdmin.useForm('SubmitButton', (state)=>state.isSubmitting);
const modified = strapiAdmin.useForm('SubmitButton', (state)=>state.modified);
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
type: "submit",
startIcon: /*#__PURE__*/ jsxRuntime.jsx(icons.Check, {}),
disabled: isSubmitting || !modified,
children: formatMessage({
id: 'global.save',
defaultMessage: 'Save'
})
});
};
const BaseForm = ({ mode = 'create' })=>{
const { formatMessage } = reactIntl.useIntl();
const { toggleNotification } = strapiAdmin.useNotification();
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
const { data: defaultLocales, error } = locales.useGetDefaultLocalesQuery();
React__namespace.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.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.getTranslation('Settings.locales.modal.create.name.label.description'),
defaultMessage: 'Locale will be displayed under that name in the administration panel'
},
label: {
id: getTranslation.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__*/ jsxRuntime.jsx(designSystem.Grid.Root, {
gap: 4,
children: translatedForm.map(({ size, ...field })=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
col: size,
direction: "column",
alignItems: "stretch",
children: /*#__PURE__*/ jsxRuntime.jsx(FormRenderer, {
...field
})
}, field.name))
});
};
const AdvancedForm = ({ isDefaultLocale })=>{
const { formatMessage } = reactIntl.useIntl();
const form = [
{
disabled: isDefaultLocale,
hint: {
id: getTranslation.getTranslation('Settings.locales.modal.advanced.setAsDefault.hint'),
defaultMessage: 'One default locale is required, change it by selecting another one'
},
label: {
id: getTranslation.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__*/ jsxRuntime.jsx(designSystem.Grid.Root, {
gap: 4,
children: form.map(({ size, ...field })=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Grid.Item, {
col: size,
direction: "column",
alignItems: "stretch",
children: /*#__PURE__*/ jsxRuntime.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__*/ jsxRuntime.jsx(EnumerationInput, {
...field
});
default:
return /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.InputRenderer, {
...field
});
}
};
const EnumerationInput = ({ disabled, hint, label, name, options, placeholder, required })=>{
const { value, error, onChange } = strapiAdmin.useField(name);
const { data: defaultLocales = [] } = locales.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__*/ jsxRuntime.jsxs(designSystem.Field.Root, {
error: error,
hint: hint,
name: name,
required: required,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Label, {
children: label
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.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__*/ jsxRuntime.jsx(designSystem.SingleSelectOption, {
value: option.value,
children: option.label
}, option.value))
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Error, {}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Hint, {})
]
});
};
exports.AdvancedForm = AdvancedForm;
exports.BaseForm = BaseForm;
exports.CreateLocale = CreateLocale;
exports.LOCALE_SCHEMA = LOCALE_SCHEMA;
exports.SubmitButton = SubmitButton;
//# sourceMappingURL=CreateLocale.js.map
@@ -0,0 +1 @@
{"version":3,"file":"CreateLocale.js","sources":["../../../admin/src/components/CreateLocale.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Form,\n type InputProps,\n InputRenderer,\n useField,\n type FormHelpers,\n useForm,\n useAPIErrorHandler,\n useNotification,\n useAuth,\n} from '@strapi/admin/strapi-admin';\nimport {\n Box,\n Button,\n ButtonProps,\n Divider,\n Field,\n Flex,\n Grid,\n Modal,\n SingleSelect,\n SingleSelectOption,\n Tabs,\n Typography,\n useId,\n} from '@strapi/design-system';\nimport { Check, Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport * as yup from 'yup';\n\nimport { CreateLocale } from '../../../shared/contracts/locales';\nimport { useCreateLocaleMutation, useGetDefaultLocalesQuery } from '../services/locales';\nimport { isBaseQueryError } from '../utils/baseQuery';\nimport { getTranslation } from '../utils/getTranslation';\n\n/* -------------------------------------------------------------------------------------------------\n * CreateLocale\n * -----------------------------------------------------------------------------------------------*/\n\ninterface CreateLocaleProps extends Pick<ButtonProps, 'disabled' | 'variant'> {}\n\nconst CreateLocale = ({ disabled, variant = 'default' }: CreateLocaleProps) => {\n const { formatMessage } = useIntl();\n const [visible, setVisible] = React.useState(false);\n\n return (\n <Modal.Root open={visible} onOpenChange={setVisible}>\n <Modal.Trigger>\n <Button\n variant={variant}\n disabled={disabled}\n startIcon={<Plus />}\n onClick={() => setVisible(true)}\n size=\"S\"\n >\n {formatMessage({\n id: getTranslation('Settings.list.actions.add'),\n defaultMessage: 'Add new locale',\n })}\n </Button>\n </Modal.Trigger>\n <CreateModal onClose={() => setVisible(false)} />\n </Modal.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * CreateModal\n * -----------------------------------------------------------------------------------------------*/\n\nconst LOCALE_SCHEMA = yup.object().shape({\n code: yup.string().nullable().required({\n id: 'Settings.locales.modal.create.code.error',\n defaultMessage: 'Please select a locale',\n }),\n name: yup\n .string()\n .nullable()\n .max(50, {\n id: 'Settings.locales.modal.create.name.error.min',\n defaultMessage: 'The locale display name can only be less than 50 characters.',\n })\n .required({\n id: 'Settings.locales.modal.create.name.error.required',\n defaultMessage: 'Please give the locale a display name',\n }),\n isDefault: yup.boolean(),\n});\n\ntype FormValues = CreateLocale.Request['body'];\n\nconst initialFormValues = {\n code: '',\n name: '',\n isDefault: false,\n} satisfies FormValues;\n\ntype ModalCreateProps = {\n onClose: () => void;\n};\n\nconst CreateModal = ({ onClose }: ModalCreateProps) => {\n const titleId = useId();\n const { toggleNotification } = useNotification();\n const {\n _unstableFormatAPIError: formatAPIError,\n _unstableFormatValidationErrors: formatValidationErrors,\n } = useAPIErrorHandler();\n const [createLocale] = useCreateLocaleMutation();\n const { formatMessage } = useIntl();\n const refetchPermissions = useAuth('CreateModal', (state) => state.refetchPermissions);\n\n const handleSubmit = async (values: FormValues, helpers: FormHelpers<FormValues>) => {\n try {\n const res = await createLocale(values);\n\n if ('error' in res) {\n if (isBaseQueryError(res.error) && res.error.name === 'ValidationError') {\n helpers.setErrors(formatValidationErrors(res.error));\n } else {\n toggleNotification({ type: 'danger', message: formatAPIError(res.error) });\n }\n\n return;\n }\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: getTranslation('Settings.locales.modal.create.success'),\n defaultMessage: 'Created locale',\n }),\n });\n\n refetchPermissions();\n onClose();\n } catch (err) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: 'notification.error',\n defaultMessage: 'An error occurred, please try again',\n }),\n });\n }\n };\n\n return (\n <Modal.Content>\n <Form\n method=\"POST\"\n initialValues={initialFormValues}\n validationSchema={LOCALE_SCHEMA}\n onSubmit={handleSubmit}\n >\n <Modal.Header>\n <Modal.Title>\n {formatMessage({\n id: getTranslation('Settings.list.actions.add'),\n defaultMessage: 'Add new locale',\n })}\n </Modal.Title>\n </Modal.Header>\n <Modal.Body>\n <Tabs.RooLine truncated
+369
View File
@@ -0,0 +1,369 @@
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
@@ -0,0 +1 @@
{"version":3,"file":"CreateLocale.mjs","sources":["../../../admin/src/components/CreateLocale.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Form,\n type InputProps,\n InputRenderer,\n useField,\n type FormHelpers,\n useForm,\n useAPIErrorHandler,\n useNotification,\n useAuth,\n} from '@strapi/admin/strapi-admin';\nimport {\n Box,\n Button,\n ButtonProps,\n Divider,\n Field,\n Flex,\n Grid,\n Modal,\n SingleSelect,\n SingleSelectOption,\n Tabs,\n Typography,\n useId,\n} from '@strapi/design-system';\nimport { Check, Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport * as yup from 'yup';\n\nimport { CreateLocale } from '../../../shared/contracts/locales';\nimport { useCreateLocaleMutation, useGetDefaultLocalesQuery } from '../services/locales';\nimport { isBaseQueryError } from '../utils/baseQuery';\nimport { getTranslation } from '../utils/getTranslation';\n\n/* -------------------------------------------------------------------------------------------------\n * CreateLocale\n * -----------------------------------------------------------------------------------------------*/\n\ninterface CreateLocaleProps extends Pick<ButtonProps, 'disabled' | 'variant'> {}\n\nconst CreateLocale = ({ disabled, variant = 'default' }: CreateLocaleProps) => {\n const { formatMessage } = useIntl();\n const [visible, setVisible] = React.useState(false);\n\n return (\n <Modal.Root open={visible} onOpenChange={setVisible}>\n <Modal.Trigger>\n <Button\n variant={variant}\n disabled={disabled}\n startIcon={<Plus />}\n onClick={() => setVisible(true)}\n size=\"S\"\n >\n {formatMessage({\n id: getTranslation('Settings.list.actions.add'),\n defaultMessage: 'Add new locale',\n })}\n </Button>\n </Modal.Trigger>\n <CreateModal onClose={() => setVisible(false)} />\n </Modal.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * CreateModal\n * -----------------------------------------------------------------------------------------------*/\n\nconst LOCALE_SCHEMA = yup.object().shape({\n code: yup.string().nullable().required({\n id: 'Settings.locales.modal.create.code.error',\n defaultMessage: 'Please select a locale',\n }),\n name: yup\n .string()\n .nullable()\n .max(50, {\n id: 'Settings.locales.modal.create.name.error.min',\n defaultMessage: 'The locale display name can only be less than 50 characters.',\n })\n .required({\n id: 'Settings.locales.modal.create.name.error.required',\n defaultMessage: 'Please give the locale a display name',\n }),\n isDefault: yup.boolean(),\n});\n\ntype FormValues = CreateLocale.Request['body'];\n\nconst initialFormValues = {\n code: '',\n name: '',\n isDefault: false,\n} satisfies FormValues;\n\ntype ModalCreateProps = {\n onClose: () => void;\n};\n\nconst CreateModal = ({ onClose }: ModalCreateProps) => {\n const titleId = useId();\n const { toggleNotification } = useNotification();\n const {\n _unstableFormatAPIError: formatAPIError,\n _unstableFormatValidationErrors: formatValidationErrors,\n } = useAPIErrorHandler();\n const [createLocale] = useCreateLocaleMutation();\n const { formatMessage } = useIntl();\n const refetchPermissions = useAuth('CreateModal', (state) => state.refetchPermissions);\n\n const handleSubmit = async (values: FormValues, helpers: FormHelpers<FormValues>) => {\n try {\n const res = await createLocale(values);\n\n if ('error' in res) {\n if (isBaseQueryError(res.error) && res.error.name === 'ValidationError') {\n helpers.setErrors(formatValidationErrors(res.error));\n } else {\n toggleNotification({ type: 'danger', message: formatAPIError(res.error) });\n }\n\n return;\n }\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: getTranslation('Settings.locales.modal.create.success'),\n defaultMessage: 'Created locale',\n }),\n });\n\n refetchPermissions();\n onClose();\n } catch (err) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: 'notification.error',\n defaultMessage: 'An error occurred, please try again',\n }),\n });\n }\n };\n\n return (\n <Modal.Content>\n <Form\n method=\"POST\"\n initialValues={initialFormValues}\n validationSchema={LOCALE_SCHEMA}\n onSubmit={handleSubmit}\n >\n <Modal.Header>\n <Modal.Title>\n {formatMessage({\n id: getTranslation('Settings.list.actions.add'),\n defaultMessage: 'Add new locale',\n })}\n </Modal.Title>\n </Modal.Header>\n <Modal.Body>\n <Tabs.RoLine truncated
+90
View File
@@ -0,0 +1,90 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var strapiAdmin = require('@strapi/admin/strapi-admin');
var designSystem = require('@strapi/design-system');
var icons = require('@strapi/icons');
var reactIntl = require('react-intl');
var locales = require('../services/locales.js');
var getTranslation = require('../utils/getTranslation.js');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
const DeleteLocale = ({ id, name })=>{
const { formatMessage } = reactIntl.useIntl();
const { toggleNotification } = strapiAdmin.useNotification();
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
const [visible, setVisible] = React__namespace.useState(false);
const [deleteLocale] = locales.useDeleteLocaleMutation();
const handleConfirm = async ()=>{
try {
const res = await deleteLocale(id);
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
return;
}
toggleNotification({
type: 'success',
message: formatMessage({
id: getTranslation.getTranslation('Settings.locales.modal.delete.success'),
defaultMessage: 'Deleted locale'
})
});
setVisible(false);
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage({
id: 'notification.error',
defaultMessage: 'An error occurred, please try again'
})
});
}
};
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Dialog.Root, {
open: visible,
onOpenChange: setVisible,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Trigger, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
onClick: ()=>setVisible(true),
label: formatMessage({
id: getTranslation.getTranslation('Settings.list.actions.delete'),
defaultMessage: 'Delete {name} locale'
}, {
name
}),
variant: "ghost",
children: /*#__PURE__*/ jsxRuntime.jsx(icons.Trash, {})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.ConfirmDialog, {
onConfirm: handleConfirm
})
]
});
};
exports.DeleteLocale = DeleteLocale;
//# sourceMappingURL=DeleteLocale.js.map
@@ -0,0 +1 @@
{"version":3,"file":"DeleteLocale.js","sources":["../../../admin/src/components/DeleteLocale.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { ConfirmDialog, useAPIErrorHandler, useNotification } from '@strapi/admin/strapi-admin';\nimport { Dialog, IconButton } from '@strapi/design-system';\nimport { Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useDeleteLocaleMutation } from '../services/locales';\nimport { getTranslation } from '../utils/getTranslation';\n\nimport type { Locale } from '../../../shared/contracts/locales';\n\n/* -------------------------------------------------------------------------------------------------\n * DeleteLocale\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DeleteLocaleProps extends Locale {}\n\nconst DeleteLocale = ({ id, name }: DeleteLocaleProps) => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n\n const [visible, setVisible] = React.useState(false);\n\n const [deleteLocale] = useDeleteLocaleMutation();\n const handleConfirm = async () => {\n try {\n const res = await deleteLocale(id);\n\n if ('error' in res) {\n toggleNotification({ type: 'danger', message: formatAPIError(res.error) });\n\n return;\n }\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: getTranslation('Settings.locales.modal.delete.success'),\n defaultMessage: 'Deleted locale',\n }),\n });\n\n setVisible(false);\n } catch (err) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: 'notification.error',\n defaultMessage: 'An error occurred, please try again',\n }),\n });\n }\n };\n\n return (\n <Dialog.Root open={visible} onOpenChange={setVisible}>\n <Dialog.Trigger>\n <IconButton\n onClick={() => setVisible(true)}\n label={formatMessage(\n {\n id: getTranslation('Settings.list.actions.delete'),\n defaultMessage: 'Delete {name} locale',\n },\n {\n name,\n }\n )}\n variant=\"ghost\"\n >\n <Trash />\n </IconButton>\n </Dialog.Trigger>\n <ConfirmDialog onConfirm={handleConfirm} />\n </Dialog.Root>\n );\n};\n\nexport { DeleteLocale };\n"],"names":["DeleteLocale","id","name","formatMessage","useIntl","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","visible","setVisible","React","useState","deleteLocale","useDeleteLocaleMutation","handleConfirm","res","type","message","error","getTranslation","defaultMessage","err","_jsxs","Dialog","Root","open","onOpenChange","_jsx","Trigger","IconButton","onClick","label","variant","Trash","ConfirmDialog","onConfirm"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,MAAMA,eAAe,CAAC,EAAEC,EAAE,EAAEC,IAAI,EAAqB,GAAA;IACnD,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;IAC1B,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,2BAAAA,EAAAA;AAC/B,IAAA,MAAM,EAAEC,uBAAAA,EAAyBC,cAAc,EAAE,GAAGC,8BAAAA,EAAAA;AAEpD,IAAA,MAAM,CAACC,OAASC,EAAAA,UAAAA,CAAW,GAAGC,gBAAAA,CAAMC,QAAQ,CAAC,KAAA,CAAA;IAE7C,MAAM,CAACC,aAAa,GAAGC,+BAAAA,EAAAA;AACvB,IAAA,MAAMC,aAAgB,GAAA,UAAA;QACpB,IAAI;YACF,MAAMC,GAAAA,GAAM,MAAMH,YAAab,CAAAA,EAAAA,CAAAA;AAE/B,YAAA,IAAI,WAAWgB,GAAK,EAAA;gBAClBZ,kBAAmB,CAAA;oBAAEa,IAAM,EAAA,QAAA;oBAAUC,OAASX,EAAAA,cAAAA,CAAeS,IAAIG,KAAK;AAAE,iBAAA,CAAA;AAExE,gBAAA;AACF;YAEAf,kBAAmB,CAAA;gBACjBa,IAAM,EAAA,SAAA;AACNC,gBAAAA,OAAAA,EAAShB,aAAc,CAAA;AACrBF,oBAAAA,EAAAA,EAAIoB,6BAAe,CAAA,uCAAA,CAAA;oBACnBC,cAAgB,EAAA;AAClB,iBAAA;AACF,aAAA,CAAA;YAEAX,UAAW,CAAA,KAAA,CAAA;AACb,SAAA,CAAE,OAAOY,GAAK,EAAA;YACZlB,kBAAmB,CAAA;gBACjBa,IAAM,EAAA,QAAA;AACNC,gBAAAA,OAAAA,EAAShB,aAAc,CAAA;oBACrBF,EAAI,EAAA,oBAAA;oBACJqB,cAAgB,EAAA;AAClB,iBAAA;AACF,aAAA,CAAA;AACF;AACF,KAAA;IAEA,qBACEE,eAAA,CAACC,oBAAOC,IAAI,EAAA;QAACC,IAAMjB,EAAAA,OAAAA;QAASkB,YAAcjB,EAAAA,UAAAA;;AACxC,0BAAAkB,cAAA,CAACJ,oBAAOK,OAAO,EAAA;AACb,gBAAA,QAAA,gBAAAD,cAACE,CAAAA,uBAAAA,EAAAA;AACCC,oBAAAA,OAAAA,EAAS,IAAMrB,UAAW,CAAA,IAAA,CAAA;AAC1BsB,oBAAAA,KAAAA,EAAO9B,aACL,CAAA;AACEF,wBAAAA,EAAAA,EAAIoB,6BAAe,CAAA,8BAAA,CAAA;wBACnBC,cAAgB,EAAA;qBAElB,EAAA;AACEpB,wBAAAA;AACF,qBAAA,CAAA;oBAEFgC,OAAQ,EAAA,OAAA;AAER,oBAAA,QAAA,gBAAAL,cAACM,CAAAA,WAAAA,EAAAA,EAAAA;;;0BAGLN,cAACO,CAAAA,yBAAAA,EAAAA;gBAAcC,SAAWrB,EAAAA;;;;AAGhC;;;;"}
@@ -0,0 +1,69 @@
import { jsxs, jsx } from 'react/jsx-runtime';
import * as React from 'react';
import { useNotification, useAPIErrorHandler, ConfirmDialog } from '@strapi/admin/strapi-admin';
import { Dialog, IconButton } from '@strapi/design-system';
import { Trash } from '@strapi/icons';
import { useIntl } from 'react-intl';
import { useDeleteLocaleMutation } from '../services/locales.mjs';
import { getTranslation } from '../utils/getTranslation.mjs';
const DeleteLocale = ({ id, name })=>{
const { formatMessage } = useIntl();
const { toggleNotification } = useNotification();
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
const [visible, setVisible] = React.useState(false);
const [deleteLocale] = useDeleteLocaleMutation();
const handleConfirm = async ()=>{
try {
const res = await deleteLocale(id);
if ('error' in res) {
toggleNotification({
type: 'danger',
message: formatAPIError(res.error)
});
return;
}
toggleNotification({
type: 'success',
message: formatMessage({
id: getTranslation('Settings.locales.modal.delete.success'),
defaultMessage: 'Deleted locale'
})
});
setVisible(false);
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage({
id: 'notification.error',
defaultMessage: 'An error occurred, please try again'
})
});
}
};
return /*#__PURE__*/ jsxs(Dialog.Root, {
open: visible,
onOpenChange: setVisible,
children: [
/*#__PURE__*/ jsx(Dialog.Trigger, {
children: /*#__PURE__*/ jsx(IconButton, {
onClick: ()=>setVisible(true),
label: formatMessage({
id: getTranslation('Settings.list.actions.delete'),
defaultMessage: 'Delete {name} locale'
}, {
name
}),
variant: "ghost",
children: /*#__PURE__*/ jsx(Trash, {})
})
}),
/*#__PURE__*/ jsx(ConfirmDialog, {
onConfirm: handleConfirm
})
]
});
};
export { DeleteLocale };
//# sourceMappingURL=DeleteLocale.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"DeleteLocale.mjs","sources":["../../../admin/src/components/DeleteLocale.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { ConfirmDialog, useAPIErrorHandler, useNotification } from '@strapi/admin/strapi-admin';\nimport { Dialog, IconButton } from '@strapi/design-system';\nimport { Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { useDeleteLocaleMutation } from '../services/locales';\nimport { getTranslation } from '../utils/getTranslation';\n\nimport type { Locale } from '../../../shared/contracts/locales';\n\n/* -------------------------------------------------------------------------------------------------\n * DeleteLocale\n * -----------------------------------------------------------------------------------------------*/\n\ninterface DeleteLocaleProps extends Locale {}\n\nconst DeleteLocale = ({ id, name }: DeleteLocaleProps) => {\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();\n\n const [visible, setVisible] = React.useState(false);\n\n const [deleteLocale] = useDeleteLocaleMutation();\n const handleConfirm = async () => {\n try {\n const res = await deleteLocale(id);\n\n if ('error' in res) {\n toggleNotification({ type: 'danger', message: formatAPIError(res.error) });\n\n return;\n }\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: getTranslation('Settings.locales.modal.delete.success'),\n defaultMessage: 'Deleted locale',\n }),\n });\n\n setVisible(false);\n } catch (err) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: 'notification.error',\n defaultMessage: 'An error occurred, please try again',\n }),\n });\n }\n };\n\n return (\n <Dialog.Root open={visible} onOpenChange={setVisible}>\n <Dialog.Trigger>\n <IconButton\n onClick={() => setVisible(true)}\n label={formatMessage(\n {\n id: getTranslation('Settings.list.actions.delete'),\n defaultMessage: 'Delete {name} locale',\n },\n {\n name,\n }\n )}\n variant=\"ghost\"\n >\n <Trash />\n </IconButton>\n </Dialog.Trigger>\n <ConfirmDialog onConfirm={handleConfirm} />\n </Dialog.Root>\n );\n};\n\nexport { DeleteLocale };\n"],"names":["DeleteLocale","id","name","formatMessage","useIntl","toggleNotification","useNotification","_unstableFormatAPIError","formatAPIError","useAPIErrorHandler","visible","setVisible","React","useState","deleteLocale","useDeleteLocaleMutation","handleConfirm","res","type","message","error","getTranslation","defaultMessage","err","_jsxs","Dialog","Root","open","onOpenChange","_jsx","Trigger","IconButton","onClick","label","variant","Trash","ConfirmDialog","onConfirm"],"mappings":";;;;;;;;;AAkBA,MAAMA,eAAe,CAAC,EAAEC,EAAE,EAAEC,IAAI,EAAqB,GAAA;IACnD,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;IAC1B,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,eAAAA,EAAAA;AAC/B,IAAA,MAAM,EAAEC,uBAAAA,EAAyBC,cAAc,EAAE,GAAGC,kBAAAA,EAAAA;AAEpD,IAAA,MAAM,CAACC,OAASC,EAAAA,UAAAA,CAAW,GAAGC,KAAAA,CAAMC,QAAQ,CAAC,KAAA,CAAA;IAE7C,MAAM,CAACC,aAAa,GAAGC,uBAAAA,EAAAA;AACvB,IAAA,MAAMC,aAAgB,GAAA,UAAA;QACpB,IAAI;YACF,MAAMC,GAAAA,GAAM,MAAMH,YAAab,CAAAA,EAAAA,CAAAA;AAE/B,YAAA,IAAI,WAAWgB,GAAK,EAAA;gBAClBZ,kBAAmB,CAAA;oBAAEa,IAAM,EAAA,QAAA;oBAAUC,OAASX,EAAAA,cAAAA,CAAeS,IAAIG,KAAK;AAAE,iBAAA,CAAA;AAExE,gBAAA;AACF;YAEAf,kBAAmB,CAAA;gBACjBa,IAAM,EAAA,SAAA;AACNC,gBAAAA,OAAAA,EAAShB,aAAc,CAAA;AACrBF,oBAAAA,EAAAA,EAAIoB,cAAe,CAAA,uCAAA,CAAA;oBACnBC,cAAgB,EAAA;AAClB,iBAAA;AACF,aAAA,CAAA;YAEAX,UAAW,CAAA,KAAA,CAAA;AACb,SAAA,CAAE,OAAOY,GAAK,EAAA;YACZlB,kBAAmB,CAAA;gBACjBa,IAAM,EAAA,QAAA;AACNC,gBAAAA,OAAAA,EAAShB,aAAc,CAAA;oBACrBF,EAAI,EAAA,oBAAA;oBACJqB,cAAgB,EAAA;AAClB,iBAAA;AACF,aAAA,CAAA;AACF;AACF,KAAA;IAEA,qBACEE,IAAA,CAACC,OAAOC,IAAI,EAAA;QAACC,IAAMjB,EAAAA,OAAAA;QAASkB,YAAcjB,EAAAA,UAAAA;;AACxC,0BAAAkB,GAAA,CAACJ,OAAOK,OAAO,EAAA;AACb,gBAAA,QAAA,gBAAAD,GAACE,CAAAA,UAAAA,EAAAA;AACCC,oBAAAA,OAAAA,EAAS,IAAMrB,UAAW,CAAA,IAAA,CAAA;AAC1BsB,oBAAAA,KAAAA,EAAO9B,aACL,CAAA;AACEF,wBAAAA,EAAAA,EAAIoB,cAAe,CAAA,8BAAA,CAAA;wBACnBC,cAAgB,EAAA;qBAElB,EAAA;AACEpB,wBAAAA;AACF,qBAAA,CAAA;oBAEFgC,OAAQ,EAAA,OAAA;AAER,oBAAA,QAAA,gBAAAL,GAACM,CAAAA,KAAAA,EAAAA,EAAAA;;;0BAGLN,GAACO,CAAAA,aAAAA,EAAAA;gBAAcC,SAAWrB,EAAAA;;;;AAGhC;;;;"}
+212
View File
@@ -0,0 +1,212 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var strapiAdmin = require('@strapi/admin/strapi-admin');
var designSystem = require('@strapi/design-system');
var icons = require('@strapi/icons');
var reactIntl = require('react-intl');
var locales = require('../services/locales.js');
var baseQuery = require('../utils/baseQuery.js');
var getTranslation = require('../utils/getTranslation.js');
var CreateLocale = require('./CreateLocale.js');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
const EditLocale = (props)=>{
const { formatMessage } = reactIntl.useIntl();
const [visible, setVisible] = React__namespace.useState(false);
return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
onClick: ()=>setVisible(true),
label: formatMessage({
id: getTranslation.getTranslation('Settings.list.actions.edit'),
defaultMessage: 'Edit {name} locale'
}, {
name: props.name
}),
variant: "ghost",
children: /*#__PURE__*/ jsxRuntime.jsx(icons.Pencil, {})
}),
/*#__PURE__*/ jsxRuntime.jsx(EditModal, {
...props,
open: visible,
onOpenChange: setVisible
})
]
});
};
/**
* @internal
* @description Exported to be used when someone clicks on a table row.
*/ const EditModal = ({ id, code, isDefault, name, open, onOpenChange })=>{
const { toggleNotification } = strapiAdmin.useNotification();
const { _unstableFormatAPIError: formatAPIError, _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
const refetchPermissions = strapiAdmin.useAuth('EditModal', (state)=>state.refetchPermissions);
const { formatMessage } = reactIntl.useIntl();
const titleId = designSystem.useId();
const [updateLocale] = locales.useUpdateLocaleMutation();
const handleSubmit = async ({ code: _code, ...data }, helpers)=>{
try {
/**
* We don't need to send the code, because the
* code can never be changed.
*/ const res = await updateLocale({
id,
...data
});
if ('error' in res) {
if (baseQuery.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.getTranslation('Settings.locales.modal.edit.success'),
defaultMessage: 'Updated locale'
})
});
refetchPermissions();
onOpenChange(false);
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage({
id: 'notification.error',
defaultMessage: 'An error occurred, please try again'
})
});
}
};
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Root, {
open: open,
onOpenChange: onOpenChange,
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Content, {
children: /*#__PURE__*/ jsxRuntime.jsxs(strapiAdmin.Form, {
method: "PUT",
onSubmit: handleSubmit,
initialValues: {
code,
name,
isDefault
},
validationSchema: CreateLocale.LOCALE_SCHEMA,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Header, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Title, {
children: formatMessage({
id: getTranslation.getTranslation('Settings.list.actions.edit'),
defaultMessage: 'Edit a locale'
}, {
name
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Body, {
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Tabs.Root, {
variant: "simple",
defaultValue: "basic",
children: [
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
justifyContent: "space-between",
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
tag: "h2",
variant: "beta",
id: titleId,
children: formatMessage({
id: getTranslation.getTranslation('Settings.locales.modal.title'),
defaultMessage: 'Configuration'
})
}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Tabs.List, {
"aria-labelledby": titleId,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Trigger, {
value: "basic",
children: formatMessage({
id: getTranslation.getTranslation('Settings.locales.modal.base'),
defaultMessage: 'Basic settings'
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Trigger, {
value: "advanced",
children: formatMessage({
id: getTranslation.getTranslation('Settings.locales.modal.advanced'),
defaultMessage: 'Advanced settings'
})
})
]
})
]
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Divider, {}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Box, {
paddingTop: 7,
paddingBottom: 7,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Content, {
value: "basic",
children: /*#__PURE__*/ jsxRuntime.jsx(CreateLocale.BaseForm, {
mode: "edit"
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Tabs.Content, {
value: "advanced",
children: /*#__PURE__*/ jsxRuntime.jsx(CreateLocale.AdvancedForm, {
isDefaultLocale: isDefault
})
})
]
})
]
})
}),
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Footer, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Close, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
variant: "tertiary",
children: formatMessage({
id: 'app.components.Button.cancel',
defaultMessage: 'Cancel'
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(CreateLocale.SubmitButton, {})
]
})
]
})
})
});
};
exports.EditLocale = EditLocale;
exports.EditModal = EditModal;
//# sourceMappingURL=EditLocale.js.map
@@ -0,0 +1 @@
{"version":3,"file":"EditLocale.js","sources":["../../../admin/src/components/EditLocale.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n useNotification,\n useAPIErrorHandler,\n Form,\n FormHelpers,\n useAuth,\n} from '@strapi/admin/strapi-admin';\nimport {\n Box,\n Button,\n Divider,\n Flex,\n IconButton,\n Modal,\n Tabs,\n Typography,\n useId,\n} from '@strapi/design-system';\nimport { Pencil } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { Locale, UpdateLocale } from '../../../shared/contracts/locales';\nimport { useUpdateLocaleMutation } from '../services/locales';\nimport { isBaseQueryError } from '../utils/baseQuery';\nimport { getTranslation } from '../utils/getTranslation';\n\nimport { AdvancedForm, BaseForm, LOCALE_SCHEMA, SubmitButton } from './CreateLocale';\n\n/* -------------------------------------------------------------------------------------------------\n * EditLocale\n * -----------------------------------------------------------------------------------------------*/\n\ninterface EditLocaleProps extends Omit<EditModalProps, 'open' | 'onOpenChange'> {}\n\nconst EditLocale = (props: EditLocaleProps) => {\n const { formatMessage } = useIntl();\n const [visible, setVisible] = React.useState(false);\n\n return (\n <>\n <IconButton\n onClick={() => setVisible(true)}\n label={formatMessage(\n {\n id: getTranslation('Settings.list.actions.edit'),\n defaultMessage: 'Edit {name} locale',\n },\n {\n name: props.name,\n }\n )}\n variant=\"ghost\"\n >\n <Pencil />\n </IconButton>\n <EditModal {...props} open={visible} onOpenChange={setVisible} />\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * EditModal\n * -----------------------------------------------------------------------------------------------*/\n\ninterface EditModalProps extends Pick<Locale, 'id' | 'isDefault' | 'name' | 'code'> {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\ntype FormValues = UpdateLocale.Request['body'] & { code: string };\n\n/**\n * @internal\n * @description Exported to be used when someone clicks on a table row.\n */\nconst EditModal = ({ id, code, isDefault, name, open, onOpenChange }: EditModalProps) => {\n const { toggleNotification } = useNotification();\n const {\n _unstableFormatAPIError: formatAPIError,\n _unstableFormatValidationErrors: formatValidationErrors,\n } = useAPIErrorHandler();\n const refetchPermissions = useAuth('EditModal', (state) => state.refetchPermissions);\n const { formatMessage } = useIntl();\n const titleId = useId();\n\n const [updateLocale] = useUpdateLocaleMutation();\n const handleSubmit = async (\n { code: _code, ...data }: FormValues,\n helpers: FormHelpers<FormValues>\n ) => {\n try {\n /**\n * We don't need to send the code, because the\n * code can never be changed.\n */\n const res = await updateLocale({\n id,\n ...data,\n });\n\n if ('error' in res) {\n if (isBaseQueryError(res.error) && res.error.name === 'ValidationError') {\n helpers.setErrors(formatValidationErrors(res.error));\n } else {\n toggleNotification({ type: 'danger', message: formatAPIError(res.error) });\n }\n\n return;\n }\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: getTranslation('Settings.locales.modal.edit.success'),\n defaultMessage: 'Updated locale',\n }),\n });\n\n refetchPermissions();\n onOpenChange(false);\n } catch (err) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: 'notification.error',\n defaultMessage: 'An error occurred, please try again',\n }),\n });\n }\n };\n\n return (\n <Modal.Root open={open} onOpenChange={onOpenChange}>\n <Modal.Content>\n <Form\n method=\"PUT\"\n onSubmit={handleSubmit}\n initialValues={{\n code,\n name,\n isDefault,\n }}\n validationSchema={LOCALE_SCHEMA}\n >\n <Modal.Header>\n <Modal.Title>\n {formatMessage(\n {\n id: getTranslation('Settings.list.actions.edit'),\n defaultMessage: 'Edit a locale',\n },\n {\n name,\n }\n )}\n </Modal.Title>\n </Modal.Header>\n <Modal.Body>\n <Tabs.Root variant=\"simple\" defaultValue=\"basic\">\n <Flex justifyContent=\"space-between\">\n <Typography tag=\"h2\" variant=\"beta\" id={titleId}>\n {formatMessage({\n Line truncated
+190
View File
@@ -0,0 +1,190 @@
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
import * as React from 'react';
import { useNotification, useAPIErrorHandler, useAuth, Form } from '@strapi/admin/strapi-admin';
import { IconButton, useId, Modal, Tabs, Flex, Typography, Divider, Box, Button } from '@strapi/design-system';
import { Pencil } from '@strapi/icons';
import { useIntl } from 'react-intl';
import { useUpdateLocaleMutation } from '../services/locales.mjs';
import { isBaseQueryError } from '../utils/baseQuery.mjs';
import { getTranslation } from '../utils/getTranslation.mjs';
import { LOCALE_SCHEMA, BaseForm, AdvancedForm, SubmitButton } from './CreateLocale.mjs';
const EditLocale = (props)=>{
const { formatMessage } = useIntl();
const [visible, setVisible] = React.useState(false);
return /*#__PURE__*/ jsxs(Fragment, {
children: [
/*#__PURE__*/ jsx(IconButton, {
onClick: ()=>setVisible(true),
label: formatMessage({
id: getTranslation('Settings.list.actions.edit'),
defaultMessage: 'Edit {name} locale'
}, {
name: props.name
}),
variant: "ghost",
children: /*#__PURE__*/ jsx(Pencil, {})
}),
/*#__PURE__*/ jsx(EditModal, {
...props,
open: visible,
onOpenChange: setVisible
})
]
});
};
/**
* @internal
* @description Exported to be used when someone clicks on a table row.
*/ const EditModal = ({ id, code, isDefault, name, open, onOpenChange })=>{
const { toggleNotification } = useNotification();
const { _unstableFormatAPIError: formatAPIError, _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
const refetchPermissions = useAuth('EditModal', (state)=>state.refetchPermissions);
const { formatMessage } = useIntl();
const titleId = useId();
const [updateLocale] = useUpdateLocaleMutation();
const handleSubmit = async ({ code: _code, ...data }, helpers)=>{
try {
/**
* We don't need to send the code, because the
* code can never be changed.
*/ const res = await updateLocale({
id,
...data
});
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.edit.success'),
defaultMessage: 'Updated locale'
})
});
refetchPermissions();
onOpenChange(false);
} catch (err) {
toggleNotification({
type: 'danger',
message: formatMessage({
id: 'notification.error',
defaultMessage: 'An error occurred, please try again'
})
});
}
};
return /*#__PURE__*/ jsx(Modal.Root, {
open: open,
onOpenChange: onOpenChange,
children: /*#__PURE__*/ jsx(Modal.Content, {
children: /*#__PURE__*/ jsxs(Form, {
method: "PUT",
onSubmit: handleSubmit,
initialValues: {
code,
name,
isDefault
},
validationSchema: LOCALE_SCHEMA,
children: [
/*#__PURE__*/ jsx(Modal.Header, {
children: /*#__PURE__*/ jsx(Modal.Title, {
children: formatMessage({
id: getTranslation('Settings.list.actions.edit'),
defaultMessage: 'Edit a locale'
}, {
name
})
})
}),
/*#__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, {
mode: "edit"
})
}),
/*#__PURE__*/ jsx(Tabs.Content, {
value: "advanced",
children: /*#__PURE__*/ jsx(AdvancedForm, {
isDefaultLocale: isDefault
})
})
]
})
]
})
}),
/*#__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, {})
]
})
]
})
})
});
};
export { EditLocale, EditModal };
//# sourceMappingURL=EditLocale.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"EditLocale.mjs","sources":["../../../admin/src/components/EditLocale.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n useNotification,\n useAPIErrorHandler,\n Form,\n FormHelpers,\n useAuth,\n} from '@strapi/admin/strapi-admin';\nimport {\n Box,\n Button,\n Divider,\n Flex,\n IconButton,\n Modal,\n Tabs,\n Typography,\n useId,\n} from '@strapi/design-system';\nimport { Pencil } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { Locale, UpdateLocale } from '../../../shared/contracts/locales';\nimport { useUpdateLocaleMutation } from '../services/locales';\nimport { isBaseQueryError } from '../utils/baseQuery';\nimport { getTranslation } from '../utils/getTranslation';\n\nimport { AdvancedForm, BaseForm, LOCALE_SCHEMA, SubmitButton } from './CreateLocale';\n\n/* -------------------------------------------------------------------------------------------------\n * EditLocale\n * -----------------------------------------------------------------------------------------------*/\n\ninterface EditLocaleProps extends Omit<EditModalProps, 'open' | 'onOpenChange'> {}\n\nconst EditLocale = (props: EditLocaleProps) => {\n const { formatMessage } = useIntl();\n const [visible, setVisible] = React.useState(false);\n\n return (\n <>\n <IconButton\n onClick={() => setVisible(true)}\n label={formatMessage(\n {\n id: getTranslation('Settings.list.actions.edit'),\n defaultMessage: 'Edit {name} locale',\n },\n {\n name: props.name,\n }\n )}\n variant=\"ghost\"\n >\n <Pencil />\n </IconButton>\n <EditModal {...props} open={visible} onOpenChange={setVisible} />\n </>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * EditModal\n * -----------------------------------------------------------------------------------------------*/\n\ninterface EditModalProps extends Pick<Locale, 'id' | 'isDefault' | 'name' | 'code'> {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\ntype FormValues = UpdateLocale.Request['body'] & { code: string };\n\n/**\n * @internal\n * @description Exported to be used when someone clicks on a table row.\n */\nconst EditModal = ({ id, code, isDefault, name, open, onOpenChange }: EditModalProps) => {\n const { toggleNotification } = useNotification();\n const {\n _unstableFormatAPIError: formatAPIError,\n _unstableFormatValidationErrors: formatValidationErrors,\n } = useAPIErrorHandler();\n const refetchPermissions = useAuth('EditModal', (state) => state.refetchPermissions);\n const { formatMessage } = useIntl();\n const titleId = useId();\n\n const [updateLocale] = useUpdateLocaleMutation();\n const handleSubmit = async (\n { code: _code, ...data }: FormValues,\n helpers: FormHelpers<FormValues>\n ) => {\n try {\n /**\n * We don't need to send the code, because the\n * code can never be changed.\n */\n const res = await updateLocale({\n id,\n ...data,\n });\n\n if ('error' in res) {\n if (isBaseQueryError(res.error) && res.error.name === 'ValidationError') {\n helpers.setErrors(formatValidationErrors(res.error));\n } else {\n toggleNotification({ type: 'danger', message: formatAPIError(res.error) });\n }\n\n return;\n }\n\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: getTranslation('Settings.locales.modal.edit.success'),\n defaultMessage: 'Updated locale',\n }),\n });\n\n refetchPermissions();\n onOpenChange(false);\n } catch (err) {\n toggleNotification({\n type: 'danger',\n message: formatMessage({\n id: 'notification.error',\n defaultMessage: 'An error occurred, please try again',\n }),\n });\n }\n };\n\n return (\n <Modal.Root open={open} onOpenChange={onOpenChange}>\n <Modal.Content>\n <Form\n method=\"PUT\"\n onSubmit={handleSubmit}\n initialValues={{\n code,\n name,\n isDefault,\n }}\n validationSchema={LOCALE_SCHEMA}\n >\n <Modal.Header>\n <Modal.Title>\n {formatMessage(\n {\n id: getTranslation('Settings.list.actions.edit'),\n defaultMessage: 'Edit a locale',\n },\n {\n name,\n }\n )}\n </Modal.Title>\n </Modal.Header>\n <Modal.Body>\n <Tabs.Root variant=\"simple\" defaultValue=\"basic\">\n <Flex justifyContent=\"space-between\">\n <Typography tag=\"h2\" variant=\"beta\" id={titleId}>\n {formatMessage({\n Line truncated
@@ -0,0 +1,82 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var designSystem = require('@strapi/design-system');
var icons = require('@strapi/icons');
var reactIntl = require('react-intl');
var locales = require('../services/locales.js');
const LocaleListCell = ({ locale: currentLocale, localizations })=>{
const { locale: language } = reactIntl.useIntl();
const { data: locales$1 = [] } = locales.useGetLocalesQuery();
const formatter = designSystem.useCollator(language, {
sensitivity: 'base'
});
if (!Array.isArray(locales$1) || !localizations) {
return null;
}
const availableLocales = localizations.map((loc)=>loc.locale);
const localesForDocument = locales$1.reduce((acc, locale)=>{
const createdLocale = [
currentLocale,
...availableLocales
].find((loc)=>{
return loc === locale.code;
});
if (createdLocale) {
acc.push(locale);
}
return acc;
}, []).map((locale)=>{
if (locale.isDefault) {
return `${locale.name} (default)`;
}
return locale.name;
}).toSorted((a, b)=>formatter.compare(a, b));
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Popover.Root, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Popover.Trigger, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
variant: "ghost",
type: "button",
onClick: (e)=>e.stopPropagation(),
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
minWidth: "100%",
alignItems: "center",
justifyContent: "center",
fontWeight: "regular",
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
textColor: "neutral800",
ellipsis: true,
marginRight: 2,
children: localesForDocument.join(', ')
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
children: /*#__PURE__*/ jsxRuntime.jsx(icons.CaretDown, {
width: "1.2rem",
height: "1.2rem"
})
})
]
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Popover.Content, {
sideOffset: 16,
children: /*#__PURE__*/ jsxRuntime.jsx("ul", {
children: localesForDocument.map((name)=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
padding: 3,
tag: "li",
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
children: name
})
}, name))
})
})
]
});
};
exports.LocaleListCell = LocaleListCell;
//# sourceMappingURL=LocaleListCell.js.map
@@ -0,0 +1 @@
{"version":3,"file":"LocaleListCell.js","sources":["../../../admin/src/components/LocaleListCell.tsx"],"sourcesContent":["import { Box, Flex, Popover, Typography, useCollator, Button } from '@strapi/design-system';\nimport { CaretDown } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { Locale } from '../../../shared/contracts/locales';\nimport { useGetLocalesQuery } from '../services/locales';\n\ninterface LocaleListCellProps {\n localizations: { locale: string }[];\n locale: string;\n}\n\nconst LocaleListCell = ({ locale: currentLocale, localizations }: LocaleListCellProps) => {\n const { locale: language } = useIntl();\n const { data: locales = [] } = useGetLocalesQuery();\n const formatter = useCollator(language, {\n sensitivity: 'base',\n });\n\n if (!Array.isArray(locales) || !localizations) {\n return null;\n }\n\n const availableLocales = localizations.map((loc) => loc.locale);\n\n const localesForDocument = locales\n .reduce<Locale[]>((acc, locale) => {\n const createdLocale = [currentLocale, ...availableLocales].find((loc) => {\n return loc === locale.code;\n });\n\n if (createdLocale) {\n acc.push(locale);\n }\n\n return acc;\n }, [])\n .map((locale) => {\n if (locale.isDefault) {\n return `${locale.name} (default)`;\n }\n\n return locale.name;\n })\n .toSorted((a, b) => formatter.compare(a, b));\n\n return (\n <Popover.Root>\n <Popover.Trigger>\n <Button variant=\"ghost\" type=\"button\" onClick={(e) => e.stopPropagation()}>\n <Flex minWidth=\"100%\" alignItems=\"center\" justifyContent=\"center\" fontWeight=\"regular\">\n <Typography textColor=\"neutral800\" ellipsis marginRight={2}>\n {localesForDocument.join(', ')}\n </Typography>\n <Flex>\n <CaretDown width=\"1.2rem\" height=\"1.2rem\" />\n </Flex>\n </Flex>\n </Button>\n </Popover.Trigger>\n <Popover.Content sideOffset={16}>\n <ul>\n {localesForDocument.map((name) => (\n <Box key={name} padding={3} tag=\"li\">\n <Typography>{name}</Typography>\n </Box>\n ))}\n </ul>\n </Popover.Content>\n </Popover.Root>\n );\n};\n\nexport { LocaleListCell };\nexport type { LocaleListCellProps };\n"],"names":["LocaleListCell","locale","currentLocale","localizations","language","useIntl","data","locales","useGetLocalesQuery","formatter","useCollator","sensitivity","Array","isArray","availableLocales","map","loc","localesForDocument","reduce","acc","createdLocale","find","code","push","isDefault","name","toSorted","a","b","compare","_jsxs","Popover","Root","_jsx","Trigger","Button","variant","type","onClick","e","stopPropagation","Flex","minWidth","alignItems","justifyContent","fontWeight","Typography","textColor","ellipsis","marginRight","join","CaretDown","width","height","Content","sideOffset","ul","Box","padding","tag"],"mappings":";;;;;;;;AAYA,MAAMA,iBAAiB,CAAC,EAAEC,QAAQC,aAAa,EAAEC,aAAa,EAAuB,GAAA;AACnF,IAAA,MAAM,EAAEF,MAAAA,EAAQG,QAAQ,EAAE,GAAGC,iBAAAA,EAAAA;AAC7B,IAAA,MAAM,EAAEC,IAAAA,EAAMC,SAAU,GAAA,EAAE,EAAE,GAAGC,0BAAAA,EAAAA;IAC/B,MAAMC,SAAAA,GAAYC,yBAAYN,QAAU,EAAA;QACtCO,WAAa,EAAA;AACf,KAAA,CAAA;AAEA,IAAA,IAAI,CAACC,KAAMC,CAAAA,OAAO,CAACN,SAAAA,CAAAA,IAAY,CAACJ,aAAe,EAAA;QAC7C,OAAO,IAAA;AACT;AAEA,IAAA,MAAMW,mBAAmBX,aAAcY,CAAAA,GAAG,CAAC,CAACC,GAAAA,GAAQA,IAAIf,MAAM,CAAA;AAE9D,IAAA,MAAMgB,kBAAqBV,GAAAA,SAAAA,CACxBW,MAAM,CAAW,CAACC,GAAKlB,EAAAA,MAAAA,GAAAA;AACtB,QAAA,MAAMmB,aAAgB,GAAA;AAAClB,YAAAA,aAAAA;AAAkBY,YAAAA,GAAAA;SAAiB,CAACO,IAAI,CAAC,CAACL,GAAAA,GAAAA;YAC/D,OAAOA,GAAAA,KAAQf,OAAOqB,IAAI;AAC5B,SAAA,CAAA;AAEA,QAAA,IAAIF,aAAe,EAAA;AACjBD,YAAAA,GAAAA,CAAII,IAAI,CAACtB,MAAAA,CAAAA;AACX;QAEA,OAAOkB,GAAAA;AACT,KAAA,EAAG,EAAE,CAAA,CACJJ,GAAG,CAAC,CAACd,MAAAA,GAAAA;QACJ,IAAIA,MAAAA,CAAOuB,SAAS,EAAE;AACpB,YAAA,OAAO,CAAC,EAAEvB,MAAAA,CAAOwB,IAAI,CAAC,UAAU,CAAC;AACnC;AAEA,QAAA,OAAOxB,OAAOwB,IAAI;KAEnBC,CAAAA,CAAAA,QAAQ,CAAC,CAACC,CAAAA,EAAGC,IAAMnB,SAAUoB,CAAAA,OAAO,CAACF,CAAGC,EAAAA,CAAAA,CAAAA,CAAAA;IAE3C,qBACEE,eAAA,CAACC,qBAAQC,IAAI,EAAA;;AACX,0BAAAC,cAAA,CAACF,qBAAQG,OAAO,EAAA;AACd,gBAAA,QAAA,gBAAAD,cAACE,CAAAA,mBAAAA,EAAAA;oBAAOC,OAAQ,EAAA,OAAA;oBAAQC,IAAK,EAAA,QAAA;oBAASC,OAAS,EAAA,CAACC,CAAMA,GAAAA,CAAAA,CAAEC,eAAe,EAAA;AACrE,oBAAA,QAAA,gBAAAV,eAACW,CAAAA,iBAAAA,EAAAA;wBAAKC,QAAS,EAAA,MAAA;wBAAOC,UAAW,EAAA,QAAA;wBAASC,cAAe,EAAA,QAAA;wBAASC,UAAW,EAAA,SAAA;;0CAC3EZ,cAACa,CAAAA,uBAAAA,EAAAA;gCAAWC,SAAU,EAAA,YAAA;gCAAaC,QAAQ,EAAA,IAAA;gCAACC,WAAa,EAAA,CAAA;AACtDhC,gCAAAA,QAAAA,EAAAA,kBAAAA,CAAmBiC,IAAI,CAAC,IAAA;;0CAE3BjB,cAACQ,CAAAA,iBAAAA,EAAAA;AACC,gCAAA,QAAA,gBAAAR,cAACkB,CAAAA,eAAAA,EAAAA;oCAAUC,KAAM,EAAA,QAAA;oCAASC,MAAO,EAAA;;;;;;;AAKzC,0BAAApB,cAAA,CAACF,qBAAQuB,OAAO,EAAA;gBAACC,UAAY,EAAA,EAAA;AAC3B,gBAAA,QAAA,gBAAAtB,cAACuB,CAAAA,IAAAA,EAAAA;AACEvC,oBAAAA,QAAAA,EAAAA,kBAAAA,CAAmBF,GAAG,CAAC,CAACU,IAAAA,iBACvBQ,cAACwB,CAAAA,gBAAAA,Line truncated
@@ -0,0 +1,80 @@
import { jsxs, jsx } from 'react/jsx-runtime';
import { useCollator, Popover, Button, Flex, Typography, Box } from '@strapi/design-system';
import { CaretDown } from '@strapi/icons';
import { useIntl } from 'react-intl';
import { useGetLocalesQuery } from '../services/locales.mjs';
const LocaleListCell = ({ locale: currentLocale, localizations })=>{
const { locale: language } = useIntl();
const { data: locales = [] } = useGetLocalesQuery();
const formatter = useCollator(language, {
sensitivity: 'base'
});
if (!Array.isArray(locales) || !localizations) {
return null;
}
const availableLocales = localizations.map((loc)=>loc.locale);
const localesForDocument = locales.reduce((acc, locale)=>{
const createdLocale = [
currentLocale,
...availableLocales
].find((loc)=>{
return loc === locale.code;
});
if (createdLocale) {
acc.push(locale);
}
return acc;
}, []).map((locale)=>{
if (locale.isDefault) {
return `${locale.name} (default)`;
}
return locale.name;
}).toSorted((a, b)=>formatter.compare(a, b));
return /*#__PURE__*/ jsxs(Popover.Root, {
children: [
/*#__PURE__*/ jsx(Popover.Trigger, {
children: /*#__PURE__*/ jsx(Button, {
variant: "ghost",
type: "button",
onClick: (e)=>e.stopPropagation(),
children: /*#__PURE__*/ jsxs(Flex, {
minWidth: "100%",
alignItems: "center",
justifyContent: "center",
fontWeight: "regular",
children: [
/*#__PURE__*/ jsx(Typography, {
textColor: "neutral800",
ellipsis: true,
marginRight: 2,
children: localesForDocument.join(', ')
}),
/*#__PURE__*/ jsx(Flex, {
children: /*#__PURE__*/ jsx(CaretDown, {
width: "1.2rem",
height: "1.2rem"
})
})
]
})
})
}),
/*#__PURE__*/ jsx(Popover.Content, {
sideOffset: 16,
children: /*#__PURE__*/ jsx("ul", {
children: localesForDocument.map((name)=>/*#__PURE__*/ jsx(Box, {
padding: 3,
tag: "li",
children: /*#__PURE__*/ jsx(Typography, {
children: name
})
}, name))
})
})
]
});
};
export { LocaleListCell };
//# sourceMappingURL=LocaleListCell.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"LocaleListCell.mjs","sources":["../../../admin/src/components/LocaleListCell.tsx"],"sourcesContent":["import { Box, Flex, Popover, Typography, useCollator, Button } from '@strapi/design-system';\nimport { CaretDown } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { Locale } from '../../../shared/contracts/locales';\nimport { useGetLocalesQuery } from '../services/locales';\n\ninterface LocaleListCellProps {\n localizations: { locale: string }[];\n locale: string;\n}\n\nconst LocaleListCell = ({ locale: currentLocale, localizations }: LocaleListCellProps) => {\n const { locale: language } = useIntl();\n const { data: locales = [] } = useGetLocalesQuery();\n const formatter = useCollator(language, {\n sensitivity: 'base',\n });\n\n if (!Array.isArray(locales) || !localizations) {\n return null;\n }\n\n const availableLocales = localizations.map((loc) => loc.locale);\n\n const localesForDocument = locales\n .reduce<Locale[]>((acc, locale) => {\n const createdLocale = [currentLocale, ...availableLocales].find((loc) => {\n return loc === locale.code;\n });\n\n if (createdLocale) {\n acc.push(locale);\n }\n\n return acc;\n }, [])\n .map((locale) => {\n if (locale.isDefault) {\n return `${locale.name} (default)`;\n }\n\n return locale.name;\n })\n .toSorted((a, b) => formatter.compare(a, b));\n\n return (\n <Popover.Root>\n <Popover.Trigger>\n <Button variant=\"ghost\" type=\"button\" onClick={(e) => e.stopPropagation()}>\n <Flex minWidth=\"100%\" alignItems=\"center\" justifyContent=\"center\" fontWeight=\"regular\">\n <Typography textColor=\"neutral800\" ellipsis marginRight={2}>\n {localesForDocument.join(', ')}\n </Typography>\n <Flex>\n <CaretDown width=\"1.2rem\" height=\"1.2rem\" />\n </Flex>\n </Flex>\n </Button>\n </Popover.Trigger>\n <Popover.Content sideOffset={16}>\n <ul>\n {localesForDocument.map((name) => (\n <Box key={name} padding={3} tag=\"li\">\n <Typography>{name}</Typography>\n </Box>\n ))}\n </ul>\n </Popover.Content>\n </Popover.Root>\n );\n};\n\nexport { LocaleListCell };\nexport type { LocaleListCellProps };\n"],"names":["LocaleListCell","locale","currentLocale","localizations","language","useIntl","data","locales","useGetLocalesQuery","formatter","useCollator","sensitivity","Array","isArray","availableLocales","map","loc","localesForDocument","reduce","acc","createdLocale","find","code","push","isDefault","name","toSorted","a","b","compare","_jsxs","Popover","Root","_jsx","Trigger","Button","variant","type","onClick","e","stopPropagation","Flex","minWidth","alignItems","justifyContent","fontWeight","Typography","textColor","ellipsis","marginRight","join","CaretDown","width","height","Content","sideOffset","ul","Box","padding","tag"],"mappings":";;;;;;AAYA,MAAMA,iBAAiB,CAAC,EAAEC,QAAQC,aAAa,EAAEC,aAAa,EAAuB,GAAA;AACnF,IAAA,MAAM,EAAEF,MAAAA,EAAQG,QAAQ,EAAE,GAAGC,OAAAA,EAAAA;AAC7B,IAAA,MAAM,EAAEC,IAAAA,EAAMC,OAAU,GAAA,EAAE,EAAE,GAAGC,kBAAAA,EAAAA;IAC/B,MAAMC,SAAAA,GAAYC,YAAYN,QAAU,EAAA;QACtCO,WAAa,EAAA;AACf,KAAA,CAAA;AAEA,IAAA,IAAI,CAACC,KAAMC,CAAAA,OAAO,CAACN,OAAAA,CAAAA,IAAY,CAACJ,aAAe,EAAA;QAC7C,OAAO,IAAA;AACT;AAEA,IAAA,MAAMW,mBAAmBX,aAAcY,CAAAA,GAAG,CAAC,CAACC,GAAAA,GAAQA,IAAIf,MAAM,CAAA;AAE9D,IAAA,MAAMgB,kBAAqBV,GAAAA,OAAAA,CACxBW,MAAM,CAAW,CAACC,GAAKlB,EAAAA,MAAAA,GAAAA;AACtB,QAAA,MAAMmB,aAAgB,GAAA;AAAClB,YAAAA,aAAAA;AAAkBY,YAAAA,GAAAA;SAAiB,CAACO,IAAI,CAAC,CAACL,GAAAA,GAAAA;YAC/D,OAAOA,GAAAA,KAAQf,OAAOqB,IAAI;AAC5B,SAAA,CAAA;AAEA,QAAA,IAAIF,aAAe,EAAA;AACjBD,YAAAA,GAAAA,CAAII,IAAI,CAACtB,MAAAA,CAAAA;AACX;QAEA,OAAOkB,GAAAA;AACT,KAAA,EAAG,EAAE,CAAA,CACJJ,GAAG,CAAC,CAACd,MAAAA,GAAAA;QACJ,IAAIA,MAAAA,CAAOuB,SAAS,EAAE;AACpB,YAAA,OAAO,CAAC,EAAEvB,MAAAA,CAAOwB,IAAI,CAAC,UAAU,CAAC;AACnC;AAEA,QAAA,OAAOxB,OAAOwB,IAAI;KAEnBC,CAAAA,CAAAA,QAAQ,CAAC,CAACC,CAAAA,EAAGC,IAAMnB,SAAUoB,CAAAA,OAAO,CAACF,CAAGC,EAAAA,CAAAA,CAAAA,CAAAA;IAE3C,qBACEE,IAAA,CAACC,QAAQC,IAAI,EAAA;;AACX,0BAAAC,GAAA,CAACF,QAAQG,OAAO,EAAA;AACd,gBAAA,QAAA,gBAAAD,GAACE,CAAAA,MAAAA,EAAAA;oBAAOC,OAAQ,EAAA,OAAA;oBAAQC,IAAK,EAAA,QAAA;oBAASC,OAAS,EAAA,CAACC,CAAMA,GAAAA,CAAAA,CAAEC,eAAe,EAAA;AACrE,oBAAA,QAAA,gBAAAV,IAACW,CAAAA,IAAAA,EAAAA;wBAAKC,QAAS,EAAA,MAAA;wBAAOC,UAAW,EAAA,QAAA;wBAASC,cAAe,EAAA,QAAA;wBAASC,UAAW,EAAA,SAAA;;0CAC3EZ,GAACa,CAAAA,UAAAA,EAAAA;gCAAWC,SAAU,EAAA,YAAA;gCAAaC,QAAQ,EAAA,IAAA;gCAACC,WAAa,EAAA,CAAA;AACtDhC,gCAAAA,QAAAA,EAAAA,kBAAAA,CAAmBiC,IAAI,CAAC,IAAA;;0CAE3BjB,GAACQ,CAAAA,IAAAA,EAAAA;AACC,gCAAA,QAAA,gBAAAR,GAACkB,CAAAA,SAAAA,EAAAA;oCAAUC,KAAM,EAAA,QAAA;oCAASC,MAAO,EAAA;;;;;;;AAKzC,0BAAApB,GAAA,CAACF,QAAQuB,OAAO,EAAA;gBAACC,UAAY,EAAA,EAAA;AAC3B,gBAAA,QAAA,gBAAAtB,GAACuB,CAAAA,IAAAA,EAAAA;AACEvC,oBAAAA,QAAAA,EAAAA,kBAAAA,CAAmBF,GAAG,CAAC,CAACU,IAAAA,iBACvBQ,GAACwB,CAAAA,GAAAA,EAAAA;4BAAeLine truncated
+98
View File
@@ -0,0 +1,98 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var strapiAdmin = require('@strapi/admin/strapi-admin');
var designSystem = require('@strapi/design-system');
var reactIntl = require('react-intl');
var useI18n = require('../hooks/useI18n.js');
var locales = require('../services/locales.js');
var getTranslation = require('../utils/getTranslation.js');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
const LocalePicker = ()=>{
const { formatMessage } = reactIntl.useIntl();
const [{ query }, setQuery] = strapiAdmin.useQueryParams();
const { hasI18n, canRead, canCreate } = useI18n.useI18n();
const { data: locales$1 = [] } = locales.useGetLocalesQuery(undefined, {
skip: !hasI18n
});
const handleChange = React__namespace.useCallback((code, replace = false)=>{
setQuery({
page: 1,
plugins: {
...query.plugins,
i18n: {
locale: code
}
}
}, 'push', replace);
}, [
query.plugins,
setQuery
]);
React__namespace.useEffect(()=>{
if (!Array.isArray(locales$1) || !hasI18n) {
return;
}
/**
* Handle the case where the current locale query param doesn't exist
* in the list of available locales, so we redirect to the default locale.
*/ const currentDesiredLocale = query.plugins?.i18n?.locale;
const doesLocaleExist = locales$1.find((loc)=>loc.code === currentDesiredLocale);
const defaultLocale = locales$1.find((locale)=>locale.isDefault);
if (!doesLocaleExist && defaultLocale?.code) {
handleChange(defaultLocale.code, true);
}
}, [
hasI18n,
handleChange,
locales$1,
query.plugins?.i18n?.locale
]);
if (!hasI18n || !Array.isArray(locales$1) || locales$1.length === 0) {
return null;
}
const displayedLocales = locales$1.filter((locale)=>{
/**
* If you can create or read we allow you to see the locale exists
* this is because in the ListView, you may be able to create a new entry
* in a locale you can't read.
*/ return canCreate.includes(locale.code) || canRead.includes(locale.code);
});
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.SingleSelect, {
size: "S",
"aria-label": formatMessage({
id: getTranslation.getTranslation('actions.select-locale'),
defaultMessage: 'Select locale'
}),
value: query.plugins?.i18n?.locale || locales$1.find((locale)=>locale.isDefault)?.code,
// @ts-expect-error – This can be removed in V2 of the DS.
onChange: handleChange,
children: displayedLocales.map((locale)=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.SingleSelectOption, {
value: locale.code,
children: locale.name
}, locale.id))
});
};
exports.LocalePicker = LocalePicker;
//# sourceMappingURL=LocalePicker.js.map
@@ -0,0 +1 @@
{"version":3,"file":"LocalePicker.js","sources":["../../../admin/src/components/LocalePicker.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useQueryParams } from '@strapi/admin/strapi-admin';\nimport { SingleSelect, SingleSelectOption } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { useI18n } from '../hooks/useI18n';\nimport { useGetLocalesQuery } from '../services/locales';\nimport { getTranslation } from '../utils/getTranslation';\n\nimport type { I18nBaseQuery } from '../types';\n\ninterface Query extends I18nBaseQuery {\n page?: number;\n}\n\nconst LocalePicker = () => {\n const { formatMessage } = useIntl();\n const [{ query }, setQuery] = useQueryParams<Query>();\n\n const { hasI18n, canRead, canCreate } = useI18n();\n const { data: locales = [] } = useGetLocalesQuery(undefined, {\n skip: !hasI18n,\n });\n\n const handleChange = React.useCallback(\n (code: string, replace = false) => {\n setQuery(\n {\n page: 1,\n plugins: { ...query.plugins, i18n: { locale: code } },\n },\n 'push',\n replace\n );\n },\n [query.plugins, setQuery]\n );\n\n React.useEffect(() => {\n if (!Array.isArray(locales) || !hasI18n) {\n return;\n }\n /**\n * Handle the case where the current locale query param doesn't exist\n * in the list of available locales, so we redirect to the default locale.\n */\n const currentDesiredLocale = query.plugins?.i18n?.locale;\n const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);\n const defaultLocale = locales.find((locale) => locale.isDefault);\n if (!doesLocaleExist && defaultLocale?.code) {\n handleChange(defaultLocale.code, true);\n }\n }, [hasI18n, handleChange, locales, query.plugins?.i18n?.locale]);\n\n if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {\n return null;\n }\n\n const displayedLocales = locales.filter((locale) => {\n /**\n * If you can create or read we allow you to see the locale exists\n * this is because in the ListView, you may be able to create a new entry\n * in a locale you can't read.\n */\n return canCreate.includes(locale.code) || canRead.includes(locale.code);\n });\n\n return (\n <SingleSelect\n size=\"S\"\n aria-label={formatMessage({\n id: getTranslation('actions.select-locale'),\n defaultMessage: 'Select locale',\n })}\n value={query.plugins?.i18n?.locale || locales.find((locale) => locale.isDefault)?.code}\n // @ts-expect-error – This can be removed in V2 of the DS.\n onChange={handleChange}\n >\n {displayedLocales.map((locale) => (\n <SingleSelectOption key={locale.id} value={locale.code}>\n {locale.name}\n </SingleSelectOption>\n ))}\n </SingleSelect>\n );\n};\n\nexport { LocalePicker };\n"],"names":["LocalePicker","formatMessage","useIntl","query","setQuery","useQueryParams","hasI18n","canRead","canCreate","useI18n","data","locales","useGetLocalesQuery","undefined","skip","handleChange","React","useCallback","code","replace","page","plugins","i18n","locale","useEffect","Array","isArray","currentDesiredLocale","doesLocaleExist","find","loc","defaultLocale","isDefault","length","displayedLocales","filter","includes","_jsx","SingleSelect","size","aria-label","id","getTranslation","defaultMessage","value","onChange","map","SingleSelectOption","name"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,MAAMA,YAAe,GAAA,IAAA;IACnB,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAC1B,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,EAAEC,SAAS,GAAGC,0BAAAA,EAAAA;AAE9B,IAAA,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAEC,SAAS,EAAE,GAAGC,eAAAA,EAAAA;AACxC,IAAA,MAAM,EAAEC,IAAMC,EAAAA,SAAAA,GAAU,EAAE,EAAE,GAAGC,2BAAmBC,SAAW,EAAA;AAC3DC,QAAAA,IAAAA,EAAM,CAACR;AACT,KAAA,CAAA;AAEA,IAAA,MAAMS,eAAeC,gBAAMC,CAAAA,WAAW,CACpC,CAACC,IAAAA,EAAcC,UAAU,KAAK,GAAA;QAC5Bf,QACE,CAAA;YACEgB,IAAM,EAAA,CAAA;YACNC,OAAS,EAAA;AAAE,gBAAA,GAAGlB,MAAMkB,OAAO;gBAAEC,IAAM,EAAA;oBAAEC,MAAQL,EAAAA;AAAK;AAAE;AACtD,SAAA,EACA,MACAC,EAAAA,OAAAA,CAAAA;KAGJ,EAAA;AAAChB,QAAAA,KAAAA,CAAMkB,OAAO;AAAEjB,QAAAA;AAAS,KAAA,CAAA;AAG3BY,IAAAA,gBAAAA,CAAMQ,SAAS,CAAC,IAAA;AACd,QAAA,IAAI,CAACC,KAAMC,CAAAA,OAAO,CAACf,SAAAA,CAAAA,IAAY,CAACL,OAAS,EAAA;AACvC,YAAA;AACF;AACA;;;AAGC,QACD,MAAMqB,oBAAAA,GAAuBxB,KAAMkB,CAAAA,OAAO,EAAEC,IAAMC,EAAAA,MAAAA;QAClD,MAAMK,eAAAA,GAAkBjB,UAAQkB,IAAI,CAAC,CAACC,GAAQA,GAAAA,GAAAA,CAAIZ,IAAI,KAAKS,oBAAAA,CAAAA;AAC3D,QAAA,MAAMI,gBAAgBpB,SAAQkB,CAAAA,IAAI,CAAC,CAACN,MAAAA,GAAWA,OAAOS,SAAS,CAAA;QAC/D,IAAI,CAACJ,eAAmBG,IAAAA,aAAAA,EAAeb,IAAM,EAAA;YAC3CH,YAAagB,CAAAA,aAAAA,CAAcb,IAAI,EAAE,IAAA,CAAA;AACnC;KACC,EAAA;AAACZ,QAAAA,OAAAA;AAASS,QAAAA,YAAAA;AAAcJ,QAAAA,SAAAA;QAASR,KAAMkB,CAAAA,OAAO,EAAEC,IAAMC,EAAAA;AAAO,KAAA,CAAA;IAEhE,IAAI,CAACjB,OAAW,IAAA,CAACmB,KAAMC,CAAAA,OAAO,CAACf,SAAYA,CAAAA,IAAAA,SAAAA,CAAQsB,MAAM,KAAK,CAAG,EAAA;QAC/D,OAAO,IAAA;AACT;AAEA,IAAA,MAAMC,gBAAmBvB,GAAAA,SAAAA,CAAQwB,Line truncated
@@ -0,0 +1,77 @@
import { jsx } from 'react/jsx-runtime';
import * as React from 'react';
import { useQueryParams } from '@strapi/admin/strapi-admin';
import { SingleSelect, SingleSelectOption } from '@strapi/design-system';
import { useIntl } from 'react-intl';
import { useI18n } from '../hooks/useI18n.mjs';
import { useGetLocalesQuery } from '../services/locales.mjs';
import { getTranslation } from '../utils/getTranslation.mjs';
const LocalePicker = ()=>{
const { formatMessage } = useIntl();
const [{ query }, setQuery] = useQueryParams();
const { hasI18n, canRead, canCreate } = useI18n();
const { data: locales = [] } = useGetLocalesQuery(undefined, {
skip: !hasI18n
});
const handleChange = React.useCallback((code, replace = false)=>{
setQuery({
page: 1,
plugins: {
...query.plugins,
i18n: {
locale: code
}
}
}, 'push', replace);
}, [
query.plugins,
setQuery
]);
React.useEffect(()=>{
if (!Array.isArray(locales) || !hasI18n) {
return;
}
/**
* Handle the case where the current locale query param doesn't exist
* in the list of available locales, so we redirect to the default locale.
*/ const currentDesiredLocale = query.plugins?.i18n?.locale;
const doesLocaleExist = locales.find((loc)=>loc.code === currentDesiredLocale);
const defaultLocale = locales.find((locale)=>locale.isDefault);
if (!doesLocaleExist && defaultLocale?.code) {
handleChange(defaultLocale.code, true);
}
}, [
hasI18n,
handleChange,
locales,
query.plugins?.i18n?.locale
]);
if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
return null;
}
const displayedLocales = locales.filter((locale)=>{
/**
* If you can create or read we allow you to see the locale exists
* this is because in the ListView, you may be able to create a new entry
* in a locale you can't read.
*/ return canCreate.includes(locale.code) || canRead.includes(locale.code);
});
return /*#__PURE__*/ jsx(SingleSelect, {
size: "S",
"aria-label": formatMessage({
id: getTranslation('actions.select-locale'),
defaultMessage: 'Select locale'
}),
value: query.plugins?.i18n?.locale || locales.find((locale)=>locale.isDefault)?.code,
// @ts-expect-error – This can be removed in V2 of the DS.
onChange: handleChange,
children: displayedLocales.map((locale)=>/*#__PURE__*/ jsx(SingleSelectOption, {
value: locale.code,
children: locale.name
}, locale.id))
});
};
export { LocalePicker };
//# sourceMappingURL=LocalePicker.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"LocalePicker.mjs","sources":["../../../admin/src/components/LocalePicker.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { useQueryParams } from '@strapi/admin/strapi-admin';\nimport { SingleSelect, SingleSelectOption } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { useI18n } from '../hooks/useI18n';\nimport { useGetLocalesQuery } from '../services/locales';\nimport { getTranslation } from '../utils/getTranslation';\n\nimport type { I18nBaseQuery } from '../types';\n\ninterface Query extends I18nBaseQuery {\n page?: number;\n}\n\nconst LocalePicker = () => {\n const { formatMessage } = useIntl();\n const [{ query }, setQuery] = useQueryParams<Query>();\n\n const { hasI18n, canRead, canCreate } = useI18n();\n const { data: locales = [] } = useGetLocalesQuery(undefined, {\n skip: !hasI18n,\n });\n\n const handleChange = React.useCallback(\n (code: string, replace = false) => {\n setQuery(\n {\n page: 1,\n plugins: { ...query.plugins, i18n: { locale: code } },\n },\n 'push',\n replace\n );\n },\n [query.plugins, setQuery]\n );\n\n React.useEffect(() => {\n if (!Array.isArray(locales) || !hasI18n) {\n return;\n }\n /**\n * Handle the case where the current locale query param doesn't exist\n * in the list of available locales, so we redirect to the default locale.\n */\n const currentDesiredLocale = query.plugins?.i18n?.locale;\n const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);\n const defaultLocale = locales.find((locale) => locale.isDefault);\n if (!doesLocaleExist && defaultLocale?.code) {\n handleChange(defaultLocale.code, true);\n }\n }, [hasI18n, handleChange, locales, query.plugins?.i18n?.locale]);\n\n if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {\n return null;\n }\n\n const displayedLocales = locales.filter((locale) => {\n /**\n * If you can create or read we allow you to see the locale exists\n * this is because in the ListView, you may be able to create a new entry\n * in a locale you can't read.\n */\n return canCreate.includes(locale.code) || canRead.includes(locale.code);\n });\n\n return (\n <SingleSelect\n size=\"S\"\n aria-label={formatMessage({\n id: getTranslation('actions.select-locale'),\n defaultMessage: 'Select locale',\n })}\n value={query.plugins?.i18n?.locale || locales.find((locale) => locale.isDefault)?.code}\n // @ts-expect-error – This can be removed in V2 of the DS.\n onChange={handleChange}\n >\n {displayedLocales.map((locale) => (\n <SingleSelectOption key={locale.id} value={locale.code}>\n {locale.name}\n </SingleSelectOption>\n ))}\n </SingleSelect>\n );\n};\n\nexport { LocalePicker };\n"],"names":["LocalePicker","formatMessage","useIntl","query","setQuery","useQueryParams","hasI18n","canRead","canCreate","useI18n","data","locales","useGetLocalesQuery","undefined","skip","handleChange","React","useCallback","code","replace","page","plugins","i18n","locale","useEffect","Array","isArray","currentDesiredLocale","doesLocaleExist","find","loc","defaultLocale","isDefault","length","displayedLocales","filter","includes","_jsx","SingleSelect","size","aria-label","id","getTranslation","defaultMessage","value","onChange","map","SingleSelectOption","name"],"mappings":";;;;;;;;;AAgBA,MAAMA,YAAe,GAAA,IAAA;IACnB,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAC1B,IAAA,MAAM,CAAC,EAAEC,KAAK,EAAE,EAAEC,SAAS,GAAGC,cAAAA,EAAAA;AAE9B,IAAA,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAEC,SAAS,EAAE,GAAGC,OAAAA,EAAAA;AACxC,IAAA,MAAM,EAAEC,IAAMC,EAAAA,OAAAA,GAAU,EAAE,EAAE,GAAGC,mBAAmBC,SAAW,EAAA;AAC3DC,QAAAA,IAAAA,EAAM,CAACR;AACT,KAAA,CAAA;AAEA,IAAA,MAAMS,eAAeC,KAAMC,CAAAA,WAAW,CACpC,CAACC,IAAAA,EAAcC,UAAU,KAAK,GAAA;QAC5Bf,QACE,CAAA;YACEgB,IAAM,EAAA,CAAA;YACNC,OAAS,EAAA;AAAE,gBAAA,GAAGlB,MAAMkB,OAAO;gBAAEC,IAAM,EAAA;oBAAEC,MAAQL,EAAAA;AAAK;AAAE;AACtD,SAAA,EACA,MACAC,EAAAA,OAAAA,CAAAA;KAGJ,EAAA;AAAChB,QAAAA,KAAAA,CAAMkB,OAAO;AAAEjB,QAAAA;AAAS,KAAA,CAAA;AAG3BY,IAAAA,KAAAA,CAAMQ,SAAS,CAAC,IAAA;AACd,QAAA,IAAI,CAACC,KAAMC,CAAAA,OAAO,CAACf,OAAAA,CAAAA,IAAY,CAACL,OAAS,EAAA;AACvC,YAAA;AACF;AACA;;;AAGC,QACD,MAAMqB,oBAAAA,GAAuBxB,KAAMkB,CAAAA,OAAO,EAAEC,IAAMC,EAAAA,MAAAA;QAClD,MAAMK,eAAAA,GAAkBjB,QAAQkB,IAAI,CAAC,CAACC,GAAQA,GAAAA,GAAAA,CAAIZ,IAAI,KAAKS,oBAAAA,CAAAA;AAC3D,QAAA,MAAMI,gBAAgBpB,OAAQkB,CAAAA,IAAI,CAAC,CAACN,MAAAA,GAAWA,OAAOS,SAAS,CAAA;QAC/D,IAAI,CAACJ,eAAmBG,IAAAA,aAAAA,EAAeb,IAAM,EAAA;YAC3CH,YAAagB,CAAAA,aAAAA,CAAcb,IAAI,EAAE,IAAA,CAAA;AACnC;KACC,EAAA;AAACZ,QAAAA,OAAAA;AAASS,QAAAA,YAAAA;AAAcJ,QAAAA,OAAAA;QAASR,KAAMkB,CAAAA,OAAO,EAAEC,IAAMC,EAAAA;AAAO,KAAA,CAAA;IAEhE,IAAI,CAACjB,OAAW,IAAA,CAACmB,KAAMC,CAAAA,OAAO,CAACf,OAAYA,CAAAA,IAAAA,OAAAA,CAAQsB,MAAM,KAAK,CAAG,EAAA;QAC/D,OAAO,IAAA;AACT;AAEA,IAAA,MAAMC,gBAAmBvB,GAAAA,OAAAA,CAAQwB,MAAM,CAAC,CAACZ,MAAAA,GALine truncated
+143
View File
@@ -0,0 +1,143 @@
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var designSystem = require('@strapi/design-system');
var reactIntl = require('react-intl');
var getTranslation = require('../utils/getTranslation.js');
var DeleteLocale = require('./DeleteLocale.js');
var EditLocale = require('./EditLocale.js');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
const LocaleTable = ({ locales = [], canDelete, canUpdate })=>{
const [editLocaleId, setEditLocaleId] = React__namespace.useState();
const { formatMessage } = reactIntl.useIntl();
const handleClick = (localeId)=>()=>{
if (canUpdate) {
setEditLocaleId(localeId);
}
};
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Table, {
colCount: 4,
rowCount: locales.length + 1,
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Thead, {
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Tr, {
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Th, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
variant: "sigma",
textColor: "neutral600",
children: formatMessage({
id: getTranslation.getTranslation('Settings.locales.row.id'),
defaultMessage: 'ID'
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Th, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
variant: "sigma",
textColor: "neutral600",
children: formatMessage({
id: getTranslation.getTranslation('Settings.locales.row.displayName'),
defaultMessage: 'Display name'
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Th, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
variant: "sigma",
textColor: "neutral600",
children: formatMessage({
id: getTranslation.getTranslation('Settings.locales.row.default-locale'),
defaultMessage: 'Default locale'
})
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Th, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.VisuallyHidden, {
children: "Actions"
})
})
]
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Tbody, {
children: locales.map((locale)=>/*#__PURE__*/ jsxRuntime.jsxs(React__namespace.Fragment, {
children: [
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Tr, {
onClick: handleClick(locale.id),
style: {
cursor: canUpdate ? 'pointer' : 'default'
},
children: [
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Td, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
textColor: "neutral800",
children: locale.id
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Td, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
textColor: "neutral800",
children: locale.name
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Td, {
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
textColor: "neutral800",
children: locale.isDefault ? formatMessage({
id: getTranslation.getTranslation('Settings.locales.default'),
defaultMessage: 'Default'
}) : null
})
}),
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Td, {
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
gap: 1,
justifyContent: "flex-end",
onClick: (e)=>e.stopPropagation(),
children: [
canUpdate && /*#__PURE__*/ jsxRuntime.jsx(EditLocale.EditLocale, {
...locale
}),
canDelete && !locale.isDefault && /*#__PURE__*/ jsxRuntime.jsx(DeleteLocale.DeleteLocale, {
...locale
})
]
})
})
]
}),
/*#__PURE__*/ jsxRuntime.jsx(EditLocale.EditModal, {
...locale,
onOpenChange: ()=>setEditLocaleId(undefined),
open: editLocaleId === locale.id
})
]
}, locale.id))
})
]
});
};
exports.LocaleTable = LocaleTable;
//# sourceMappingURL=LocaleTable.js.map
@@ -0,0 +1 @@
{"version":3,"file":"LocaleTable.js","sources":["../../../admin/src/components/LocaleTable.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Flex,\n Table,\n Tbody,\n Td,\n Th,\n Thead,\n Tr,\n Typography,\n VisuallyHidden,\n} from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getTranslation } from '../utils/getTranslation';\n\nimport { DeleteLocale } from './DeleteLocale';\nimport { EditLocale, EditModal } from './EditLocale';\n\nimport type { Locale } from '../../../shared/contracts/locales';\n\n/* -------------------------------------------------------------------------------------------------\n * LocaleTable\n * -----------------------------------------------------------------------------------------------*/\n\ntype LocaleTableProps = {\n locales?: Locale[];\n canDelete?: boolean;\n canUpdate?: boolean;\n onDeleteLocale?: (locale: Locale) => void;\n onEditLocale?: (locale: Locale) => void;\n};\n\nconst LocaleTable = ({ locales = [], canDelete, canUpdate }: LocaleTableProps) => {\n const [editLocaleId, setEditLocaleId] = React.useState<Locale['id']>();\n const { formatMessage } = useIntl();\n\n const handleClick = (localeId: Locale['id']) => () => {\n if (canUpdate) {\n setEditLocaleId(localeId);\n }\n };\n\n return (\n <Table colCount={4} rowCount={locales.length + 1}>\n <Thead>\n <Tr>\n <Th>\n <Typography variant=\"sigma\" textColor=\"neutral600\">\n {formatMessage({\n id: getTranslation('Settings.locales.row.id'),\n defaultMessage: 'ID',\n })}\n </Typography>\n </Th>\n <Th>\n <Typography variant=\"sigma\" textColor=\"neutral600\">\n {formatMessage({\n id: getTranslation('Settings.locales.row.displayName'),\n defaultMessage: 'Display name',\n })}\n </Typography>\n </Th>\n <Th>\n <Typography variant=\"sigma\" textColor=\"neutral600\">\n {formatMessage({\n id: getTranslation('Settings.locales.row.default-locale'),\n defaultMessage: 'Default locale',\n })}\n </Typography>\n </Th>\n <Th>\n <VisuallyHidden>Actions</VisuallyHidden>\n </Th>\n </Tr>\n </Thead>\n <Tbody>\n {locales.map((locale) => (\n <React.Fragment key={locale.id}>\n <Tr\n onClick={handleClick(locale.id)}\n style={{ cursor: canUpdate ? 'pointer' : 'default' }}\n >\n <Td>\n <Typography textColor=\"neutral800\">{locale.id}</Typography>\n </Td>\n <Td>\n <Typography textColor=\"neutral800\">{locale.name}</Typography>\n </Td>\n <Td>\n <Typography textColor=\"neutral800\">\n {locale.isDefault\n ? formatMessage({\n id: getTranslation('Settings.locales.default'),\n defaultMessage: 'Default',\n })\n : null}\n </Typography>\n </Td>\n <Td>\n <Flex gap={1} justifyContent=\"flex-end\" onClick={(e) => e.stopPropagation()}>\n {canUpdate && <EditLocale {...locale} />}\n {canDelete && !locale.isDefault && <DeleteLocale {...locale} />}\n </Flex>\n </Td>\n </Tr>\n <EditModal\n {...locale}\n onOpenChange={() => setEditLocaleId(undefined)}\n open={editLocaleId === locale.id}\n />\n </React.Fragment>\n ))}\n </Tbody>\n </Table>\n );\n};\n\nexport { LocaleTable };\nexport type { LocaleTableProps };\n"],"names":["LocaleTable","locales","canDelete","canUpdate","editLocaleId","setEditLocaleId","React","useState","formatMessage","useIntl","handleClick","localeId","_jsxs","Table","colCount","rowCount","length","_jsx","Thead","Tr","Th","Typography","variant","textColor","id","getTranslation","defaultMessage","VisuallyHidden","Tbody","map","locale","Fragment","onClick","style","cursor","Td","name","isDefault","Flex","gap","justifyContent","e","stopPropagation","EditLocale","DeleteLocale","EditModal","onOpenChange","undefined","open"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCMA,MAAAA,WAAAA,GAAc,CAAC,EAAEC,OAAAA,GAAU,EAAE,EAAEC,SAAS,EAAEC,SAAS,EAAoB,GAAA;AAC3E,IAAA,MAAM,CAACC,YAAAA,EAAcC,eAAgB,CAAA,GAAGC,iBAAMC,QAAQ,EAAA;IACtD,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;IAE1B,MAAMC,WAAAA,GAAc,CAACC,QAA2B,GAAA,IAAA;AAC9C,YAAA,IAAIR,SAAW,EAAA;gBACbE,eAAgBM,CAAAA,QAAAA,CAAAA;AAClB;AACF,SAAA;AAEA,IAAA,qBACEC,eAACC,CAAAA,kBAAAA,EAAAA;QAAMC,QAAU,EAAA,CAAA;QAAGC,QAAUd,EAAAA,OAAAA,CAAQe,MAAM,GAAG,CAAA;;0BAC7CC,cAACC,CAAAA,kBAAAA,EAAAA;AACC,gBAAA,QAAA,gBAAAN,Line truncated
+122
View File
@@ -0,0 +1,122 @@
import { jsxs, jsx } from 'react/jsx-runtime';
import * as React from 'react';
import { Table, Thead, Tr, Th, Typography, VisuallyHidden, Tbody, Td, Flex } from '@strapi/design-system';
import { useIntl } from 'react-intl';
import { getTranslation } from '../utils/getTranslation.mjs';
import { DeleteLocale } from './DeleteLocale.mjs';
import { EditLocale, EditModal } from './EditLocale.mjs';
const LocaleTable = ({ locales = [], canDelete, canUpdate })=>{
const [editLocaleId, setEditLocaleId] = React.useState();
const { formatMessage } = useIntl();
const handleClick = (localeId)=>()=>{
if (canUpdate) {
setEditLocaleId(localeId);
}
};
return /*#__PURE__*/ jsxs(Table, {
colCount: 4,
rowCount: locales.length + 1,
children: [
/*#__PURE__*/ jsx(Thead, {
children: /*#__PURE__*/ jsxs(Tr, {
children: [
/*#__PURE__*/ jsx(Th, {
children: /*#__PURE__*/ jsx(Typography, {
variant: "sigma",
textColor: "neutral600",
children: formatMessage({
id: getTranslation('Settings.locales.row.id'),
defaultMessage: 'ID'
})
})
}),
/*#__PURE__*/ jsx(Th, {
children: /*#__PURE__*/ jsx(Typography, {
variant: "sigma",
textColor: "neutral600",
children: formatMessage({
id: getTranslation('Settings.locales.row.displayName'),
defaultMessage: 'Display name'
})
})
}),
/*#__PURE__*/ jsx(Th, {
children: /*#__PURE__*/ jsx(Typography, {
variant: "sigma",
textColor: "neutral600",
children: formatMessage({
id: getTranslation('Settings.locales.row.default-locale'),
defaultMessage: 'Default locale'
})
})
}),
/*#__PURE__*/ jsx(Th, {
children: /*#__PURE__*/ jsx(VisuallyHidden, {
children: "Actions"
})
})
]
})
}),
/*#__PURE__*/ jsx(Tbody, {
children: locales.map((locale)=>/*#__PURE__*/ jsxs(React.Fragment, {
children: [
/*#__PURE__*/ jsxs(Tr, {
onClick: handleClick(locale.id),
style: {
cursor: canUpdate ? 'pointer' : 'default'
},
children: [
/*#__PURE__*/ jsx(Td, {
children: /*#__PURE__*/ jsx(Typography, {
textColor: "neutral800",
children: locale.id
})
}),
/*#__PURE__*/ jsx(Td, {
children: /*#__PURE__*/ jsx(Typography, {
textColor: "neutral800",
children: locale.name
})
}),
/*#__PURE__*/ jsx(Td, {
children: /*#__PURE__*/ jsx(Typography, {
textColor: "neutral800",
children: locale.isDefault ? formatMessage({
id: getTranslation('Settings.locales.default'),
defaultMessage: 'Default'
}) : null
})
}),
/*#__PURE__*/ jsx(Td, {
children: /*#__PURE__*/ jsxs(Flex, {
gap: 1,
justifyContent: "flex-end",
onClick: (e)=>e.stopPropagation(),
children: [
canUpdate && /*#__PURE__*/ jsx(EditLocale, {
...locale
}),
canDelete && !locale.isDefault && /*#__PURE__*/ jsx(DeleteLocale, {
...locale
})
]
})
})
]
}),
/*#__PURE__*/ jsx(EditModal, {
...locale,
onOpenChange: ()=>setEditLocaleId(undefined),
open: editLocaleId === locale.id
})
]
}, locale.id))
})
]
});
};
export { LocaleTable };
//# sourceMappingURL=LocaleTable.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"LocaleTable.mjs","sources":["../../../admin/src/components/LocaleTable.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Flex,\n Table,\n Tbody,\n Td,\n Th,\n Thead,\n Tr,\n Typography,\n VisuallyHidden,\n} from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getTranslation } from '../utils/getTranslation';\n\nimport { DeleteLocale } from './DeleteLocale';\nimport { EditLocale, EditModal } from './EditLocale';\n\nimport type { Locale } from '../../../shared/contracts/locales';\n\n/* -------------------------------------------------------------------------------------------------\n * LocaleTable\n * -----------------------------------------------------------------------------------------------*/\n\ntype LocaleTableProps = {\n locales?: Locale[];\n canDelete?: boolean;\n canUpdate?: boolean;\n onDeleteLocale?: (locale: Locale) => void;\n onEditLocale?: (locale: Locale) => void;\n};\n\nconst LocaleTable = ({ locales = [], canDelete, canUpdate }: LocaleTableProps) => {\n const [editLocaleId, setEditLocaleId] = React.useState<Locale['id']>();\n const { formatMessage } = useIntl();\n\n const handleClick = (localeId: Locale['id']) => () => {\n if (canUpdate) {\n setEditLocaleId(localeId);\n }\n };\n\n return (\n <Table colCount={4} rowCount={locales.length + 1}>\n <Thead>\n <Tr>\n <Th>\n <Typography variant=\"sigma\" textColor=\"neutral600\">\n {formatMessage({\n id: getTranslation('Settings.locales.row.id'),\n defaultMessage: 'ID',\n })}\n </Typography>\n </Th>\n <Th>\n <Typography variant=\"sigma\" textColor=\"neutral600\">\n {formatMessage({\n id: getTranslation('Settings.locales.row.displayName'),\n defaultMessage: 'Display name',\n })}\n </Typography>\n </Th>\n <Th>\n <Typography variant=\"sigma\" textColor=\"neutral600\">\n {formatMessage({\n id: getTranslation('Settings.locales.row.default-locale'),\n defaultMessage: 'Default locale',\n })}\n </Typography>\n </Th>\n <Th>\n <VisuallyHidden>Actions</VisuallyHidden>\n </Th>\n </Tr>\n </Thead>\n <Tbody>\n {locales.map((locale) => (\n <React.Fragment key={locale.id}>\n <Tr\n onClick={handleClick(locale.id)}\n style={{ cursor: canUpdate ? 'pointer' : 'default' }}\n >\n <Td>\n <Typography textColor=\"neutral800\">{locale.id}</Typography>\n </Td>\n <Td>\n <Typography textColor=\"neutral800\">{locale.name}</Typography>\n </Td>\n <Td>\n <Typography textColor=\"neutral800\">\n {locale.isDefault\n ? formatMessage({\n id: getTranslation('Settings.locales.default'),\n defaultMessage: 'Default',\n })\n : null}\n </Typography>\n </Td>\n <Td>\n <Flex gap={1} justifyContent=\"flex-end\" onClick={(e) => e.stopPropagation()}>\n {canUpdate && <EditLocale {...locale} />}\n {canDelete && !locale.isDefault && <DeleteLocale {...locale} />}\n </Flex>\n </Td>\n </Tr>\n <EditModal\n {...locale}\n onOpenChange={() => setEditLocaleId(undefined)}\n open={editLocaleId === locale.id}\n />\n </React.Fragment>\n ))}\n </Tbody>\n </Table>\n );\n};\n\nexport { LocaleTable };\nexport type { LocaleTableProps };\n"],"names":["LocaleTable","locales","canDelete","canUpdate","editLocaleId","setEditLocaleId","React","useState","formatMessage","useIntl","handleClick","localeId","_jsxs","Table","colCount","rowCount","length","_jsx","Thead","Tr","Th","Typography","variant","textColor","id","getTranslation","defaultMessage","VisuallyHidden","Tbody","map","locale","Fragment","onClick","style","cursor","Td","name","isDefault","Flex","gap","justifyContent","e","stopPropagation","EditLocale","DeleteLocale","EditModal","onOpenChange","undefined","open"],"mappings":";;;;;;;;AAkCMA,MAAAA,WAAAA,GAAc,CAAC,EAAEC,OAAAA,GAAU,EAAE,EAAEC,SAAS,EAAEC,SAAS,EAAoB,GAAA;AAC3E,IAAA,MAAM,CAACC,YAAAA,EAAcC,eAAgB,CAAA,GAAGC,MAAMC,QAAQ,EAAA;IACtD,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;IAE1B,MAAMC,WAAAA,GAAc,CAACC,QAA2B,GAAA,IAAA;AAC9C,YAAA,IAAIR,SAAW,EAAA;gBACbE,eAAgBM,CAAAA,QAAAA,CAAAA;AAClB;AACF,SAAA;AAEA,IAAA,qBACEC,IAACC,CAAAA,KAAAA,EAAAA;QAAMC,QAAU,EAAA,CAAA;QAAGC,QAAUd,EAAAA,OAAAA,CAAQe,MAAM,GAAG,CAAA;;0BAC7CC,GAACC,CAAAA,KAAAA,EAAAA;AACC,gBAAA,QAAA,gBAAAN,IAACO,CAAAA,EAAAA,EAAAA;Line truncated