@strapi/i18n 0.0.0-experimental.da85533897155e719d784f0271223c866d2f69ab → 0.0.0-experimental.dd1d47ef78ef6cfec4ed62576108500bd9f13740
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{SettingsPage-DW0GwDcD.mjs → SettingsPage-BHvunuIF.mjs} +4 -4
- package/dist/_chunks/SettingsPage-BHvunuIF.mjs.map +1 -0
- package/dist/_chunks/{SettingsPage-a96ZyFLy.js → SettingsPage-Bcj7380u.js} +4 -4
- package/dist/_chunks/SettingsPage-Bcj7380u.js.map +1 -0
- package/dist/_chunks/{en-BsOU9o5z.js → en-BKBz3tro.js} +10 -3
- package/dist/_chunks/en-BKBz3tro.js.map +1 -0
- package/dist/_chunks/{en-CM6Pjfyv.mjs → en-DlXfy6Gy.mjs} +10 -3
- package/dist/_chunks/en-DlXfy6Gy.mjs.map +1 -0
- package/dist/_chunks/{index-sfNkjx75.js → index-BKZbxhpm.js} +383 -94
- package/dist/_chunks/index-BKZbxhpm.js.map +1 -0
- package/dist/_chunks/{index-4KJn181Q.mjs → index-DUdrr5PR.mjs} +386 -97
- package/dist/_chunks/index-DUdrr5PR.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/BulkLocaleActionModal.d.ts +2 -1
- package/dist/admin/src/components/CMHeaderActions.d.ts +29 -3
- package/dist/admin/src/components/CreateLocale.d.ts +6 -6
- package/dist/admin/src/utils/clean.d.ts +4 -0
- package/dist/server/index.js +389 -485
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +391 -487
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts +1 -4
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +7 -11
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +6 -8
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/sanitize/index.d.ts +11 -0
- package/dist/server/src/services/sanitize/index.d.ts.map +1 -0
- package/dist/server/src/utils/index.d.ts +2 -2
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/package.json +10 -10
- package/dist/_chunks/SettingsPage-DW0GwDcD.mjs.map +0 -1
- package/dist/_chunks/SettingsPage-a96ZyFLy.js.map +0 -1
- package/dist/_chunks/en-BsOU9o5z.js.map +0 -1
- package/dist/_chunks/en-CM6Pjfyv.mjs.map +0 -1
- package/dist/_chunks/index-4KJn181Q.mjs.map +0 -1
- package/dist/_chunks/index-sfNkjx75.js.map +0 -1
- package/dist/server/src/migrations/content-type/disable/index.d.ts +0 -3
- package/dist/server/src/migrations/content-type/disable/index.d.ts.map +0 -1
- package/dist/server/src/migrations/content-type/enable/index.d.ts +0 -3
- package/dist/server/src/migrations/content-type/enable/index.d.ts.map +0 -1
- package/dist/server/src/services/entity-service-decorator.d.ts +0 -29
- package/dist/server/src/services/entity-service-decorator.d.ts.map +0 -1
- package/strapi-server.js +0 -3
@@ -1,13 +1,13 @@
|
|
1
1
|
import get from "lodash/get";
|
2
2
|
import * as yup from "yup";
|
3
|
-
import { jsxs, jsx } from "react/jsx-runtime";
|
3
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
4
4
|
import * as React from "react";
|
5
5
|
import { Typography, Dialog, Field, Checkbox, Flex, Button, Modal, Box, Status, IconButton, Tooltip, SingleSelect, SingleSelectOption, VisuallyHidden, useCollator, Popover } from "@strapi/design-system";
|
6
|
-
import { WarningCircle, Pencil, CrossCircle, CheckCircle, ArrowsCounterClockwise, Trash, ListPlus, Earth, EarthStriked, CaretDown } from "@strapi/icons";
|
6
|
+
import { WarningCircle, Pencil, CrossCircle, CheckCircle, ArrowsCounterClockwise, Trash, Plus, Download, ListPlus, Cross, Earth, EarthStriked, CaretDown } from "@strapi/icons";
|
7
7
|
import { useIntl } from "react-intl";
|
8
8
|
import { styled } from "styled-components";
|
9
9
|
import { skipToken } from "@reduxjs/toolkit/query";
|
10
|
-
import { useAuth, adminApi, useTable, Table, useQueryParams, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
|
10
|
+
import { useAuth, adminApi, useTable, Table, useQueryParams, useForm, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
|
11
11
|
import { unstable_useDocument, unstable_useDocumentActions, buildValidParams } from "@strapi/content-manager/strapi-admin";
|
12
12
|
import { useParams, Link, useNavigate, matchPath } from "react-router-dom";
|
13
13
|
import * as qs from "qs";
|
@@ -217,10 +217,94 @@ const relationsApi = i18nApi.injectEndpoints({
|
|
217
217
|
})
|
218
218
|
});
|
219
219
|
const { useGetManyDraftRelationCountQuery } = relationsApi;
|
220
|
+
const cleanData = (data, schema, components) => {
|
221
|
+
const cleanedData = removeFields(data, [
|
222
|
+
"createdAt",
|
223
|
+
"createdBy",
|
224
|
+
"updatedAt",
|
225
|
+
"updatedBy",
|
226
|
+
"id",
|
227
|
+
"documentId",
|
228
|
+
"publishedAt",
|
229
|
+
"strapi_stage",
|
230
|
+
"strapi_assignee",
|
231
|
+
"locale",
|
232
|
+
"status"
|
233
|
+
]);
|
234
|
+
const cleanedDataWithoutPasswordAndRelation = recursiveRemoveFieldTypes(
|
235
|
+
cleanedData,
|
236
|
+
schema,
|
237
|
+
components,
|
238
|
+
["relation", "password"]
|
239
|
+
);
|
240
|
+
return cleanedDataWithoutPasswordAndRelation;
|
241
|
+
};
|
242
|
+
const removeFields = (data, fields) => {
|
243
|
+
return Object.keys(data).reduce((acc, current) => {
|
244
|
+
if (fields.includes(current)) {
|
245
|
+
return acc;
|
246
|
+
}
|
247
|
+
acc[current] = data[current];
|
248
|
+
return acc;
|
249
|
+
}, {});
|
250
|
+
};
|
251
|
+
const recursiveRemoveFieldTypes = (data, schema, components, fields) => {
|
252
|
+
return Object.keys(data).reduce((acc, current) => {
|
253
|
+
const attribute = schema.attributes[current] ?? { type: void 0 };
|
254
|
+
if (fields.includes(attribute.type)) {
|
255
|
+
return acc;
|
256
|
+
}
|
257
|
+
if (attribute.type === "dynamiczone") {
|
258
|
+
acc[current] = data[current].map((componentValue, index2) => {
|
259
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
260
|
+
componentValue,
|
261
|
+
components[componentValue.__component],
|
262
|
+
components,
|
263
|
+
fields
|
264
|
+
);
|
265
|
+
return {
|
266
|
+
...rest,
|
267
|
+
__temp_key__: index2 + 1
|
268
|
+
};
|
269
|
+
});
|
270
|
+
} else if (attribute.type === "component") {
|
271
|
+
const { repeatable, component } = attribute;
|
272
|
+
if (repeatable) {
|
273
|
+
acc[current] = (data[current] ?? []).map((compoData, index2) => {
|
274
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
275
|
+
compoData,
|
276
|
+
components[component],
|
277
|
+
components,
|
278
|
+
fields
|
279
|
+
);
|
280
|
+
return {
|
281
|
+
...rest,
|
282
|
+
__temp_key__: index2 + 1
|
283
|
+
};
|
284
|
+
});
|
285
|
+
} else {
|
286
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
287
|
+
data[current] ?? {},
|
288
|
+
components[component],
|
289
|
+
components,
|
290
|
+
fields
|
291
|
+
);
|
292
|
+
acc[current] = rest;
|
293
|
+
}
|
294
|
+
} else {
|
295
|
+
acc[current] = data[current];
|
296
|
+
}
|
297
|
+
return acc;
|
298
|
+
}, {});
|
299
|
+
};
|
220
300
|
const isErrorMessageDescriptor = (object) => {
|
221
301
|
return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
|
222
302
|
};
|
223
|
-
const EntryValidationText = ({
|
303
|
+
const EntryValidationText = ({
|
304
|
+
status = "draft",
|
305
|
+
validationErrors,
|
306
|
+
action
|
307
|
+
}) => {
|
224
308
|
const { formatMessage } = useIntl();
|
225
309
|
const getErrorStr = (key, value) => {
|
226
310
|
if (typeof value === "string") {
|
@@ -254,30 +338,63 @@ const EntryValidationText = ({ status = "draft", validationErrors }) => {
|
|
254
338
|
) })
|
255
339
|
] });
|
256
340
|
}
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
341
|
+
const getStatusMessage = () => {
|
342
|
+
if (action === "bulk-publish") {
|
343
|
+
if (status === "published") {
|
344
|
+
return {
|
345
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
346
|
+
text: formatMessage({
|
347
|
+
id: "content-manager.bulk-publish.already-published",
|
348
|
+
defaultMessage: "Already Published"
|
349
|
+
}),
|
350
|
+
textColor: "success600",
|
351
|
+
fontWeight: "bold"
|
352
|
+
};
|
353
|
+
} else if (status === "modified") {
|
354
|
+
return {
|
355
|
+
icon: /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
|
356
|
+
text: formatMessage({
|
357
|
+
id: "app.utils.ready-to-publish-changes",
|
358
|
+
defaultMessage: "Ready to publish changes"
|
359
|
+
})
|
360
|
+
};
|
361
|
+
} else {
|
362
|
+
return {
|
363
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
364
|
+
text: formatMessage({
|
365
|
+
id: "app.utils.ready-to-publish",
|
366
|
+
defaultMessage: "Ready to publish"
|
367
|
+
})
|
368
|
+
};
|
369
|
+
}
|
370
|
+
} else {
|
371
|
+
if (status === "draft") {
|
372
|
+
return {
|
373
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
374
|
+
text: formatMessage({
|
375
|
+
id: "content-manager.bulk-unpublish.already-unpublished",
|
376
|
+
defaultMessage: "Already Unpublished"
|
377
|
+
}),
|
378
|
+
textColor: "success600",
|
379
|
+
fontWeight: "bold"
|
380
|
+
};
|
381
|
+
} else {
|
382
|
+
return {
|
383
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
384
|
+
text: formatMessage({
|
385
|
+
id: "app.utils.ready-to-unpublish-changes",
|
386
|
+
defaultMessage: "Ready to unpublish"
|
387
|
+
}),
|
388
|
+
textColor: "success600",
|
389
|
+
fontWeight: "bold"
|
390
|
+
};
|
391
|
+
}
|
392
|
+
}
|
393
|
+
};
|
394
|
+
const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
|
275
395
|
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
276
|
-
|
277
|
-
/* @__PURE__ */ jsx(Typography, { children:
|
278
|
-
id: "app.utils.ready-to-publish",
|
279
|
-
defaultMessage: "Ready to publish"
|
280
|
-
}) })
|
396
|
+
icon,
|
397
|
+
/* @__PURE__ */ jsx(Typography, { textColor, fontWeight, children: text })
|
281
398
|
] });
|
282
399
|
};
|
283
400
|
const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
@@ -285,7 +402,8 @@ const BulkLocaleActionModal = ({
|
|
285
402
|
headers,
|
286
403
|
rows,
|
287
404
|
localesMetadata,
|
288
|
-
validationErrors = {}
|
405
|
+
validationErrors = {},
|
406
|
+
action
|
289
407
|
}) => {
|
290
408
|
const { formatMessage } = useIntl();
|
291
409
|
const selectedRows = useTable(
|
@@ -298,22 +416,24 @@ const BulkLocaleActionModal = ({
|
|
298
416
|
return acc;
|
299
417
|
}, {});
|
300
418
|
const localesWithErrors = Object.keys(validationErrors);
|
301
|
-
const
|
419
|
+
const publishedCount = selectedRows.filter(
|
302
420
|
({ locale }) => currentStatusByLocale[locale] === "published"
|
303
421
|
).length;
|
304
|
-
const
|
422
|
+
const draftCount = selectedRows.filter(
|
305
423
|
({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
|
306
424
|
).length;
|
307
425
|
const withErrorsCount = localesWithErrors.length;
|
426
|
+
const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
|
427
|
+
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.";
|
308
428
|
return formatMessage(
|
309
429
|
{
|
310
|
-
id:
|
311
|
-
defaultMessage
|
430
|
+
id: messageId,
|
431
|
+
defaultMessage
|
312
432
|
},
|
313
433
|
{
|
314
434
|
withErrorsCount,
|
315
|
-
|
316
|
-
|
435
|
+
draftCount,
|
436
|
+
publishedCount,
|
317
437
|
b: BoldChunk
|
318
438
|
}
|
319
439
|
);
|
@@ -345,7 +465,7 @@ const BulkLocaleActionModal = ({
|
|
345
465
|
children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
|
346
466
|
}
|
347
467
|
) }) }),
|
348
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status }) }),
|
468
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status, action }) }),
|
349
469
|
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
350
470
|
IconButton,
|
351
471
|
{
|
@@ -371,6 +491,48 @@ const BulkLocaleActionModal = ({
|
|
371
491
|
] }) })
|
372
492
|
] });
|
373
493
|
};
|
494
|
+
const statusVariants = {
|
495
|
+
draft: "secondary",
|
496
|
+
published: "success",
|
497
|
+
modified: "alternative"
|
498
|
+
};
|
499
|
+
const LocaleOption = ({
|
500
|
+
isDraftAndPublishEnabled,
|
501
|
+
locale,
|
502
|
+
status,
|
503
|
+
entryExists
|
504
|
+
}) => {
|
505
|
+
const { formatMessage } = useIntl();
|
506
|
+
if (!entryExists) {
|
507
|
+
return formatMessage(
|
508
|
+
{
|
509
|
+
id: getTranslation("CMEditViewLocalePicker.locale.create"),
|
510
|
+
defaultMessage: "Create <bold>{locale}</bold> locale"
|
511
|
+
},
|
512
|
+
{
|
513
|
+
bold: (locale2) => /* @__PURE__ */ jsx("b", { children: locale2 }),
|
514
|
+
locale: locale.name
|
515
|
+
}
|
516
|
+
);
|
517
|
+
}
|
518
|
+
return /* @__PURE__ */ jsxs(Flex, { width: "100%", gap: 1, justifyContent: "space-between", children: [
|
519
|
+
/* @__PURE__ */ jsx(Typography, { children: locale.name }),
|
520
|
+
isDraftAndPublishEnabled ? /* @__PURE__ */ jsx(
|
521
|
+
Status,
|
522
|
+
{
|
523
|
+
display: "flex",
|
524
|
+
paddingLeft: "6px",
|
525
|
+
paddingRight: "6px",
|
526
|
+
paddingTop: "2px",
|
527
|
+
paddingBottom: "2px",
|
528
|
+
showBullet: false,
|
529
|
+
size: "S",
|
530
|
+
variant: statusVariants[status],
|
531
|
+
children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
|
532
|
+
}
|
533
|
+
) : null
|
534
|
+
] });
|
535
|
+
};
|
374
536
|
const LocalePickerAction = ({
|
375
537
|
document,
|
376
538
|
meta,
|
@@ -382,7 +544,13 @@ const LocalePickerAction = ({
|
|
382
544
|
const [{ query }, setQuery] = useQueryParams();
|
383
545
|
const { hasI18n, canCreate, canRead } = useI18n();
|
384
546
|
const { data: locales = [] } = useGetLocalesQuery();
|
385
|
-
const
|
547
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
548
|
+
const { schema } = unstable_useDocument({
|
549
|
+
model,
|
550
|
+
collectionType,
|
551
|
+
documentId,
|
552
|
+
params: { locale: currentDesiredLocale }
|
553
|
+
});
|
386
554
|
const handleSelect = React.useCallback(
|
387
555
|
(value) => {
|
388
556
|
setQuery({
|
@@ -400,53 +568,47 @@ const LocalePickerAction = ({
|
|
400
568
|
if (!Array.isArray(locales) || !hasI18n) {
|
401
569
|
return;
|
402
570
|
}
|
403
|
-
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
404
571
|
const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
|
405
572
|
const defaultLocale = locales.find((locale) => locale.isDefault);
|
406
573
|
if (!doesLocaleExist && defaultLocale?.code) {
|
407
574
|
handleSelect(defaultLocale.code);
|
408
575
|
}
|
409
|
-
}, [handleSelect, hasI18n, locales,
|
410
|
-
|
411
|
-
return null;
|
412
|
-
}
|
413
|
-
const currentLocale = query.plugins?.i18n?.locale || locales.find((loc) => loc.isDefault)?.code;
|
576
|
+
}, [handleSelect, hasI18n, locales, currentDesiredLocale]);
|
577
|
+
const currentLocale = Array.isArray(locales) ? locales.find((locale) => locale.code === currentDesiredLocale) : void 0;
|
414
578
|
const allCurrentLocales = [
|
415
|
-
{ status: getDocumentStatus(document, meta), locale: currentLocale },
|
579
|
+
{ status: getDocumentStatus(document, meta), locale: currentLocale?.code },
|
416
580
|
...meta?.availableLocales ?? []
|
417
581
|
];
|
582
|
+
if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
|
583
|
+
return null;
|
584
|
+
}
|
418
585
|
return {
|
419
586
|
label: formatMessage({
|
420
587
|
id: getTranslation("Settings.locales.modal.locales.label"),
|
421
588
|
defaultMessage: "Locales"
|
422
589
|
}),
|
423
590
|
options: locales.map((locale) => {
|
591
|
+
const entryWithLocaleExists = allCurrentLocales.some((doc) => doc.locale === locale.code);
|
424
592
|
const currentLocaleDoc = allCurrentLocales.find(
|
425
593
|
(doc) => "locale" in doc ? doc.locale === locale.code : false
|
426
594
|
);
|
427
|
-
const
|
428
|
-
const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
|
429
|
-
const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
|
595
|
+
const permissionsToCheck = currentLocaleDoc ? canRead : canCreate;
|
430
596
|
return {
|
431
597
|
disabled: !permissionsToCheck.includes(locale.code),
|
432
598
|
value: locale.code,
|
433
|
-
label:
|
434
|
-
|
435
|
-
Status,
|
599
|
+
label: /* @__PURE__ */ jsx(
|
600
|
+
LocaleOption,
|
436
601
|
{
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
paddingBottom: "2px",
|
442
|
-
showBullet: false,
|
443
|
-
size: "S",
|
444
|
-
variant: statusVariant,
|
445
|
-
children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
|
602
|
+
isDraftAndPublishEnabled: !!schema?.options?.draftAndPublish,
|
603
|
+
locale,
|
604
|
+
status: currentLocaleDoc?.status,
|
605
|
+
entryExists: entryWithLocaleExists
|
446
606
|
}
|
447
|
-
)
|
607
|
+
),
|
608
|
+
startIcon: !entryWithLocaleExists ? /* @__PURE__ */ jsx(Plus, {}) : null
|
448
609
|
};
|
449
610
|
}),
|
611
|
+
customizeContent: () => currentLocale?.name,
|
450
612
|
onSelect: handleSelect,
|
451
613
|
value: currentLocale
|
452
614
|
};
|
@@ -462,6 +624,99 @@ const getDocumentStatus = (document, meta) => {
|
|
462
624
|
}
|
463
625
|
return docStatus;
|
464
626
|
};
|
627
|
+
const FillFromAnotherLocaleAction = ({
|
628
|
+
documentId,
|
629
|
+
meta,
|
630
|
+
model,
|
631
|
+
collectionType
|
632
|
+
}) => {
|
633
|
+
const { formatMessage } = useIntl();
|
634
|
+
const [{ query }] = useQueryParams();
|
635
|
+
const { hasI18n } = useI18n();
|
636
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
637
|
+
const [localeSelected, setLocaleSelected] = React.useState(null);
|
638
|
+
const setValues = useForm("FillFromAnotherLocale", (state) => state.setValues);
|
639
|
+
const { getDocument } = unstable_useDocumentActions();
|
640
|
+
const { schema, components } = unstable_useDocument({
|
641
|
+
model,
|
642
|
+
documentId,
|
643
|
+
collectionType,
|
644
|
+
params: { locale: currentDesiredLocale }
|
645
|
+
});
|
646
|
+
const { data: locales = [] } = useGetLocalesQuery();
|
647
|
+
const availableLocales = Array.isArray(locales) ? locales.filter((locale) => meta?.availableLocales.some((l) => l.locale === locale.code)) : [];
|
648
|
+
const fillFromLocale = (onClose) => async () => {
|
649
|
+
const response = await getDocument({
|
650
|
+
collectionType,
|
651
|
+
model,
|
652
|
+
documentId,
|
653
|
+
params: { locale: localeSelected }
|
654
|
+
});
|
655
|
+
if (!response || !schema) {
|
656
|
+
return;
|
657
|
+
}
|
658
|
+
const { data } = response;
|
659
|
+
const cleanedData = cleanData(data, schema, components);
|
660
|
+
setValues(cleanedData);
|
661
|
+
onClose();
|
662
|
+
};
|
663
|
+
if (!hasI18n) {
|
664
|
+
return null;
|
665
|
+
}
|
666
|
+
return {
|
667
|
+
type: "icon",
|
668
|
+
icon: /* @__PURE__ */ jsx(Download, {}),
|
669
|
+
disabled: availableLocales.length === 0,
|
670
|
+
label: formatMessage({
|
671
|
+
id: getTranslation("CMEditViewCopyLocale.copy-text"),
|
672
|
+
defaultMessage: "Fill in from another locale"
|
673
|
+
}),
|
674
|
+
dialog: {
|
675
|
+
type: "dialog",
|
676
|
+
title: formatMessage({
|
677
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.title"),
|
678
|
+
defaultMessage: "Confirmation"
|
679
|
+
}),
|
680
|
+
content: ({ onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
681
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
|
682
|
+
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
683
|
+
/* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
|
684
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.body"),
|
685
|
+
defaultMessage: "Your current content will be erased and filled by the content of the selected locale:"
|
686
|
+
}) }),
|
687
|
+
/* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
|
688
|
+
/* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
|
689
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.field.label"),
|
690
|
+
defaultMessage: "Locale"
|
691
|
+
}) }),
|
692
|
+
/* @__PURE__ */ jsx(
|
693
|
+
SingleSelect,
|
694
|
+
{
|
695
|
+
value: localeSelected,
|
696
|
+
placeholder: formatMessage({
|
697
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.field.placeholder"),
|
698
|
+
defaultMessage: "Select one locale..."
|
699
|
+
}),
|
700
|
+
onChange: (value) => setLocaleSelected(value),
|
701
|
+
children: availableLocales.map((locale) => /* @__PURE__ */ jsx(SingleSelectOption, { value: locale.code, children: locale.name }, locale.code))
|
702
|
+
}
|
703
|
+
)
|
704
|
+
] })
|
705
|
+
] }) }),
|
706
|
+
/* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, width: "100%", children: [
|
707
|
+
/* @__PURE__ */ jsx(Button, { flex: "auto", variant: "tertiary", onClick: onClose, children: formatMessage({
|
708
|
+
id: getTranslation("CMEditViewCopyLocale.cancel-text"),
|
709
|
+
defaultMessage: "No, cancel"
|
710
|
+
}) }),
|
711
|
+
/* @__PURE__ */ jsx(Button, { flex: "auto", variant: "success", onClick: fillFromLocale(onClose), children: formatMessage({
|
712
|
+
id: getTranslation("CMEditViewCopyLocale.submit-text"),
|
713
|
+
defaultMessage: "Yes, fill in"
|
714
|
+
}) })
|
715
|
+
] }) })
|
716
|
+
] })
|
717
|
+
}
|
718
|
+
};
|
719
|
+
};
|
465
720
|
const DeleteLocaleAction = ({
|
466
721
|
document,
|
467
722
|
documentId,
|
@@ -473,16 +728,23 @@ const DeleteLocaleAction = ({
|
|
473
728
|
const { toggleNotification } = useNotification();
|
474
729
|
const { delete: deleteAction } = unstable_useDocumentActions();
|
475
730
|
const { hasI18n, canDelete } = useI18n();
|
731
|
+
const [{ query }] = useQueryParams();
|
732
|
+
const { data: locales = [] } = useGetLocalesQuery();
|
733
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
734
|
+
const locale = !("error" in locales) && locales.find((loc) => loc.code === currentDesiredLocale);
|
476
735
|
if (!hasI18n) {
|
477
736
|
return null;
|
478
737
|
}
|
479
738
|
return {
|
480
739
|
disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
|
481
740
|
position: ["header", "table-row"],
|
482
|
-
label: formatMessage(
|
483
|
-
|
484
|
-
|
485
|
-
|
741
|
+
label: formatMessage(
|
742
|
+
{
|
743
|
+
id: getTranslation("actions.delete.label"),
|
744
|
+
defaultMessage: "Delete entry ({locale})"
|
745
|
+
},
|
746
|
+
{ locale: locale && locale.name }
|
747
|
+
),
|
486
748
|
icon: /* @__PURE__ */ jsx(StyledTrash, {}),
|
487
749
|
variant: "danger",
|
488
750
|
dialog: {
|
@@ -499,7 +761,12 @@ const DeleteLocaleAction = ({
|
|
499
761
|
}) })
|
500
762
|
] }),
|
501
763
|
onConfirm: async () => {
|
502
|
-
|
764
|
+
const unableToDelete = (
|
765
|
+
// We are unable to delete a collection type without a document ID
|
766
|
+
// & unable to delete generally if there is no document locale
|
767
|
+
collectionType !== "single-types" && !documentId || !document?.locale
|
768
|
+
);
|
769
|
+
if (unableToDelete) {
|
503
770
|
console.error(
|
504
771
|
"You're trying to delete a document without an id or locale, this is likely a bug with Strapi. Please open an issue."
|
505
772
|
);
|
@@ -525,23 +792,24 @@ const DeleteLocaleAction = ({
|
|
525
792
|
}
|
526
793
|
};
|
527
794
|
};
|
528
|
-
const
|
795
|
+
const BulkLocaleAction = ({
|
529
796
|
document: baseDocument,
|
530
797
|
documentId,
|
531
798
|
model,
|
532
|
-
collectionType
|
799
|
+
collectionType,
|
800
|
+
action
|
533
801
|
}) => {
|
534
802
|
const baseLocale = baseDocument?.locale ?? null;
|
535
803
|
const [{ query }] = useQueryParams();
|
536
804
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
537
|
-
const
|
805
|
+
const isOnPublishedTab = query.status === "published";
|
538
806
|
const { formatMessage } = useIntl();
|
539
807
|
const { hasI18n, canPublish } = useI18n();
|
540
808
|
const { toggleNotification } = useNotification();
|
541
809
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
542
810
|
const [selectedRows, setSelectedRows] = React.useState([]);
|
543
811
|
const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
|
544
|
-
const { publishMany: publishManyAction } = unstable_useDocumentActions();
|
812
|
+
const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
|
545
813
|
const {
|
546
814
|
document,
|
547
815
|
meta: documentMeta,
|
@@ -557,7 +825,7 @@ const BulkLocalePublishAction = ({
|
|
557
825
|
}
|
558
826
|
},
|
559
827
|
{
|
560
|
-
skip: !hasI18n
|
828
|
+
skip: !hasI18n || !baseLocale
|
561
829
|
}
|
562
830
|
);
|
563
831
|
const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : skipToken);
|
@@ -609,12 +877,19 @@ const BulkLocalePublishAction = ({
|
|
609
877
|
}, {});
|
610
878
|
return [rowsFromMeta, errors];
|
611
879
|
}, [document, documentMeta?.availableLocales, validate]);
|
612
|
-
const
|
613
|
-
|
880
|
+
const isBulkPublish = action === "bulk-publish";
|
881
|
+
const localesForAction = selectedRows.reduce((acc, selectedRow) => {
|
882
|
+
const isValidLocale = (
|
883
|
+
// Validation errors are irrelevant if we are trying to unpublish
|
884
|
+
!isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
|
885
|
+
);
|
886
|
+
const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
|
887
|
+
if (shouldAddLocale) {
|
614
888
|
acc.push(selectedRow.locale);
|
615
889
|
}
|
616
890
|
return acc;
|
617
891
|
}, []);
|
892
|
+
const enableDraftRelationsCount = false;
|
618
893
|
const {
|
619
894
|
data: draftRelationsCount = 0,
|
620
895
|
isLoading: isDraftRelationsLoading,
|
@@ -623,10 +898,10 @@ const BulkLocalePublishAction = ({
|
|
623
898
|
{
|
624
899
|
model,
|
625
900
|
documentIds: [documentId],
|
626
|
-
locale:
|
901
|
+
locale: localesForAction
|
627
902
|
},
|
628
903
|
{
|
629
|
-
skip: !
|
904
|
+
skip: !enableDraftRelationsCount
|
630
905
|
}
|
631
906
|
);
|
632
907
|
React.useEffect(() => {
|
@@ -652,7 +927,18 @@ const BulkLocalePublishAction = ({
|
|
652
927
|
documentIds: [documentId],
|
653
928
|
params: {
|
654
929
|
...params,
|
655
|
-
locale:
|
930
|
+
locale: localesForAction
|
931
|
+
}
|
932
|
+
});
|
933
|
+
setSelectedRows([]);
|
934
|
+
};
|
935
|
+
const unpublish = async () => {
|
936
|
+
await unpublishManyAction({
|
937
|
+
model,
|
938
|
+
documentIds: [documentId],
|
939
|
+
params: {
|
940
|
+
...params,
|
941
|
+
locale: localesForAction
|
656
942
|
}
|
657
943
|
});
|
658
944
|
setSelectedRows([]);
|
@@ -660,14 +946,12 @@ const BulkLocalePublishAction = ({
|
|
660
946
|
const handleAction = async () => {
|
661
947
|
if (draftRelationsCount > 0) {
|
662
948
|
setIsDraftRelationConfirmationOpen(true);
|
663
|
-
} else {
|
949
|
+
} else if (isBulkPublish) {
|
664
950
|
await publish();
|
951
|
+
} else {
|
952
|
+
await unpublish();
|
665
953
|
}
|
666
954
|
};
|
667
|
-
const isUnpublish = document?.status === "published";
|
668
|
-
if (isUnpublish) {
|
669
|
-
console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
|
670
|
-
}
|
671
955
|
if (isDraftRelationConfirmationOpen) {
|
672
956
|
return {
|
673
957
|
label: formatMessage({
|
@@ -705,18 +989,18 @@ const BulkLocalePublishAction = ({
|
|
705
989
|
const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
|
706
990
|
return {
|
707
991
|
label: formatMessage({
|
708
|
-
id: getTranslation("
|
709
|
-
defaultMessage: "Publish Multiple Locales
|
992
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
993
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
710
994
|
}),
|
711
|
-
|
712
|
-
|
995
|
+
variant: isBulkPublish ? "secondary" : "danger",
|
996
|
+
icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
|
997
|
+
disabled: isOnPublishedTab || canPublish.length === 0,
|
713
998
|
position: ["panel"],
|
714
|
-
variant: "secondary",
|
715
999
|
dialog: {
|
716
1000
|
type: "modal",
|
717
1001
|
title: formatMessage({
|
718
|
-
id: getTranslation("
|
719
|
-
defaultMessage: "Publish Multiple Locales
|
1002
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
1003
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
720
1004
|
}),
|
721
1005
|
content: () => {
|
722
1006
|
return /* @__PURE__ */ jsx(
|
@@ -735,7 +1019,8 @@ const BulkLocalePublishAction = ({
|
|
735
1019
|
validationErrors,
|
736
1020
|
headers,
|
737
1021
|
rows,
|
738
|
-
localesMetadata
|
1022
|
+
localesMetadata,
|
1023
|
+
action: action ?? "bulk-publish"
|
739
1024
|
}
|
740
1025
|
)
|
741
1026
|
}
|
@@ -745,18 +1030,24 @@ const BulkLocalePublishAction = ({
|
|
745
1030
|
Button,
|
746
1031
|
{
|
747
1032
|
loading: isDraftRelationsLoading,
|
748
|
-
disabled: !hasPermission ||
|
1033
|
+
disabled: !hasPermission || localesForAction.length === 0,
|
749
1034
|
variant: "default",
|
750
1035
|
onClick: handleAction,
|
751
1036
|
children: formatMessage({
|
752
|
-
id: "app.utils.publish",
|
753
|
-
defaultMessage: "Publish"
|
1037
|
+
id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
|
1038
|
+
defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
|
754
1039
|
})
|
755
1040
|
}
|
756
1041
|
) })
|
757
1042
|
}
|
758
1043
|
};
|
759
1044
|
};
|
1045
|
+
const BulkLocalePublishAction = (props) => {
|
1046
|
+
return BulkLocaleAction({ action: "bulk-publish", ...props });
|
1047
|
+
};
|
1048
|
+
const BulkLocaleUnpublishAction = (props) => {
|
1049
|
+
return BulkLocaleAction({ action: "bulk-unpublish", ...props });
|
1050
|
+
};
|
760
1051
|
const StyledTrash = styled(Trash)`
|
761
1052
|
path {
|
762
1053
|
fill: currentColor;
|
@@ -1108,9 +1399,6 @@ const localeMiddleware = (ctx) => (next) => (permissions) => {
|
|
1108
1399
|
return next(revisedPermissions);
|
1109
1400
|
};
|
1110
1401
|
const prefixPluginTranslations = (trad, pluginId2) => {
|
1111
|
-
if (!pluginId2) {
|
1112
|
-
throw new TypeError("pluginId can't be empty");
|
1113
|
-
}
|
1114
1402
|
return Object.keys(trad).reduce((acc, current) => {
|
1115
1403
|
acc[`${pluginId2}.${current}`] = trad[current];
|
1116
1404
|
return acc;
|
@@ -1180,11 +1468,11 @@ const index = {
|
|
1180
1468
|
},
|
1181
1469
|
id: "internationalization",
|
1182
1470
|
to: "internationalization",
|
1183
|
-
Component: () => import("./SettingsPage-
|
1471
|
+
Component: () => import("./SettingsPage-BHvunuIF.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
|
1184
1472
|
permissions: PERMISSIONS.accessMain
|
1185
1473
|
});
|
1186
1474
|
const contentManager = app.getPlugin("content-manager");
|
1187
|
-
contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
|
1475
|
+
contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
|
1188
1476
|
contentManager.apis.addDocumentAction((actions) => {
|
1189
1477
|
const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
|
1190
1478
|
actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
|
@@ -1192,6 +1480,7 @@ const index = {
|
|
1192
1480
|
});
|
1193
1481
|
contentManager.apis.addDocumentAction((actions) => {
|
1194
1482
|
actions.splice(2, 0, BulkLocalePublishAction);
|
1483
|
+
actions.splice(5, 0, BulkLocaleUnpublishAction);
|
1195
1484
|
return actions;
|
1196
1485
|
});
|
1197
1486
|
contentManager.injectComponent("listView", "actions", {
|
@@ -1297,7 +1586,7 @@ const index = {
|
|
1297
1586
|
async registerTrads({ locales }) {
|
1298
1587
|
const importedTrads = await Promise.all(
|
1299
1588
|
locales.map((locale) => {
|
1300
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-9eCAqqrB.mjs"), "./translations/dk.json": () => import("./dk-2qBjxt-P.mjs"), "./translations/en.json": () => import("./en-
|
1589
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-9eCAqqrB.mjs"), "./translations/dk.json": () => import("./dk-2qBjxt-P.mjs"), "./translations/en.json": () => import("./en-DlXfy6Gy.mjs"), "./translations/es.json": () => import("./es-DlmMVaBG.mjs"), "./translations/fr.json": () => import("./fr-3S6ke71d.mjs"), "./translations/ko.json": () => import("./ko-qTjQ8IMw.mjs"), "./translations/pl.json": () => import("./pl-B67TSHqT.mjs"), "./translations/ru.json": () => import("./ru-hagMa57T.mjs"), "./translations/tr.json": () => import("./tr-Dw_jmkG-.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-Dyc-aR-h.mjs"), "./translations/zh.json": () => import("./zh-57YM4amO.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
|
1301
1590
|
return {
|
1302
1591
|
data: prefixPluginTranslations(data, pluginId),
|
1303
1592
|
locale
|
@@ -1323,4 +1612,4 @@ export {
|
|
1323
1612
|
index as i,
|
1324
1613
|
useCreateLocaleMutation as u
|
1325
1614
|
};
|
1326
|
-
//# sourceMappingURL=index-
|
1615
|
+
//# sourceMappingURL=index-DUdrr5PR.mjs.map
|