@strapi/content-manager 5.0.0-beta.8 → 5.0.0-rc.0
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/LICENSE +18 -3
- package/dist/_chunks/{ComponentConfigurationPage-by0e_kNd.js → ComponentConfigurationPage-DVY3LwHo.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-by0e_kNd.js.map → ComponentConfigurationPage-DVY3LwHo.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-CuWgXugY.mjs → ComponentConfigurationPage-Dy9BQQ2V.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-CuWgXugY.mjs.map → ComponentConfigurationPage-Dy9BQQ2V.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DbI4KMyz.mjs → EditConfigurationPage-DbR8mWH5.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-DbI4KMyz.mjs.map → EditConfigurationPage-DbR8mWH5.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CqBeCPGH.js → EditConfigurationPage-b6V7YHfo.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CqBeCPGH.js.map → EditConfigurationPage-b6V7YHfo.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-dFPBya9U.mjs → EditViewPage-CPrukwtO.mjs} +46 -46
- package/dist/_chunks/EditViewPage-CPrukwtO.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-ChgloMyO.js → EditViewPage-DhttErmY.js} +45 -45
- package/dist/_chunks/EditViewPage-DhttErmY.js.map +1 -0
- package/dist/_chunks/{Field-dLk-vgLL.js → Field-CBRV4uan.js} +416 -136
- package/dist/_chunks/Field-CBRV4uan.js.map +1 -0
- package/dist/_chunks/{Field-C1nUKcdS.mjs → Field-DrgIgQPw.mjs} +417 -137
- package/dist/_chunks/Field-DrgIgQPw.mjs.map +1 -0
- package/dist/_chunks/{Form-CbXtmHC_.js → Form-Bk3v7Frl.js} +25 -26
- package/dist/_chunks/Form-Bk3v7Frl.js.map +1 -0
- package/dist/_chunks/{Form-DOlpi7Js.mjs → Form-Dxk4txLJ.mjs} +27 -28
- package/dist/_chunks/Form-Dxk4txLJ.mjs.map +1 -0
- package/dist/_chunks/{History-BFNUAiGc.mjs → History-DSU-y4Hg.mjs} +126 -31
- package/dist/_chunks/History-DSU-y4Hg.mjs.map +1 -0
- package/dist/_chunks/{History-BjDfohBr.js → History-xNH_9UuV.js} +125 -30
- package/dist/_chunks/History-xNH_9UuV.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-IQBgWTaa.js → ListConfigurationPage-BCPzXk5W.js} +48 -47
- package/dist/_chunks/ListConfigurationPage-BCPzXk5W.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DDi0KqFm.mjs → ListConfigurationPage-BWwZ-uMJ.mjs} +49 -49
- package/dist/_chunks/ListConfigurationPage-BWwZ-uMJ.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-BPjljUsH.mjs → ListViewPage-D9UmehuA.mjs} +74 -70
- package/dist/_chunks/ListViewPage-D9UmehuA.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-CZYGqlvF.js → ListViewPage-ZIvstfvl.js} +72 -68
- package/dist/_chunks/ListViewPage-ZIvstfvl.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DaWw67K-.mjs → NoContentTypePage-CstnyWv2.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-DaWw67K-.mjs.map → NoContentTypePage-CstnyWv2.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-BOAI6VZ1.js → NoContentTypePage-h7FcuMjI.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-BOAI6VZ1.js.map → NoContentTypePage-h7FcuMjI.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-cYEtLc_e.js → NoPermissionsPage-DofU68cO.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-cYEtLc_e.js.map → NoPermissionsPage-DofU68cO.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-CZrJH00p.mjs → NoPermissionsPage-aFCCLbsf.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-CZrJH00p.mjs.map → NoPermissionsPage-aFCCLbsf.mjs.map} +1 -1
- package/dist/_chunks/{Relations-DTowyge2.mjs → Relations-7v66IP7b.mjs} +4 -4
- package/dist/_chunks/Relations-7v66IP7b.mjs.map +1 -0
- package/dist/_chunks/{Relations-DU6B7irU.js → Relations-DAS_DKG5.js} +4 -4
- package/dist/_chunks/Relations-DAS_DKG5.js.map +1 -0
- package/dist/_chunks/{en-GCOTL6jR.mjs → en-BrCTWlZv.mjs} +9 -4
- package/dist/_chunks/{en-GCOTL6jR.mjs.map → en-BrCTWlZv.mjs.map} +1 -1
- package/dist/_chunks/{en-DTULi5-d.js → en-uOUIxfcQ.js} +9 -4
- package/dist/_chunks/{en-DTULi5-d.js.map → en-uOUIxfcQ.js.map} +1 -1
- package/dist/_chunks/{index-CCJeB7Rw.js → index-CAlLHIrI.js} +1198 -784
- package/dist/_chunks/index-CAlLHIrI.js.map +1 -0
- package/dist/_chunks/{index-BaGHmIir.mjs → index-DIQ7Io-l.mjs} +1229 -815
- package/dist/_chunks/index-DIQ7Io-l.mjs.map +1 -0
- package/dist/_chunks/{layout-ni_L9kT1.js → layout-B1ZS-usI.js} +21 -16
- package/dist/_chunks/layout-B1ZS-usI.js.map +1 -0
- package/dist/_chunks/{layout-BinjszSQ.mjs → layout-DHe2GdT4.mjs} +22 -17
- package/dist/_chunks/layout-DHe2GdT4.mjs.map +1 -0
- package/dist/_chunks/{relations-c91ji5eR.mjs → relations-BUieBWhT.mjs} +2 -2
- package/dist/_chunks/{relations-c91ji5eR.mjs.map → relations-BUieBWhT.mjs.map} +1 -1
- package/dist/_chunks/{relations-CeJAJc5I.js → relations-yXHkSG1Z.js} +2 -2
- package/dist/_chunks/{relations-CeJAJc5I.js.map → relations-yXHkSG1Z.js.map} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +8 -8
- package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
- package/dist/admin/src/hooks/useDocumentActions.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +8 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +2 -10
- package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
- package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
- package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +14 -0
- package/dist/server/index.js +26 -17
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +26 -17
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/single-types.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/package.json +8 -8
- package/dist/_chunks/EditViewPage-ChgloMyO.js.map +0 -1
- package/dist/_chunks/EditViewPage-dFPBya9U.mjs.map +0 -1
- package/dist/_chunks/Field-C1nUKcdS.mjs.map +0 -1
- package/dist/_chunks/Field-dLk-vgLL.js.map +0 -1
- package/dist/_chunks/Form-CbXtmHC_.js.map +0 -1
- package/dist/_chunks/Form-DOlpi7Js.mjs.map +0 -1
- package/dist/_chunks/History-BFNUAiGc.mjs.map +0 -1
- package/dist/_chunks/History-BjDfohBr.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DDi0KqFm.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-IQBgWTaa.js.map +0 -1
- package/dist/_chunks/ListViewPage-BPjljUsH.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-CZYGqlvF.js.map +0 -1
- package/dist/_chunks/Relations-DTowyge2.mjs.map +0 -1
- package/dist/_chunks/Relations-DU6B7irU.js.map +0 -1
- package/dist/_chunks/index-BaGHmIir.mjs.map +0 -1
- package/dist/_chunks/index-CCJeB7Rw.js.map +0 -1
- package/dist/_chunks/layout-BinjszSQ.mjs.map +0 -1
- package/dist/_chunks/layout-ni_L9kT1.js.map +0 -1
@@ -1,12 +1,12 @@
|
|
1
|
-
import { ClockCounterClockwise, CrossCircle, More, WarningCircle, ListPlus, Pencil, Trash, Check, ChevronRight, Duplicate, Feather } from "@strapi/icons";
|
1
|
+
import { ClockCounterClockwise, CrossCircle, More, WarningCircle, ListPlus, Pencil, Trash, Check, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, Feather } from "@strapi/icons";
|
2
2
|
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
3
|
-
import { useStrapiApp, useQueryParams, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useTracking, useForm, BackButton, DescriptionComponentRenderer, useTable } from "@strapi/admin/strapi-admin";
|
3
|
+
import { useStrapiApp, useQueryParams, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useTracking, useForm, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
|
4
4
|
import { stringify } from "qs";
|
5
5
|
import { useIntl } from "react-intl";
|
6
|
-
import { useNavigate, useParams, Navigate, useMatch, NavLink } from "react-router-dom";
|
6
|
+
import { useNavigate, useParams, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
|
7
7
|
import * as React from "react";
|
8
8
|
import { lazy } from "react";
|
9
|
-
import { Menu, VisuallyHidden, Flex, Typography, Dialog,
|
9
|
+
import { Button, Menu, VisuallyHidden, Flex, Box, Typography, Dialog, Modal, Radio, Status, SingleSelect, SingleSelectOption, Loader, IconButton, Tooltip, LinkButton } from "@strapi/design-system";
|
10
10
|
import { styled } from "styled-components";
|
11
11
|
import * as yup from "yup";
|
12
12
|
import { ValidationError } from "yup";
|
@@ -198,6 +198,7 @@ const contentManagerApi = adminApi.enhanceEndpoints({
|
|
198
198
|
]
|
199
199
|
});
|
200
200
|
const documentApi = contentManagerApi.injectEndpoints({
|
201
|
+
overrideExisting: true,
|
201
202
|
endpoints: (builder) => ({
|
202
203
|
autoCloneDocument: builder.mutation({
|
203
204
|
query: ({ model, sourceId, query }) => ({
|
@@ -599,11 +600,11 @@ const createAttributeSchema = (attribute) => {
|
|
599
600
|
}
|
600
601
|
};
|
601
602
|
const addRequiredValidation = (attribute) => (schema) => {
|
602
|
-
if (attribute.required) {
|
603
|
-
return schema.required
|
604
|
-
|
605
|
-
|
606
|
-
|
603
|
+
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
604
|
+
return schema.min(1, translatedErrors.required);
|
605
|
+
}
|
606
|
+
if (attribute.required && attribute.type !== "relation") {
|
607
|
+
return schema.required(translatedErrors.required);
|
607
608
|
}
|
608
609
|
return schema?.nullable ? schema.nullable() : (
|
609
610
|
// In some cases '.nullable' will not be available on the schema.
|
@@ -637,6 +638,28 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
637
638
|
const addMinValidation = (attribute) => (schema) => {
|
638
639
|
if ("min" in attribute) {
|
639
640
|
const min = toInteger(attribute.min);
|
641
|
+
if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
|
642
|
+
if (!attribute.required && "test" in schema && min) {
|
643
|
+
return schema.test(
|
644
|
+
"custom-min",
|
645
|
+
{
|
646
|
+
...translatedErrors.min,
|
647
|
+
values: {
|
648
|
+
min: attribute.min
|
649
|
+
}
|
650
|
+
},
|
651
|
+
(value) => {
|
652
|
+
if (!value) {
|
653
|
+
return true;
|
654
|
+
}
|
655
|
+
if (Array.isArray(value) && value.length === 0) {
|
656
|
+
return true;
|
657
|
+
}
|
658
|
+
return value.length >= min;
|
659
|
+
}
|
660
|
+
);
|
661
|
+
}
|
662
|
+
}
|
640
663
|
if ("min" in schema && min) {
|
641
664
|
return schema.min(min, {
|
642
665
|
...translatedErrors.min,
|
@@ -763,7 +786,10 @@ const useDocument = (args, opts) => {
|
|
763
786
|
isLoading: isLoadingDocument,
|
764
787
|
isFetching: isFetchingDocument,
|
765
788
|
error
|
766
|
-
} = useGetDocumentQuery(args,
|
789
|
+
} = useGetDocumentQuery(args, {
|
790
|
+
...opts,
|
791
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
792
|
+
});
|
767
793
|
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
768
794
|
React.useEffect(() => {
|
769
795
|
if (error) {
|
@@ -927,12 +953,13 @@ const useDocumentActions = () => {
|
|
927
953
|
);
|
928
954
|
const [discardDocument] = useDiscardDocumentMutation();
|
929
955
|
const discard = React.useCallback(
|
930
|
-
async ({ collectionType, model, documentId }) => {
|
956
|
+
async ({ collectionType, model, documentId, params }) => {
|
931
957
|
try {
|
932
958
|
const res = await discardDocument({
|
933
959
|
collectionType,
|
934
960
|
model,
|
935
|
-
documentId
|
961
|
+
documentId,
|
962
|
+
params
|
936
963
|
});
|
937
964
|
if ("error" in res) {
|
938
965
|
toggleNotification({
|
@@ -1264,7 +1291,7 @@ const useDocumentActions = () => {
|
|
1264
1291
|
};
|
1265
1292
|
};
|
1266
1293
|
const ProtectedHistoryPage = lazy(
|
1267
|
-
() => import("./History-
|
1294
|
+
() => import("./History-DSU-y4Hg.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1268
1295
|
);
|
1269
1296
|
const routes$1 = [
|
1270
1297
|
{
|
@@ -1277,31 +1304,31 @@ const routes$1 = [
|
|
1277
1304
|
}
|
1278
1305
|
];
|
1279
1306
|
const ProtectedEditViewPage = lazy(
|
1280
|
-
() => import("./EditViewPage-
|
1307
|
+
() => import("./EditViewPage-CPrukwtO.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1281
1308
|
);
|
1282
1309
|
const ProtectedListViewPage = lazy(
|
1283
|
-
() => import("./ListViewPage-
|
1310
|
+
() => import("./ListViewPage-D9UmehuA.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1284
1311
|
);
|
1285
1312
|
const ProtectedListConfiguration = lazy(
|
1286
|
-
() => import("./ListConfigurationPage-
|
1313
|
+
() => import("./ListConfigurationPage-BWwZ-uMJ.mjs").then((mod) => ({
|
1287
1314
|
default: mod.ProtectedListConfiguration
|
1288
1315
|
}))
|
1289
1316
|
);
|
1290
1317
|
const ProtectedEditConfigurationPage = lazy(
|
1291
|
-
() => import("./EditConfigurationPage-
|
1318
|
+
() => import("./EditConfigurationPage-DbR8mWH5.mjs").then((mod) => ({
|
1292
1319
|
default: mod.ProtectedEditConfigurationPage
|
1293
1320
|
}))
|
1294
1321
|
);
|
1295
1322
|
const ProtectedComponentConfigurationPage = lazy(
|
1296
|
-
() => import("./ComponentConfigurationPage-
|
1323
|
+
() => import("./ComponentConfigurationPage-Dy9BQQ2V.mjs").then((mod) => ({
|
1297
1324
|
default: mod.ProtectedComponentConfigurationPage
|
1298
1325
|
}))
|
1299
1326
|
);
|
1300
1327
|
const NoPermissions = lazy(
|
1301
|
-
() => import("./NoPermissionsPage-
|
1328
|
+
() => import("./NoPermissionsPage-aFCCLbsf.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1302
1329
|
);
|
1303
1330
|
const NoContentType = lazy(
|
1304
|
-
() => import("./NoContentTypePage-
|
1331
|
+
() => import("./NoContentTypePage-CstnyWv2.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1305
1332
|
);
|
1306
1333
|
const CollectionTypePages = () => {
|
1307
1334
|
const { collectionType } = useParams();
|
@@ -1428,7 +1455,7 @@ const DocumentActionButton = (action) => {
|
|
1428
1455
|
DocumentActionConfirmDialog,
|
1429
1456
|
{
|
1430
1457
|
...action.dialog,
|
1431
|
-
variant: action.variant,
|
1458
|
+
variant: action.dialog?.variant ?? action.variant,
|
1432
1459
|
isOpen: dialogId === action.id,
|
1433
1460
|
onClose: handleClose
|
1434
1461
|
}
|
@@ -1508,7 +1535,7 @@ const DocumentActionsMenu = ({
|
|
1508
1535
|
display: "block",
|
1509
1536
|
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
|
1510
1537
|
/* @__PURE__ */ jsxs(Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
|
1511
|
-
action.icon,
|
1538
|
+
/* @__PURE__ */ jsx(Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
|
1512
1539
|
action.label
|
1513
1540
|
] }),
|
1514
1541
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
|
@@ -1569,6 +1596,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
|
|
1569
1596
|
return "primary600";
|
1570
1597
|
}
|
1571
1598
|
};
|
1599
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1600
|
+
switch (variant) {
|
1601
|
+
case "danger":
|
1602
|
+
return "danger600";
|
1603
|
+
case "secondary":
|
1604
|
+
return "neutral500";
|
1605
|
+
case "success":
|
1606
|
+
return "success600";
|
1607
|
+
default:
|
1608
|
+
return "primary600";
|
1609
|
+
}
|
1610
|
+
};
|
1572
1611
|
const DocumentActionConfirmDialog = ({
|
1573
1612
|
onClose,
|
1574
1613
|
onCancel,
|
@@ -1591,22 +1630,20 @@ const DocumentActionConfirmDialog = ({
|
|
1591
1630
|
}
|
1592
1631
|
onClose();
|
1593
1632
|
};
|
1594
|
-
return /* @__PURE__ */
|
1595
|
-
/* @__PURE__ */ jsx(
|
1596
|
-
/* @__PURE__ */ jsx(
|
1597
|
-
|
1598
|
-
{
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1608
|
-
)
|
1609
|
-
] });
|
1633
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
1634
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1635
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1636
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1637
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
1638
|
+
id: "app.components.Button.cancel",
|
1639
|
+
defaultMessage: "Cancel"
|
1640
|
+
}) }) }),
|
1641
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
1642
|
+
id: "app.components.Button.confirm",
|
1643
|
+
defaultMessage: "Confirm"
|
1644
|
+
}) })
|
1645
|
+
] })
|
1646
|
+
] }) });
|
1610
1647
|
};
|
1611
1648
|
const DocumentActionModal = ({
|
1612
1649
|
isOpen,
|
@@ -1616,36 +1653,19 @@ const DocumentActionModal = ({
|
|
1616
1653
|
content: Content,
|
1617
1654
|
onModalClose
|
1618
1655
|
}) => {
|
1619
|
-
const id = React.useId();
|
1620
|
-
if (!isOpen) {
|
1621
|
-
return null;
|
1622
|
-
}
|
1623
1656
|
const handleClose = () => {
|
1624
1657
|
if (onClose) {
|
1625
1658
|
onClose();
|
1626
1659
|
}
|
1627
1660
|
onModalClose();
|
1628
1661
|
};
|
1629
|
-
return /* @__PURE__ */
|
1630
|
-
/* @__PURE__ */ jsx(
|
1631
|
-
/* @__PURE__ */ jsx(
|
1632
|
-
/* @__PURE__ */ jsx(
|
1633
|
-
|
1634
|
-
{
|
1635
|
-
paddingTop: 4,
|
1636
|
-
paddingBottom: 4,
|
1637
|
-
paddingLeft: 5,
|
1638
|
-
paddingRight: 5,
|
1639
|
-
borderWidth: "1px 0 0 0",
|
1640
|
-
borderStyle: "solid",
|
1641
|
-
borderColor: "neutral150",
|
1642
|
-
background: "neutral100",
|
1643
|
-
children: typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1644
|
-
}
|
1645
|
-
)
|
1646
|
-
] });
|
1662
|
+
return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
1663
|
+
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
|
1664
|
+
/* @__PURE__ */ jsx(Modal.Body, { children: typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content }),
|
1665
|
+
/* @__PURE__ */ jsx(Modal.Footer, { children: typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer })
|
1666
|
+
] }) });
|
1647
1667
|
};
|
1648
|
-
const PublishAction = ({
|
1668
|
+
const PublishAction$1 = ({
|
1649
1669
|
activeTab,
|
1650
1670
|
documentId,
|
1651
1671
|
model,
|
@@ -1664,6 +1684,12 @@ const PublishAction = ({
|
|
1664
1684
|
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1665
1685
|
);
|
1666
1686
|
const { publish } = useDocumentActions();
|
1687
|
+
const [
|
1688
|
+
countDraftRelations,
|
1689
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
1690
|
+
] = useLazyGetDraftRelationCountQuery();
|
1691
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
1692
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1667
1693
|
const [{ query, rawQuery }] = useQueryParams();
|
1668
1694
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1669
1695
|
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1672,10 +1698,101 @@ const PublishAction = ({
|
|
1672
1698
|
const validate = useForm("PublishAction", (state) => state.validate);
|
1673
1699
|
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1674
1700
|
const formValues = useForm("PublishAction", ({ values }) => values);
|
1701
|
+
React.useEffect(() => {
|
1702
|
+
if (isErrorDraftRelations) {
|
1703
|
+
toggleNotification({
|
1704
|
+
type: "danger",
|
1705
|
+
message: formatMessage({
|
1706
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
1707
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
1708
|
+
})
|
1709
|
+
});
|
1710
|
+
}
|
1711
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
1712
|
+
React.useEffect(() => {
|
1713
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
1714
|
+
const extractDraftRelations = (data) => {
|
1715
|
+
const relations = data.connect || [];
|
1716
|
+
relations.forEach((relation) => {
|
1717
|
+
if (relation.status === "draft") {
|
1718
|
+
localDraftRelations.add(relation.id);
|
1719
|
+
}
|
1720
|
+
});
|
1721
|
+
};
|
1722
|
+
const traverseAndExtract = (data) => {
|
1723
|
+
Object.entries(data).forEach(([key, value]) => {
|
1724
|
+
if (key === "connect" && Array.isArray(value)) {
|
1725
|
+
extractDraftRelations({ connect: value });
|
1726
|
+
} else if (typeof value === "object" && value !== null) {
|
1727
|
+
traverseAndExtract(value);
|
1728
|
+
}
|
1729
|
+
});
|
1730
|
+
};
|
1731
|
+
if (!documentId || modified) {
|
1732
|
+
traverseAndExtract(formValues);
|
1733
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
1734
|
+
}
|
1735
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1736
|
+
React.useEffect(() => {
|
1737
|
+
if (documentId) {
|
1738
|
+
const fetchDraftRelationsCount = async () => {
|
1739
|
+
const { data, error } = await countDraftRelations({
|
1740
|
+
collectionType,
|
1741
|
+
model,
|
1742
|
+
documentId,
|
1743
|
+
params
|
1744
|
+
});
|
1745
|
+
if (error) {
|
1746
|
+
throw error;
|
1747
|
+
}
|
1748
|
+
if (data) {
|
1749
|
+
setServerCountOfDraftRelations(data.data);
|
1750
|
+
}
|
1751
|
+
};
|
1752
|
+
fetchDraftRelationsCount();
|
1753
|
+
}
|
1754
|
+
}, [documentId, countDraftRelations, collectionType, model, params]);
|
1675
1755
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1676
1756
|
if (!schema?.options?.draftAndPublish) {
|
1677
1757
|
return null;
|
1678
1758
|
}
|
1759
|
+
const performPublish = async () => {
|
1760
|
+
setSubmitting(true);
|
1761
|
+
try {
|
1762
|
+
const { errors } = await validate();
|
1763
|
+
if (errors) {
|
1764
|
+
toggleNotification({
|
1765
|
+
type: "danger",
|
1766
|
+
message: formatMessage({
|
1767
|
+
id: "content-manager.validation.error",
|
1768
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1769
|
+
})
|
1770
|
+
});
|
1771
|
+
return;
|
1772
|
+
}
|
1773
|
+
const res = await publish(
|
1774
|
+
{
|
1775
|
+
collectionType,
|
1776
|
+
model,
|
1777
|
+
documentId,
|
1778
|
+
params
|
1779
|
+
},
|
1780
|
+
formValues
|
1781
|
+
);
|
1782
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1783
|
+
navigate({
|
1784
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1785
|
+
search: rawQuery
|
1786
|
+
});
|
1787
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1788
|
+
setErrors(formatValidationErrors(res.error));
|
1789
|
+
}
|
1790
|
+
} finally {
|
1791
|
+
setSubmitting(false);
|
1792
|
+
}
|
1793
|
+
};
|
1794
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1795
|
+
const hasDraftRelations = totalDraftRelations > 0;
|
1679
1796
|
return {
|
1680
1797
|
/**
|
1681
1798
|
* Disabled when:
|
@@ -1688,49 +1805,41 @@ const PublishAction = ({
|
|
1688
1805
|
* - the user doesn't have the permission to create a new document
|
1689
1806
|
* - the user doesn't have the permission to update the document
|
1690
1807
|
*/
|
1691
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
|
1808
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
|
1692
1809
|
label: formatMessage({
|
1693
1810
|
id: "app.utils.publish",
|
1694
1811
|
defaultMessage: "Publish"
|
1695
1812
|
}),
|
1696
1813
|
onClick: async () => {
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
formValues
|
1718
|
-
);
|
1719
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1720
|
-
navigate({
|
1721
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1722
|
-
search: rawQuery
|
1723
|
-
});
|
1724
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1725
|
-
setErrors(formatValidationErrors(res.error));
|
1814
|
+
if (hasDraftRelations) {
|
1815
|
+
return;
|
1816
|
+
}
|
1817
|
+
await performPublish();
|
1818
|
+
},
|
1819
|
+
dialog: hasDraftRelations ? {
|
1820
|
+
type: "dialog",
|
1821
|
+
variant: "danger",
|
1822
|
+
footer: null,
|
1823
|
+
title: formatMessage({
|
1824
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
1825
|
+
defaultMessage: "Confirmation"
|
1826
|
+
}),
|
1827
|
+
content: formatMessage(
|
1828
|
+
{
|
1829
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
1830
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
1831
|
+
},
|
1832
|
+
{
|
1833
|
+
count: totalDraftRelations
|
1726
1834
|
}
|
1727
|
-
|
1728
|
-
|
1835
|
+
),
|
1836
|
+
onConfirm: async () => {
|
1837
|
+
await performPublish();
|
1729
1838
|
}
|
1730
|
-
}
|
1839
|
+
} : void 0
|
1731
1840
|
};
|
1732
1841
|
};
|
1733
|
-
PublishAction.type = "publish";
|
1842
|
+
PublishAction$1.type = "publish";
|
1734
1843
|
const UpdateAction = ({
|
1735
1844
|
activeTab,
|
1736
1845
|
documentId,
|
@@ -1826,10 +1935,13 @@ const UpdateAction = ({
|
|
1826
1935
|
document
|
1827
1936
|
);
|
1828
1937
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1829
|
-
navigate(
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1938
|
+
navigate(
|
1939
|
+
{
|
1940
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1941
|
+
search: rawQuery
|
1942
|
+
},
|
1943
|
+
{ replace: true }
|
1944
|
+
);
|
1833
1945
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1834
1946
|
setErrors(formatValidationErrors(res.error));
|
1835
1947
|
}
|
@@ -1861,10 +1973,8 @@ const UnpublishAction$1 = ({
|
|
1861
1973
|
const { toggleNotification } = useNotification();
|
1862
1974
|
const [shouldKeepDraft, setShouldKeepDraft] = React.useState(true);
|
1863
1975
|
const isDocumentModified = document?.status === "modified";
|
1864
|
-
const handleChange = (
|
1865
|
-
|
1866
|
-
setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1867
|
-
}
|
1976
|
+
const handleChange = (value) => {
|
1977
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1868
1978
|
};
|
1869
1979
|
if (!schema?.options?.draftAndPublish) {
|
1870
1980
|
return null;
|
@@ -1914,40 +2024,24 @@ const UnpublishAction$1 = ({
|
|
1914
2024
|
}) })
|
1915
2025
|
] }),
|
1916
2026
|
/* @__PURE__ */ jsxs(
|
1917
|
-
|
2027
|
+
Radio.Group,
|
1918
2028
|
{
|
1919
|
-
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
2029
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2030
|
+
name: "discard-options",
|
2031
|
+
"aria-label": formatMessage({
|
2032
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2033
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2034
|
+
}),
|
2035
|
+
onValueChange: handleChange,
|
1925
2036
|
children: [
|
1926
|
-
/* @__PURE__ */ jsx(
|
1927
|
-
|
1928
|
-
|
1929
|
-
|
1930
|
-
|
1931
|
-
|
1932
|
-
|
1933
|
-
|
1934
|
-
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
1935
|
-
defaultMessage: "Keep draft"
|
1936
|
-
})
|
1937
|
-
}
|
1938
|
-
),
|
1939
|
-
/* @__PURE__ */ jsx(
|
1940
|
-
Radio,
|
1941
|
-
{
|
1942
|
-
checked: !shouldKeepDraft,
|
1943
|
-
value: UNPUBLISH_DRAFT_OPTIONS.DISCARD,
|
1944
|
-
name: "discard-options",
|
1945
|
-
children: formatMessage({
|
1946
|
-
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
1947
|
-
defaultMessage: "Replace draft"
|
1948
|
-
})
|
1949
|
-
}
|
1950
|
-
)
|
2037
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2038
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2039
|
+
defaultMessage: "Keep draft"
|
2040
|
+
}) }),
|
2041
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2042
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2043
|
+
defaultMessage: "Replace draft"
|
2044
|
+
}) })
|
1951
2045
|
]
|
1952
2046
|
}
|
1953
2047
|
)
|
@@ -2036,7 +2130,7 @@ const StyledCrossCircle = styled(CrossCircle)`
|
|
2036
2130
|
fill: currentColor;
|
2037
2131
|
}
|
2038
2132
|
`;
|
2039
|
-
const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction$1, DiscardAction];
|
2133
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2040
2134
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2041
2135
|
const RelativeTime = React.forwardRef(
|
2042
2136
|
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
@@ -2093,23 +2187,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2093
2187
|
id: "content-manager.containers.edit.title.new",
|
2094
2188
|
defaultMessage: "Create an entry"
|
2095
2189
|
}) : documentTitle;
|
2096
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2190
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2097
2191
|
/* @__PURE__ */ jsx(BackButton, {}),
|
2098
|
-
/* @__PURE__ */ jsxs(
|
2099
|
-
|
2100
|
-
{
|
2101
|
-
|
2102
|
-
|
2103
|
-
paddingTop: 1,
|
2104
|
-
gap: "80px",
|
2105
|
-
alignItems: "flex-start",
|
2106
|
-
children: [
|
2107
|
-
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2108
|
-
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2109
|
-
]
|
2110
|
-
}
|
2111
|
-
),
|
2112
|
-
status ? /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2192
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2193
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2194
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2195
|
+
] }),
|
2196
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2113
2197
|
] });
|
2114
2198
|
};
|
2115
2199
|
const HeaderToolbar = () => {
|
@@ -2491,163 +2575,785 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
|
|
2491
2575
|
}
|
2492
2576
|
);
|
2493
2577
|
});
|
2494
|
-
const
|
2495
|
-
|
2496
|
-
|
2497
|
-
|
2498
|
-
|
2499
|
-
|
2500
|
-
|
2501
|
-
|
2502
|
-
|
2503
|
-
|
2504
|
-
|
2505
|
-
|
2506
|
-
|
2507
|
-
|
2508
|
-
|
2509
|
-
|
2578
|
+
const HOOKS = {
|
2579
|
+
/**
|
2580
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
2581
|
+
* @constant
|
2582
|
+
* @type {string}
|
2583
|
+
*/
|
2584
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2585
|
+
/**
|
2586
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2587
|
+
* @constant
|
2588
|
+
* @type {string}
|
2589
|
+
*/
|
2590
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2591
|
+
/**
|
2592
|
+
* Hook that allows to mutate the CM's edit view layout
|
2593
|
+
* @constant
|
2594
|
+
* @type {string}
|
2595
|
+
*/
|
2596
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2597
|
+
/**
|
2598
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
2599
|
+
* @constant
|
2600
|
+
* @type {string}
|
2601
|
+
*/
|
2602
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2510
2603
|
};
|
2511
|
-
const
|
2512
|
-
|
2513
|
-
|
2514
|
-
|
2515
|
-
|
2516
|
-
|
2517
|
-
|
2518
|
-
|
2519
|
-
|
2520
|
-
|
2521
|
-
|
2522
|
-
|
2523
|
-
|
2524
|
-
|
2525
|
-
|
2526
|
-
|
2527
|
-
|
2528
|
-
|
2529
|
-
|
2530
|
-
|
2531
|
-
|
2532
|
-
|
2533
|
-
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2604
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2605
|
+
endpoints: (builder) => ({
|
2606
|
+
getContentTypeConfiguration: builder.query({
|
2607
|
+
query: (uid) => ({
|
2608
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
2609
|
+
method: "GET"
|
2610
|
+
}),
|
2611
|
+
transformResponse: (response) => response.data,
|
2612
|
+
providesTags: (_result, _error, uid) => [
|
2613
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
2614
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
2615
|
+
]
|
2616
|
+
}),
|
2617
|
+
getAllContentTypeSettings: builder.query({
|
2618
|
+
query: () => "/content-manager/content-types-settings",
|
2619
|
+
transformResponse: (response) => response.data,
|
2620
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2621
|
+
}),
|
2622
|
+
updateContentTypeConfiguration: builder.mutation({
|
2623
|
+
query: ({ uid, ...body }) => ({
|
2624
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
2625
|
+
method: "PUT",
|
2626
|
+
data: body
|
2627
|
+
}),
|
2628
|
+
transformResponse: (response) => response.data,
|
2629
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
2630
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
2631
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
2632
|
+
// Is this necessary?
|
2633
|
+
{ type: "InitialData" }
|
2634
|
+
]
|
2635
|
+
})
|
2636
|
+
})
|
2637
|
+
});
|
2638
|
+
const {
|
2639
|
+
useGetContentTypeConfigurationQuery,
|
2640
|
+
useGetAllContentTypeSettingsQuery,
|
2641
|
+
useUpdateContentTypeConfigurationMutation
|
2642
|
+
} = contentTypesApi;
|
2643
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
2644
|
+
const { type } = attribute;
|
2645
|
+
if (type === "relation") {
|
2646
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
2647
|
+
}
|
2648
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2649
|
+
};
|
2650
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2651
|
+
if (!mainFieldName) {
|
2652
|
+
return void 0;
|
2653
|
+
}
|
2654
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2655
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2656
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2657
|
+
);
|
2658
|
+
return {
|
2659
|
+
name: mainFieldName,
|
2660
|
+
type: mainFieldType ?? "string"
|
2537
2661
|
};
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2662
|
+
};
|
2663
|
+
const DEFAULT_SETTINGS = {
|
2664
|
+
bulkable: false,
|
2665
|
+
filterable: false,
|
2666
|
+
searchable: false,
|
2667
|
+
pagination: false,
|
2668
|
+
defaultSortBy: "",
|
2669
|
+
defaultSortOrder: "asc",
|
2670
|
+
mainField: "id",
|
2671
|
+
pageSize: 10
|
2672
|
+
};
|
2673
|
+
const useDocumentLayout = (model) => {
|
2674
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2675
|
+
const [{ query }] = useQueryParams();
|
2676
|
+
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2677
|
+
const { toggleNotification } = useNotification();
|
2678
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2679
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2680
|
+
const {
|
2681
|
+
data,
|
2682
|
+
isLoading: isLoadingConfigs,
|
2683
|
+
error,
|
2684
|
+
isFetching: isFetchingConfigs
|
2685
|
+
} = useGetContentTypeConfigurationQuery(model);
|
2686
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2687
|
+
React.useEffect(() => {
|
2688
|
+
if (error) {
|
2689
|
+
toggleNotification({
|
2690
|
+
type: "danger",
|
2691
|
+
message: formatAPIError(error)
|
2692
|
+
});
|
2542
2693
|
}
|
2694
|
+
}, [error, formatAPIError, toggleNotification]);
|
2695
|
+
const editLayout = React.useMemo(
|
2696
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2697
|
+
layout: [],
|
2698
|
+
components: {},
|
2699
|
+
metadatas: {},
|
2700
|
+
options: {},
|
2701
|
+
settings: DEFAULT_SETTINGS
|
2702
|
+
},
|
2703
|
+
[data, isLoading, schemas, schema, components]
|
2704
|
+
);
|
2705
|
+
const listLayout = React.useMemo(() => {
|
2706
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2707
|
+
layout: [],
|
2708
|
+
metadatas: {},
|
2709
|
+
options: {},
|
2710
|
+
settings: DEFAULT_SETTINGS
|
2711
|
+
};
|
2712
|
+
}, [data, isLoading, schemas, schema, components]);
|
2713
|
+
const { layout: edit } = React.useMemo(
|
2714
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2715
|
+
layout: editLayout,
|
2716
|
+
query
|
2717
|
+
}),
|
2718
|
+
[editLayout, query, runHookWaterfall]
|
2719
|
+
);
|
2720
|
+
return {
|
2721
|
+
error,
|
2722
|
+
isLoading,
|
2723
|
+
edit,
|
2724
|
+
list: listLayout
|
2543
2725
|
};
|
2544
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
2545
|
-
/* @__PURE__ */ jsx(
|
2546
|
-
Button,
|
2547
|
-
{
|
2548
|
-
disabled: action.disabled,
|
2549
|
-
startIcon: action.icon,
|
2550
|
-
variant: action.variant,
|
2551
|
-
onClick: handleClick(action),
|
2552
|
-
children: action.label
|
2553
|
-
}
|
2554
|
-
),
|
2555
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
|
2556
|
-
BulkActionConfirmDialog,
|
2557
|
-
{
|
2558
|
-
...action.dialog,
|
2559
|
-
variant: action.variant,
|
2560
|
-
isOpen: dialogId === action.id,
|
2561
|
-
onClose: handleClose
|
2562
|
-
}
|
2563
|
-
) : null,
|
2564
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
|
2565
|
-
BulkActionModal,
|
2566
|
-
{
|
2567
|
-
...action.dialog,
|
2568
|
-
onModalClose: handleClose,
|
2569
|
-
isOpen: dialogId === action.id
|
2570
|
-
}
|
2571
|
-
) : null
|
2572
|
-
] });
|
2573
2726
|
};
|
2574
|
-
const
|
2575
|
-
|
2576
|
-
|
2577
|
-
|
2578
|
-
|
2579
|
-
|
2580
|
-
|
2581
|
-
|
2582
|
-
variant = "secondary"
|
2727
|
+
const useDocLayout = () => {
|
2728
|
+
const { model } = useDoc();
|
2729
|
+
return useDocumentLayout(model);
|
2730
|
+
};
|
2731
|
+
const formatEditLayout = (data, {
|
2732
|
+
schemas,
|
2733
|
+
schema,
|
2734
|
+
components
|
2583
2735
|
}) => {
|
2584
|
-
|
2585
|
-
const
|
2586
|
-
|
2587
|
-
|
2736
|
+
let currentPanelIndex = 0;
|
2737
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2738
|
+
data.contentType.layouts.edit,
|
2739
|
+
schema?.attributes,
|
2740
|
+
data.contentType.metadatas,
|
2741
|
+
{ configurations: data.components, schemas: components },
|
2742
|
+
schemas
|
2743
|
+
).reduce((panels, row) => {
|
2744
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
2745
|
+
panels.push([row]);
|
2746
|
+
currentPanelIndex += 2;
|
2747
|
+
} else {
|
2748
|
+
if (!panels[currentPanelIndex]) {
|
2749
|
+
panels.push([]);
|
2750
|
+
}
|
2751
|
+
panels[currentPanelIndex].push(row);
|
2588
2752
|
}
|
2589
|
-
|
2590
|
-
};
|
2591
|
-
const
|
2592
|
-
|
2593
|
-
|
2753
|
+
return panels;
|
2754
|
+
}, []);
|
2755
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
2756
|
+
(acc, [uid, configuration]) => {
|
2757
|
+
acc[uid] = {
|
2758
|
+
layout: convertEditLayoutToFieldLayouts(
|
2759
|
+
configuration.layouts.edit,
|
2760
|
+
components[uid].attributes,
|
2761
|
+
configuration.metadatas
|
2762
|
+
),
|
2763
|
+
settings: {
|
2764
|
+
...configuration.settings,
|
2765
|
+
icon: components[uid].info.icon,
|
2766
|
+
displayName: components[uid].info.displayName
|
2767
|
+
}
|
2768
|
+
};
|
2769
|
+
return acc;
|
2770
|
+
},
|
2771
|
+
{}
|
2772
|
+
);
|
2773
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2774
|
+
(acc, [attribute, metadata]) => {
|
2775
|
+
return {
|
2776
|
+
...acc,
|
2777
|
+
[attribute]: metadata.edit
|
2778
|
+
};
|
2779
|
+
},
|
2780
|
+
{}
|
2781
|
+
);
|
2782
|
+
return {
|
2783
|
+
layout: panelledEditAttributes,
|
2784
|
+
components: componentEditAttributes,
|
2785
|
+
metadatas: editMetadatas,
|
2786
|
+
settings: {
|
2787
|
+
...data.contentType.settings,
|
2788
|
+
displayName: schema?.info.displayName
|
2789
|
+
},
|
2790
|
+
options: {
|
2791
|
+
...schema?.options,
|
2792
|
+
...schema?.pluginOptions,
|
2793
|
+
...data.contentType.options
|
2594
2794
|
}
|
2595
|
-
onClose();
|
2596
2795
|
};
|
2597
|
-
|
2598
|
-
|
2599
|
-
|
2600
|
-
|
2601
|
-
|
2602
|
-
|
2603
|
-
|
2604
|
-
defaultMessage: "Cancel"
|
2605
|
-
}) }),
|
2606
|
-
endAction: /* @__PURE__ */ jsx(
|
2607
|
-
Button,
|
2608
|
-
{
|
2609
|
-
onClick: handleConfirm,
|
2610
|
-
variant: variant === "danger-light" ? variant : "secondary",
|
2611
|
-
startIcon: variant === "danger-light" ? /* @__PURE__ */ jsx(Trash, {}) : /* @__PURE__ */ jsx(Check, {}),
|
2612
|
-
children: confirmButton ? confirmButton : formatMessage({
|
2613
|
-
id: "app.components.Button.confirm",
|
2614
|
-
defaultMessage: "Confirm"
|
2615
|
-
})
|
2616
|
-
}
|
2617
|
-
)
|
2796
|
+
};
|
2797
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
2798
|
+
return rows.map(
|
2799
|
+
(row) => row.map((field) => {
|
2800
|
+
const attribute = attributes[field.name];
|
2801
|
+
if (!attribute) {
|
2802
|
+
return null;
|
2618
2803
|
}
|
2619
|
-
|
2620
|
-
|
2804
|
+
const { edit: metadata } = metadatas[field.name];
|
2805
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2806
|
+
return {
|
2807
|
+
attribute,
|
2808
|
+
disabled: !metadata.editable,
|
2809
|
+
hint: metadata.description,
|
2810
|
+
label: metadata.label ?? "",
|
2811
|
+
name: field.name,
|
2812
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
2813
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2814
|
+
schemas,
|
2815
|
+
components: components?.schemas ?? {}
|
2816
|
+
}),
|
2817
|
+
placeholder: metadata.placeholder ?? "",
|
2818
|
+
required: attribute.required ?? false,
|
2819
|
+
size: field.size,
|
2820
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
2821
|
+
visible: metadata.visible ?? true,
|
2822
|
+
type: attribute.type
|
2823
|
+
};
|
2824
|
+
}).filter((field) => field !== null)
|
2825
|
+
);
|
2621
2826
|
};
|
2622
|
-
const
|
2623
|
-
|
2624
|
-
|
2625
|
-
|
2626
|
-
content: Content,
|
2627
|
-
onModalClose
|
2827
|
+
const formatListLayout = (data, {
|
2828
|
+
schemas,
|
2829
|
+
schema,
|
2830
|
+
components
|
2628
2831
|
}) => {
|
2629
|
-
const
|
2630
|
-
|
2631
|
-
|
2632
|
-
|
2633
|
-
|
2634
|
-
|
2635
|
-
|
2832
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2833
|
+
(acc, [attribute, metadata]) => {
|
2834
|
+
return {
|
2835
|
+
...acc,
|
2836
|
+
[attribute]: metadata.list
|
2837
|
+
};
|
2838
|
+
},
|
2839
|
+
{}
|
2840
|
+
);
|
2841
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
2842
|
+
data.contentType.layouts.list,
|
2843
|
+
schema?.attributes,
|
2844
|
+
listMetadatas,
|
2845
|
+
{ configurations: data.components, schemas: components },
|
2846
|
+
schemas
|
2847
|
+
);
|
2848
|
+
return {
|
2849
|
+
layout: listAttributes,
|
2850
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
2851
|
+
metadatas: listMetadatas,
|
2852
|
+
options: {
|
2853
|
+
...schema?.options,
|
2854
|
+
...schema?.pluginOptions,
|
2855
|
+
...data.contentType.options
|
2636
2856
|
}
|
2637
|
-
onModalClose();
|
2638
2857
|
};
|
2639
|
-
return /* @__PURE__ */ jsxs(ModalLayout, { borderRadius: "4px", overflow: "hidden", onClose: handleClose, labelledBy: id, children: [
|
2640
|
-
/* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", textColor: "neutral800", tag: "h2", id, children: title }) }),
|
2641
|
-
/* @__PURE__ */ jsx(Content, { onClose: handleClose })
|
2642
|
-
] });
|
2643
2858
|
};
|
2644
|
-
const
|
2645
|
-
|
2646
|
-
|
2647
|
-
|
2648
|
-
|
2649
|
-
|
2650
|
-
|
2859
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
2860
|
+
return columns.map((name) => {
|
2861
|
+
const attribute = attributes[name];
|
2862
|
+
if (!attribute) {
|
2863
|
+
return null;
|
2864
|
+
}
|
2865
|
+
const metadata = metadatas[name];
|
2866
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2867
|
+
return {
|
2868
|
+
attribute,
|
2869
|
+
label: metadata.label ?? "",
|
2870
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2871
|
+
schemas,
|
2872
|
+
components: components?.schemas ?? {}
|
2873
|
+
}),
|
2874
|
+
name,
|
2875
|
+
searchable: metadata.searchable ?? true,
|
2876
|
+
sortable: metadata.sortable ?? true
|
2877
|
+
};
|
2878
|
+
}).filter((field) => field !== null);
|
2879
|
+
};
|
2880
|
+
const ConfirmBulkActionDialog = ({
|
2881
|
+
onToggleDialog,
|
2882
|
+
isOpen = false,
|
2883
|
+
dialogBody,
|
2884
|
+
endAction
|
2885
|
+
}) => {
|
2886
|
+
const { formatMessage } = useIntl();
|
2887
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2888
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
|
2889
|
+
id: "app.components.ConfirmDialog.title",
|
2890
|
+
defaultMessage: "Confirmation"
|
2891
|
+
}) }),
|
2892
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
2893
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
2894
|
+
dialogBody
|
2895
|
+
] }) }),
|
2896
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
2897
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
|
2898
|
+
id: "app.components.Button.cancel",
|
2899
|
+
defaultMessage: "Cancel"
|
2900
|
+
}) }) }),
|
2901
|
+
endAction
|
2902
|
+
] })
|
2903
|
+
] }) });
|
2904
|
+
};
|
2905
|
+
const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
2906
|
+
const ConfirmDialogPublishAll = ({
|
2907
|
+
isOpen,
|
2908
|
+
onToggleDialog,
|
2909
|
+
isConfirmButtonLoading = false,
|
2910
|
+
onConfirm
|
2911
|
+
}) => {
|
2912
|
+
const { formatMessage } = useIntl();
|
2913
|
+
const selectedEntries = useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
|
2914
|
+
const { toggleNotification } = useNotification();
|
2915
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2916
|
+
const { model, schema } = useDoc();
|
2917
|
+
const [{ query }] = useQueryParams();
|
2918
|
+
const {
|
2919
|
+
data: countDraftRelations = 0,
|
2920
|
+
isLoading,
|
2921
|
+
error
|
2922
|
+
} = useGetManyDraftRelationCountQuery(
|
2923
|
+
{
|
2924
|
+
model,
|
2925
|
+
documentIds: selectedEntries.map((entry) => entry.documentId),
|
2926
|
+
locale: query?.plugins?.i18n?.locale
|
2927
|
+
},
|
2928
|
+
{
|
2929
|
+
skip: selectedEntries.length === 0
|
2930
|
+
}
|
2931
|
+
);
|
2932
|
+
React.useEffect(() => {
|
2933
|
+
if (error) {
|
2934
|
+
toggleNotification({ type: "danger", message: formatAPIError(error) });
|
2935
|
+
}
|
2936
|
+
}, [error, formatAPIError, toggleNotification]);
|
2937
|
+
if (error) {
|
2938
|
+
return null;
|
2939
|
+
}
|
2940
|
+
return /* @__PURE__ */ jsx(
|
2941
|
+
ConfirmBulkActionDialog,
|
2942
|
+
{
|
2943
|
+
isOpen: isOpen && !isLoading,
|
2944
|
+
onToggleDialog,
|
2945
|
+
dialogBody: /* @__PURE__ */ jsxs(Fragment, { children: [
|
2946
|
+
/* @__PURE__ */ jsxs(Typography, { id: "confirm-description", textAlign: "center", children: [
|
2947
|
+
countDraftRelations > 0 && formatMessage(
|
2948
|
+
{
|
2949
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2950
|
+
defaultMessage: "<b>{count} {count, plural, one { relation } other { relations } } out of {entities} { entities, plural, one { entry } other { entries } } {count, plural, one { is } other { are } }</b> not published yet and might lead to unexpected behavior. "
|
2951
|
+
},
|
2952
|
+
{
|
2953
|
+
b: BoldChunk$1,
|
2954
|
+
count: countDraftRelations,
|
2955
|
+
entities: selectedEntries.length
|
2956
|
+
}
|
2957
|
+
),
|
2958
|
+
formatMessage({
|
2959
|
+
id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
|
2960
|
+
defaultMessage: "Are you sure you want to publish these entries?"
|
2961
|
+
})
|
2962
|
+
] }),
|
2963
|
+
schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsx(Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
|
2964
|
+
{
|
2965
|
+
id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
|
2966
|
+
defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
|
2967
|
+
},
|
2968
|
+
{
|
2969
|
+
em: Emphasis
|
2970
|
+
}
|
2971
|
+
) })
|
2972
|
+
] }),
|
2973
|
+
endAction: /* @__PURE__ */ jsx(
|
2974
|
+
Button,
|
2975
|
+
{
|
2976
|
+
onClick: onConfirm,
|
2977
|
+
variant: "secondary",
|
2978
|
+
startIcon: /* @__PURE__ */ jsx(Check, {}),
|
2979
|
+
loading: isConfirmButtonLoading,
|
2980
|
+
children: formatMessage({
|
2981
|
+
id: "app.utils.publish",
|
2982
|
+
defaultMessage: "Publish"
|
2983
|
+
})
|
2984
|
+
}
|
2985
|
+
)
|
2986
|
+
}
|
2987
|
+
);
|
2988
|
+
};
|
2989
|
+
const TypographyMaxWidth = styled(Typography)`
|
2990
|
+
max-width: 300px;
|
2991
|
+
`;
|
2992
|
+
const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
2993
|
+
const messages = [];
|
2994
|
+
Object.entries(errors).forEach(([key, value]) => {
|
2995
|
+
const currentKey = parentKey ? `${parentKey}.${key}` : key;
|
2996
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
2997
|
+
if ("id" in value && "defaultMessage" in value) {
|
2998
|
+
messages.push(
|
2999
|
+
formatMessage(
|
3000
|
+
{
|
3001
|
+
id: `${value.id}.withField`,
|
3002
|
+
defaultMessage: value.defaultMessage
|
3003
|
+
},
|
3004
|
+
{ field: currentKey }
|
3005
|
+
)
|
3006
|
+
);
|
3007
|
+
} else {
|
3008
|
+
messages.push(
|
3009
|
+
...formatErrorMessages(
|
3010
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3011
|
+
value,
|
3012
|
+
currentKey,
|
3013
|
+
formatMessage
|
3014
|
+
)
|
3015
|
+
);
|
3016
|
+
}
|
3017
|
+
} else {
|
3018
|
+
messages.push(
|
3019
|
+
formatMessage(
|
3020
|
+
{
|
3021
|
+
id: `${value}.withField`,
|
3022
|
+
defaultMessage: value
|
3023
|
+
},
|
3024
|
+
{ field: currentKey }
|
3025
|
+
)
|
3026
|
+
);
|
3027
|
+
}
|
3028
|
+
});
|
3029
|
+
return messages;
|
3030
|
+
};
|
3031
|
+
const EntryValidationText = ({ validationErrors, status }) => {
|
3032
|
+
const { formatMessage } = useIntl();
|
3033
|
+
if (validationErrors) {
|
3034
|
+
const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
|
3035
|
+
" "
|
3036
|
+
);
|
3037
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3038
|
+
/* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
|
3039
|
+
/* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
|
3040
|
+
] });
|
3041
|
+
}
|
3042
|
+
if (status === "published") {
|
3043
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3044
|
+
/* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
3045
|
+
/* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
|
3046
|
+
id: "content-manager.bulk-publish.already-published",
|
3047
|
+
defaultMessage: "Already Published"
|
3048
|
+
}) })
|
3049
|
+
] });
|
3050
|
+
}
|
3051
|
+
if (status === "modified") {
|
3052
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3053
|
+
/* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
|
3054
|
+
/* @__PURE__ */ jsx(Typography, { children: formatMessage({
|
3055
|
+
id: "content-manager.bulk-publish.modified",
|
3056
|
+
defaultMessage: "Ready to publish changes"
|
3057
|
+
}) })
|
3058
|
+
] });
|
3059
|
+
}
|
3060
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3061
|
+
/* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
3062
|
+
/* @__PURE__ */ jsx(Typography, { children: formatMessage({
|
3063
|
+
id: "app.utils.ready-to-publish",
|
3064
|
+
defaultMessage: "Ready to publish"
|
3065
|
+
}) })
|
3066
|
+
] });
|
3067
|
+
};
|
3068
|
+
const TABLE_HEADERS = [
|
3069
|
+
{ name: "id", label: "id" },
|
3070
|
+
{ name: "name", label: "name" },
|
3071
|
+
{ name: "status", label: "status" },
|
3072
|
+
{ name: "publicationStatus", label: "Publication status" }
|
3073
|
+
];
|
3074
|
+
const SelectedEntriesTableContent = ({
|
3075
|
+
isPublishing,
|
3076
|
+
rowsToDisplay = [],
|
3077
|
+
entriesToPublish = [],
|
3078
|
+
validationErrors = {}
|
3079
|
+
}) => {
|
3080
|
+
const { pathname } = useLocation();
|
3081
|
+
const { formatMessage } = useIntl();
|
3082
|
+
const {
|
3083
|
+
list: {
|
3084
|
+
settings: { mainField }
|
3085
|
+
}
|
3086
|
+
} = useDocLayout();
|
3087
|
+
const shouldDisplayMainField = mainField != null && mainField !== "id";
|
3088
|
+
return /* @__PURE__ */ jsxs(Table.Content, { children: [
|
3089
|
+
/* @__PURE__ */ jsxs(Table.Head, { children: [
|
3090
|
+
/* @__PURE__ */ jsx(Table.HeaderCheckboxCell, {}),
|
3091
|
+
TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
|
3092
|
+
(head) => /* @__PURE__ */ jsx(Table.HeaderCell, { ...head }, head.name)
|
3093
|
+
)
|
3094
|
+
] }),
|
3095
|
+
/* @__PURE__ */ jsx(Table.Loading, {}),
|
3096
|
+
/* @__PURE__ */ jsx(Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxs(Table.Row, { children: [
|
3097
|
+
/* @__PURE__ */ jsx(Table.CheckboxCell, { id: row.id }),
|
3098
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row.id }) }),
|
3099
|
+
shouldDisplayMainField && /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row[mainField] }) }),
|
3100
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
|
3101
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3102
|
+
/* @__PURE__ */ jsx(Typography, { children: formatMessage({
|
3103
|
+
id: "content-manager.success.record.publishing",
|
3104
|
+
defaultMessage: "Publishing..."
|
3105
|
+
}) }),
|
3106
|
+
/* @__PURE__ */ jsx(Loader, { small: true })
|
3107
|
+
] }) : /* @__PURE__ */ jsx(
|
3108
|
+
EntryValidationText,
|
3109
|
+
{
|
3110
|
+
validationErrors: validationErrors[row.documentId],
|
3111
|
+
status: row.status
|
3112
|
+
}
|
3113
|
+
) }),
|
3114
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3115
|
+
IconButton,
|
3116
|
+
{
|
3117
|
+
tag: Link,
|
3118
|
+
to: {
|
3119
|
+
pathname: `${pathname}/${row.documentId}`,
|
3120
|
+
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3121
|
+
},
|
3122
|
+
state: { from: pathname },
|
3123
|
+
label: formatMessage(
|
3124
|
+
{ id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
|
3125
|
+
{
|
3126
|
+
target: formatMessage(
|
3127
|
+
{
|
3128
|
+
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3129
|
+
defaultMessage: "item line {number}"
|
3130
|
+
},
|
3131
|
+
{ number: index2 + 1 }
|
3132
|
+
)
|
3133
|
+
}
|
3134
|
+
),
|
3135
|
+
target: "_blank",
|
3136
|
+
marginLeft: "auto",
|
3137
|
+
children: /* @__PURE__ */ jsx(Pencil, {})
|
3138
|
+
}
|
3139
|
+
) })
|
3140
|
+
] }, row.id)) })
|
3141
|
+
] });
|
3142
|
+
};
|
3143
|
+
const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
3144
|
+
const SelectedEntriesModalContent = ({
|
3145
|
+
listViewSelectedEntries,
|
3146
|
+
toggleModal,
|
3147
|
+
setListViewSelectedDocuments,
|
3148
|
+
model
|
3149
|
+
}) => {
|
3150
|
+
const { formatMessage } = useIntl();
|
3151
|
+
const { schema, components } = useContentTypeSchema(model);
|
3152
|
+
const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
|
3153
|
+
const [{ query }] = useQueryParams();
|
3154
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
3155
|
+
const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
|
3156
|
+
{
|
3157
|
+
model,
|
3158
|
+
params: {
|
3159
|
+
page: "1",
|
3160
|
+
pageSize: documentIds.length.toString(),
|
3161
|
+
sort: query.sort,
|
3162
|
+
filters: {
|
3163
|
+
documentId: {
|
3164
|
+
$in: documentIds
|
3165
|
+
}
|
3166
|
+
},
|
3167
|
+
locale: query.plugins?.i18n?.locale
|
3168
|
+
}
|
3169
|
+
},
|
3170
|
+
{
|
3171
|
+
selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
|
3172
|
+
}
|
3173
|
+
);
|
3174
|
+
const { rows, validationErrors } = React.useMemo(() => {
|
3175
|
+
if (data.length > 0 && schema) {
|
3176
|
+
const validate = createYupSchema(schema.attributes, components);
|
3177
|
+
const validationErrors2 = {};
|
3178
|
+
const rows2 = data.map((entry) => {
|
3179
|
+
try {
|
3180
|
+
validate.validateSync(entry, { abortEarly: false });
|
3181
|
+
return entry;
|
3182
|
+
} catch (e) {
|
3183
|
+
if (e instanceof ValidationError) {
|
3184
|
+
validationErrors2[entry.documentId] = getYupValidationErrors(e);
|
3185
|
+
}
|
3186
|
+
return entry;
|
3187
|
+
}
|
3188
|
+
});
|
3189
|
+
return { rows: rows2, validationErrors: validationErrors2 };
|
3190
|
+
}
|
3191
|
+
return {
|
3192
|
+
rows: [],
|
3193
|
+
validationErrors: {}
|
3194
|
+
};
|
3195
|
+
}, [components, data, schema]);
|
3196
|
+
const [publishedCount, setPublishedCount] = React.useState(0);
|
3197
|
+
const [isDialogOpen, setIsDialogOpen] = React.useState(false);
|
3198
|
+
const { publishMany: bulkPublishAction } = useDocumentActions();
|
3199
|
+
const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
|
3200
|
+
const selectedRows = useTable("publishAction", (state) => state.selectedRows);
|
3201
|
+
const selectedEntries = rows.filter(
|
3202
|
+
(entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
|
3203
|
+
);
|
3204
|
+
const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
|
3205
|
+
const selectedEntriesWithErrorsCount = selectedEntries.filter(
|
3206
|
+
({ documentId }) => validationErrors[documentId]
|
3207
|
+
).length;
|
3208
|
+
const selectedEntriesPublished = selectedEntries.filter(
|
3209
|
+
({ status }) => status === "published"
|
3210
|
+
).length;
|
3211
|
+
const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
|
3212
|
+
const toggleDialog = () => setIsDialogOpen((prev) => !prev);
|
3213
|
+
const handleConfirmBulkPublish = async () => {
|
3214
|
+
toggleDialog();
|
3215
|
+
const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
|
3216
|
+
if (!("error" in res)) {
|
3217
|
+
setPublishedCount(res.count);
|
3218
|
+
const unpublishedEntries = rows.filter((row) => {
|
3219
|
+
return !entriesToPublish.includes(row.documentId);
|
3220
|
+
});
|
3221
|
+
setListViewSelectedDocuments(unpublishedEntries);
|
3222
|
+
}
|
3223
|
+
};
|
3224
|
+
const getFormattedCountMessage = () => {
|
3225
|
+
if (publishedCount) {
|
3226
|
+
return formatMessage(
|
3227
|
+
{
|
3228
|
+
id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
|
3229
|
+
defaultMessage: "<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} published. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
|
3230
|
+
},
|
3231
|
+
{
|
3232
|
+
publishedCount,
|
3233
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3234
|
+
b: BoldChunk
|
3235
|
+
}
|
3236
|
+
);
|
3237
|
+
}
|
3238
|
+
return formatMessage(
|
3239
|
+
{
|
3240
|
+
id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
|
3241
|
+
defaultMessage: "<b>{alreadyPublishedCount}</b> {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
|
3242
|
+
},
|
3243
|
+
{
|
3244
|
+
readyToPublishCount: selectedEntriesWithNoErrorsCount,
|
3245
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3246
|
+
alreadyPublishedCount: selectedEntriesPublished,
|
3247
|
+
b: BoldChunk
|
3248
|
+
}
|
3249
|
+
);
|
3250
|
+
};
|
3251
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
3252
|
+
/* @__PURE__ */ jsxs(Modal.Body, { children: [
|
3253
|
+
/* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
|
3254
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsx(
|
3255
|
+
SelectedEntriesTableContent,
|
3256
|
+
{
|
3257
|
+
isPublishing: isSubmittingForm,
|
3258
|
+
rowsToDisplay: rows,
|
3259
|
+
entriesToPublish,
|
3260
|
+
validationErrors
|
3261
|
+
}
|
3262
|
+
) })
|
3263
|
+
] }),
|
3264
|
+
/* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3265
|
+
/* @__PURE__ */ jsx(Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
|
3266
|
+
id: "app.components.Button.cancel",
|
3267
|
+
defaultMessage: "Cancel"
|
3268
|
+
}) }),
|
3269
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3270
|
+
/* @__PURE__ */ jsx(Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
|
3271
|
+
/* @__PURE__ */ jsx(
|
3272
|
+
Button,
|
3273
|
+
{
|
3274
|
+
onClick: toggleDialog,
|
3275
|
+
disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
|
3276
|
+
loading: isSubmittingForm,
|
3277
|
+
children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
|
3278
|
+
}
|
3279
|
+
)
|
3280
|
+
] })
|
3281
|
+
] }),
|
3282
|
+
/* @__PURE__ */ jsx(
|
3283
|
+
ConfirmDialogPublishAll,
|
3284
|
+
{
|
3285
|
+
isOpen: isDialogOpen,
|
3286
|
+
onToggleDialog: toggleDialog,
|
3287
|
+
isConfirmButtonLoading: isSubmittingForm,
|
3288
|
+
onConfirm: handleConfirmBulkPublish
|
3289
|
+
}
|
3290
|
+
)
|
3291
|
+
] });
|
3292
|
+
};
|
3293
|
+
const PublishAction = ({ documents, model }) => {
|
3294
|
+
const { formatMessage } = useIntl();
|
3295
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3296
|
+
const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
|
3297
|
+
const setListViewSelectedDocuments = useTable("publishAction", (state) => state.selectRow);
|
3298
|
+
const refetchList = () => {
|
3299
|
+
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3300
|
+
};
|
3301
|
+
if (!showPublishButton)
|
3302
|
+
return null;
|
3303
|
+
return {
|
3304
|
+
actionType: "publish",
|
3305
|
+
variant: "tertiary",
|
3306
|
+
label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
|
3307
|
+
dialog: {
|
3308
|
+
type: "modal",
|
3309
|
+
title: formatMessage({
|
3310
|
+
id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
|
3311
|
+
defaultMessage: "Publish entries"
|
3312
|
+
}),
|
3313
|
+
content: ({ onClose }) => {
|
3314
|
+
return /* @__PURE__ */ jsx(Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsx(
|
3315
|
+
SelectedEntriesModalContent,
|
3316
|
+
{
|
3317
|
+
listViewSelectedEntries: documents,
|
3318
|
+
toggleModal: () => {
|
3319
|
+
onClose();
|
3320
|
+
refetchList();
|
3321
|
+
},
|
3322
|
+
setListViewSelectedDocuments,
|
3323
|
+
model
|
3324
|
+
}
|
3325
|
+
) });
|
3326
|
+
},
|
3327
|
+
onClose: () => {
|
3328
|
+
refetchList();
|
3329
|
+
}
|
3330
|
+
}
|
3331
|
+
};
|
3332
|
+
};
|
3333
|
+
const BulkActionsRenderer = () => {
|
3334
|
+
const plugins = useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
|
3335
|
+
const { model, collectionType } = useDoc();
|
3336
|
+
const { selectedRows } = useTable("BulkActionsRenderer", (state) => state);
|
3337
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 2, children: /* @__PURE__ */ jsx(
|
3338
|
+
DescriptionComponentRenderer,
|
3339
|
+
{
|
3340
|
+
props: {
|
3341
|
+
model,
|
3342
|
+
collectionType,
|
3343
|
+
documents: selectedRows
|
3344
|
+
},
|
3345
|
+
descriptions: plugins["content-manager"].apis.getBulkActions(),
|
3346
|
+
children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsx(DocumentActionButton, { ...action }, action.id))
|
3347
|
+
}
|
3348
|
+
) });
|
3349
|
+
};
|
3350
|
+
const DeleteAction = ({ documents, model }) => {
|
3351
|
+
const { formatMessage } = useIntl();
|
3352
|
+
const { schema: contentType } = useDoc();
|
3353
|
+
const selectRow = useTable("DeleteAction", (state) => state.selectRow);
|
3354
|
+
const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
|
3355
|
+
const [{ query }] = useQueryParams();
|
3356
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
2651
3357
|
const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
|
2652
3358
|
const { deleteMany: bulkDeleteAction } = useDocumentActions();
|
2653
3359
|
const documentIds = documents.map(({ documentId }) => documentId);
|
@@ -2673,6 +3379,7 @@ const DeleteAction = ({ documents, model }) => {
|
|
2673
3379
|
defaultMessage: "Confirmation"
|
2674
3380
|
}),
|
2675
3381
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3382
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
2676
3383
|
/* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
2677
3384
|
id: "popUpWarning.bodyMessage.contentType.delete.all",
|
2678
3385
|
defaultMessage: "Are you sure you want to delete these entries?"
|
@@ -2709,7 +3416,7 @@ const UnpublishAction = ({ documents, model }) => {
|
|
2709
3416
|
selectRow([]);
|
2710
3417
|
}
|
2711
3418
|
};
|
2712
|
-
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published");
|
3419
|
+
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
2713
3420
|
if (!showUnpublishButton)
|
2714
3421
|
return null;
|
2715
3422
|
return {
|
@@ -2722,6 +3429,7 @@ const UnpublishAction = ({ documents, model }) => {
|
|
2722
3429
|
defaultMessage: "Confirmation"
|
2723
3430
|
}),
|
2724
3431
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3432
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
2725
3433
|
/* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
2726
3434
|
id: "popUpWarning.bodyMessage.contentType.unpublish.all",
|
2727
3435
|
defaultMessage: "Are you sure you want to unpublish these entries?"
|
@@ -2746,7 +3454,7 @@ const UnpublishAction = ({ documents, model }) => {
|
|
2746
3454
|
};
|
2747
3455
|
UnpublishAction.type = "unpublish";
|
2748
3456
|
const Emphasis = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
|
2749
|
-
const DEFAULT_BULK_ACTIONS = [UnpublishAction, DeleteAction];
|
3457
|
+
const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
|
2750
3458
|
const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
2751
3459
|
const { formatMessage } = useIntl();
|
2752
3460
|
const getDefaultErrorMessage = (reason) => {
|
@@ -2898,503 +3606,201 @@ const CloneAction = ({ model, documentId }) => {
|
|
2898
3606
|
if (!documentId) {
|
2899
3607
|
console.error(
|
2900
3608
|
"You're trying to clone a document in the table without an id, this is likely a bug with Strapi. Please open an issue."
|
2901
|
-
);
|
2902
|
-
toggleNotification({
|
2903
|
-
message: formatMessage({
|
2904
|
-
id: "content-manager.actions.clone.error",
|
2905
|
-
defaultMessage: "An error occurred while trying to clone the document."
|
2906
|
-
}),
|
2907
|
-
type: "danger"
|
2908
|
-
});
|
2909
|
-
return;
|
2910
|
-
}
|
2911
|
-
const res = await autoClone({ model, sourceId: documentId });
|
2912
|
-
if ("data" in res) {
|
2913
|
-
navigate(res.data.documentId);
|
2914
|
-
return true;
|
2915
|
-
}
|
2916
|
-
if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
|
2917
|
-
const prohibitedFields2 = res.error.details.prohibitedFields;
|
2918
|
-
setProhibitedFields(prohibitedFields2);
|
2919
|
-
}
|
2920
|
-
},
|
2921
|
-
dialog: {
|
2922
|
-
type: "modal",
|
2923
|
-
title: formatMessage({
|
2924
|
-
id: "content-manager.containers.list.autoCloneModal.header",
|
2925
|
-
defaultMessage: "Duplicate"
|
2926
|
-
}),
|
2927
|
-
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
2928
|
-
footer: ({ onClose }) => {
|
2929
|
-
return /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
|
2930
|
-
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
2931
|
-
id: "cancel",
|
2932
|
-
defaultMessage: "Cancel"
|
2933
|
-
}) }),
|
2934
|
-
/* @__PURE__ */ jsx(
|
2935
|
-
LinkButton,
|
2936
|
-
{
|
2937
|
-
tag: NavLink,
|
2938
|
-
to: {
|
2939
|
-
pathname: `clone/${documentId}`
|
2940
|
-
},
|
2941
|
-
children: formatMessage({
|
2942
|
-
id: "content-manager.containers.list.autoCloneModal.create",
|
2943
|
-
defaultMessage: "Create"
|
2944
|
-
})
|
2945
|
-
}
|
2946
|
-
)
|
2947
|
-
] });
|
2948
|
-
}
|
2949
|
-
}
|
2950
|
-
};
|
2951
|
-
};
|
2952
|
-
CloneAction.type = "clone";
|
2953
|
-
const StyledDuplicate = styled(Duplicate)`
|
2954
|
-
path {
|
2955
|
-
fill: currentColor;
|
2956
|
-
}
|
2957
|
-
`;
|
2958
|
-
const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
|
2959
|
-
class ContentManagerPlugin {
|
2960
|
-
/**
|
2961
|
-
* The following properties are the stored ones provided by any plugins registering with
|
2962
|
-
* the content-manager. The function calls however, need to be called at runtime in the
|
2963
|
-
* application, so instead we collate them and run them later with the complete list incl.
|
2964
|
-
* ones already registered & the context of the view.
|
2965
|
-
*/
|
2966
|
-
bulkActions = [...DEFAULT_BULK_ACTIONS];
|
2967
|
-
documentActions = [
|
2968
|
-
...DEFAULT_ACTIONS,
|
2969
|
-
...DEFAULT_TABLE_ROW_ACTIONS,
|
2970
|
-
...DEFAULT_HEADER_ACTIONS,
|
2971
|
-
HistoryAction
|
2972
|
-
];
|
2973
|
-
editViewSidePanels = [ActionsPanel];
|
2974
|
-
headerActions = [];
|
2975
|
-
constructor() {
|
2976
|
-
}
|
2977
|
-
addEditViewSidePanel(panels) {
|
2978
|
-
if (Array.isArray(panels)) {
|
2979
|
-
this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
|
2980
|
-
} else if (typeof panels === "function") {
|
2981
|
-
this.editViewSidePanels = panels(this.editViewSidePanels);
|
2982
|
-
} else {
|
2983
|
-
throw new Error(
|
2984
|
-
`Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
|
2985
|
-
panels
|
2986
|
-
)}`
|
2987
|
-
);
|
2988
|
-
}
|
2989
|
-
}
|
2990
|
-
addDocumentAction(actions2) {
|
2991
|
-
if (Array.isArray(actions2)) {
|
2992
|
-
this.documentActions = [...this.documentActions, ...actions2];
|
2993
|
-
} else if (typeof actions2 === "function") {
|
2994
|
-
this.documentActions = actions2(this.documentActions);
|
2995
|
-
} else {
|
2996
|
-
throw new Error(
|
2997
|
-
`Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
|
2998
|
-
actions2
|
2999
|
-
)}`
|
3000
|
-
);
|
3001
|
-
}
|
3002
|
-
}
|
3003
|
-
addDocumentHeaderAction(actions2) {
|
3004
|
-
if (Array.isArray(actions2)) {
|
3005
|
-
this.headerActions = [...this.headerActions, ...actions2];
|
3006
|
-
} else if (typeof actions2 === "function") {
|
3007
|
-
this.headerActions = actions2(this.headerActions);
|
3008
|
-
} else {
|
3009
|
-
throw new Error(
|
3010
|
-
`Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
|
3011
|
-
actions2
|
3012
|
-
)}`
|
3013
|
-
);
|
3014
|
-
}
|
3015
|
-
}
|
3016
|
-
addBulkAction(actions2) {
|
3017
|
-
if (Array.isArray(actions2)) {
|
3018
|
-
this.bulkActions = [...this.bulkActions, ...actions2];
|
3019
|
-
} else if (typeof actions2 === "function") {
|
3020
|
-
this.bulkActions = actions2(this.bulkActions);
|
3021
|
-
} else {
|
3022
|
-
throw new Error(
|
3023
|
-
`Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
|
3024
|
-
actions2
|
3025
|
-
)}`
|
3026
|
-
);
|
3027
|
-
}
|
3028
|
-
}
|
3029
|
-
get config() {
|
3030
|
-
return {
|
3031
|
-
id: PLUGIN_ID,
|
3032
|
-
name: "Content Manager",
|
3033
|
-
injectionZones: INJECTION_ZONES,
|
3034
|
-
apis: {
|
3035
|
-
addBulkAction: this.addBulkAction.bind(this),
|
3036
|
-
addDocumentAction: this.addDocumentAction.bind(this),
|
3037
|
-
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3038
|
-
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3039
|
-
getBulkActions: () => this.bulkActions,
|
3040
|
-
getDocumentActions: () => this.documentActions,
|
3041
|
-
getEditViewSidePanels: () => this.editViewSidePanels,
|
3042
|
-
getHeaderActions: () => this.headerActions
|
3043
|
-
}
|
3044
|
-
};
|
3045
|
-
}
|
3046
|
-
}
|
3047
|
-
const getPrintableType = (value) => {
|
3048
|
-
const nativeType = typeof value;
|
3049
|
-
if (nativeType === "object") {
|
3050
|
-
if (value === null)
|
3051
|
-
return "null";
|
3052
|
-
if (Array.isArray(value))
|
3053
|
-
return "array";
|
3054
|
-
if (value instanceof Object && value.constructor.name !== "Object") {
|
3055
|
-
return value.constructor.name;
|
3056
|
-
}
|
3057
|
-
}
|
3058
|
-
return nativeType;
|
3059
|
-
};
|
3060
|
-
const initialState = {
|
3061
|
-
collectionTypeLinks: [],
|
3062
|
-
components: [],
|
3063
|
-
fieldSizes: {},
|
3064
|
-
models: [],
|
3065
|
-
singleTypeLinks: [],
|
3066
|
-
isLoading: true
|
3067
|
-
};
|
3068
|
-
const appSlice = createSlice({
|
3069
|
-
name: "app",
|
3070
|
-
initialState,
|
3071
|
-
reducers: {
|
3072
|
-
setInitialData(state, action) {
|
3073
|
-
const {
|
3074
|
-
authorizedCollectionTypeLinks,
|
3075
|
-
authorizedSingleTypeLinks,
|
3076
|
-
components,
|
3077
|
-
contentTypeSchemas,
|
3078
|
-
fieldSizes
|
3079
|
-
} = action.payload;
|
3080
|
-
state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
|
3081
|
-
({ isDisplayed }) => isDisplayed
|
3082
|
-
);
|
3083
|
-
state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
|
3084
|
-
state.components = components;
|
3085
|
-
state.models = contentTypeSchemas;
|
3086
|
-
state.fieldSizes = fieldSizes;
|
3087
|
-
state.isLoading = false;
|
3088
|
-
}
|
3089
|
-
}
|
3090
|
-
});
|
3091
|
-
const { actions, reducer: reducer$1 } = appSlice;
|
3092
|
-
const { setInitialData } = actions;
|
3093
|
-
const reducer = combineReducers({
|
3094
|
-
app: reducer$1
|
3095
|
-
});
|
3096
|
-
const HOOKS = {
|
3097
|
-
/**
|
3098
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
3099
|
-
* @constant
|
3100
|
-
* @type {string}
|
3101
|
-
*/
|
3102
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
3103
|
-
/**
|
3104
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
3105
|
-
* @constant
|
3106
|
-
* @type {string}
|
3107
|
-
*/
|
3108
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
3109
|
-
/**
|
3110
|
-
* Hook that allows to mutate the CM's edit view layout
|
3111
|
-
* @constant
|
3112
|
-
* @type {string}
|
3113
|
-
*/
|
3114
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
3115
|
-
/**
|
3116
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
3117
|
-
* @constant
|
3118
|
-
* @type {string}
|
3119
|
-
*/
|
3120
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
3121
|
-
};
|
3122
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
3123
|
-
endpoints: (builder) => ({
|
3124
|
-
getContentTypeConfiguration: builder.query({
|
3125
|
-
query: (uid) => ({
|
3126
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
3127
|
-
method: "GET"
|
3128
|
-
}),
|
3129
|
-
transformResponse: (response) => response.data,
|
3130
|
-
providesTags: (_result, _error, uid) => [
|
3131
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
3132
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
3133
|
-
]
|
3134
|
-
}),
|
3135
|
-
getAllContentTypeSettings: builder.query({
|
3136
|
-
query: () => "/content-manager/content-types-settings",
|
3137
|
-
transformResponse: (response) => response.data,
|
3138
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
3139
|
-
}),
|
3140
|
-
updateContentTypeConfiguration: builder.mutation({
|
3141
|
-
query: ({ uid, ...body }) => ({
|
3142
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
3143
|
-
method: "PUT",
|
3144
|
-
data: body
|
3145
|
-
}),
|
3146
|
-
transformResponse: (response) => response.data,
|
3147
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
3148
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
3149
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
3150
|
-
// Is this necessary?
|
3151
|
-
{ type: "InitialData" }
|
3152
|
-
]
|
3153
|
-
})
|
3154
|
-
})
|
3155
|
-
});
|
3156
|
-
const {
|
3157
|
-
useGetContentTypeConfigurationQuery,
|
3158
|
-
useGetAllContentTypeSettingsQuery,
|
3159
|
-
useUpdateContentTypeConfigurationMutation
|
3160
|
-
} = contentTypesApi;
|
3161
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
3162
|
-
const { type } = attribute;
|
3163
|
-
if (type === "relation") {
|
3164
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
3165
|
-
}
|
3166
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
3167
|
-
};
|
3168
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
3169
|
-
if (!mainFieldName) {
|
3170
|
-
return void 0;
|
3171
|
-
}
|
3172
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
3173
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
3174
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
3175
|
-
);
|
3176
|
-
return {
|
3177
|
-
name: mainFieldName,
|
3178
|
-
type: mainFieldType ?? "string"
|
3179
|
-
};
|
3180
|
-
};
|
3181
|
-
const DEFAULT_SETTINGS = {
|
3182
|
-
bulkable: false,
|
3183
|
-
filterable: false,
|
3184
|
-
searchable: false,
|
3185
|
-
pagination: false,
|
3186
|
-
defaultSortBy: "",
|
3187
|
-
defaultSortOrder: "asc",
|
3188
|
-
mainField: "id",
|
3189
|
-
pageSize: 10
|
3190
|
-
};
|
3191
|
-
const useDocumentLayout = (model) => {
|
3192
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
3193
|
-
const [{ query }] = useQueryParams();
|
3194
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
3195
|
-
const { toggleNotification } = useNotification();
|
3196
|
-
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
3197
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
3198
|
-
const {
|
3199
|
-
data,
|
3200
|
-
isLoading: isLoadingConfigs,
|
3201
|
-
error,
|
3202
|
-
isFetching: isFetchingConfigs
|
3203
|
-
} = useGetContentTypeConfigurationQuery(model);
|
3204
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
3205
|
-
React.useEffect(() => {
|
3206
|
-
if (error) {
|
3207
|
-
toggleNotification({
|
3208
|
-
type: "danger",
|
3209
|
-
message: formatAPIError(error)
|
3210
|
-
});
|
3211
|
-
}
|
3212
|
-
}, [error, formatAPIError, toggleNotification]);
|
3213
|
-
const editLayout = React.useMemo(
|
3214
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
3215
|
-
layout: [],
|
3216
|
-
components: {},
|
3217
|
-
metadatas: {},
|
3218
|
-
options: {},
|
3219
|
-
settings: DEFAULT_SETTINGS
|
3220
|
-
},
|
3221
|
-
[data, isLoading, schemas, schema, components]
|
3222
|
-
);
|
3223
|
-
const listLayout = React.useMemo(() => {
|
3224
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
3225
|
-
layout: [],
|
3226
|
-
metadatas: {},
|
3227
|
-
options: {},
|
3228
|
-
settings: DEFAULT_SETTINGS
|
3229
|
-
};
|
3230
|
-
}, [data, isLoading, schemas, schema, components]);
|
3231
|
-
const { layout: edit } = React.useMemo(
|
3232
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
3233
|
-
layout: editLayout,
|
3234
|
-
query
|
3235
|
-
}),
|
3236
|
-
[editLayout, query, runHookWaterfall]
|
3237
|
-
);
|
3238
|
-
return {
|
3239
|
-
error,
|
3240
|
-
isLoading,
|
3241
|
-
edit,
|
3242
|
-
list: listLayout
|
3243
|
-
};
|
3244
|
-
};
|
3245
|
-
const useDocLayout = () => {
|
3246
|
-
const { model } = useDoc();
|
3247
|
-
return useDocumentLayout(model);
|
3248
|
-
};
|
3249
|
-
const formatEditLayout = (data, {
|
3250
|
-
schemas,
|
3251
|
-
schema,
|
3252
|
-
components
|
3253
|
-
}) => {
|
3254
|
-
let currentPanelIndex = 0;
|
3255
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
3256
|
-
data.contentType.layouts.edit,
|
3257
|
-
schema?.attributes,
|
3258
|
-
data.contentType.metadatas,
|
3259
|
-
{ configurations: data.components, schemas: components },
|
3260
|
-
schemas
|
3261
|
-
).reduce((panels, row) => {
|
3262
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
3263
|
-
panels.push([row]);
|
3264
|
-
currentPanelIndex += 2;
|
3265
|
-
} else {
|
3266
|
-
if (!panels[currentPanelIndex]) {
|
3267
|
-
panels.push([]);
|
3268
|
-
}
|
3269
|
-
panels[currentPanelIndex].push(row);
|
3270
|
-
}
|
3271
|
-
return panels;
|
3272
|
-
}, []);
|
3273
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
3274
|
-
(acc, [uid, configuration]) => {
|
3275
|
-
acc[uid] = {
|
3276
|
-
layout: convertEditLayoutToFieldLayouts(
|
3277
|
-
configuration.layouts.edit,
|
3278
|
-
components[uid].attributes,
|
3279
|
-
configuration.metadatas
|
3280
|
-
),
|
3281
|
-
settings: {
|
3282
|
-
...configuration.settings,
|
3283
|
-
icon: components[uid].info.icon,
|
3284
|
-
displayName: components[uid].info.displayName
|
3285
|
-
}
|
3286
|
-
};
|
3287
|
-
return acc;
|
3288
|
-
},
|
3289
|
-
{}
|
3290
|
-
);
|
3291
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
3292
|
-
(acc, [attribute, metadata]) => {
|
3293
|
-
return {
|
3294
|
-
...acc,
|
3295
|
-
[attribute]: metadata.edit
|
3296
|
-
};
|
3297
|
-
},
|
3298
|
-
{}
|
3299
|
-
);
|
3300
|
-
return {
|
3301
|
-
layout: panelledEditAttributes,
|
3302
|
-
components: componentEditAttributes,
|
3303
|
-
metadatas: editMetadatas,
|
3304
|
-
settings: {
|
3305
|
-
...data.contentType.settings,
|
3306
|
-
displayName: schema?.info.displayName
|
3307
|
-
},
|
3308
|
-
options: {
|
3309
|
-
...schema?.options,
|
3310
|
-
...schema?.pluginOptions,
|
3311
|
-
...data.contentType.options
|
3312
|
-
}
|
3313
|
-
};
|
3314
|
-
};
|
3315
|
-
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
3316
|
-
return rows.map(
|
3317
|
-
(row) => row.map((field) => {
|
3318
|
-
const attribute = attributes[field.name];
|
3319
|
-
if (!attribute) {
|
3320
|
-
return null;
|
3609
|
+
);
|
3610
|
+
toggleNotification({
|
3611
|
+
message: formatMessage({
|
3612
|
+
id: "content-manager.actions.clone.error",
|
3613
|
+
defaultMessage: "An error occurred while trying to clone the document."
|
3614
|
+
}),
|
3615
|
+
type: "danger"
|
3616
|
+
});
|
3617
|
+
return;
|
3618
|
+
}
|
3619
|
+
const res = await autoClone({ model, sourceId: documentId });
|
3620
|
+
if ("data" in res) {
|
3621
|
+
navigate(res.data.documentId);
|
3622
|
+
return true;
|
3623
|
+
}
|
3624
|
+
if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
|
3625
|
+
const prohibitedFields2 = res.error.details.prohibitedFields;
|
3626
|
+
setProhibitedFields(prohibitedFields2);
|
3321
3627
|
}
|
3322
|
-
const { edit: metadata } = metadatas[field.name];
|
3323
|
-
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
3324
|
-
return {
|
3325
|
-
attribute,
|
3326
|
-
disabled: !metadata.editable,
|
3327
|
-
hint: metadata.description,
|
3328
|
-
label: metadata.label ?? "",
|
3329
|
-
name: field.name,
|
3330
|
-
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
3331
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
3332
|
-
schemas,
|
3333
|
-
components: components?.schemas ?? {}
|
3334
|
-
}),
|
3335
|
-
placeholder: metadata.placeholder ?? "",
|
3336
|
-
required: attribute.required ?? false,
|
3337
|
-
size: field.size,
|
3338
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
3339
|
-
visible: metadata.visible ?? true,
|
3340
|
-
type: attribute.type
|
3341
|
-
};
|
3342
|
-
}).filter((field) => field !== null)
|
3343
|
-
);
|
3344
|
-
};
|
3345
|
-
const formatListLayout = (data, {
|
3346
|
-
schemas,
|
3347
|
-
schema,
|
3348
|
-
components
|
3349
|
-
}) => {
|
3350
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
3351
|
-
(acc, [attribute, metadata]) => {
|
3352
|
-
return {
|
3353
|
-
...acc,
|
3354
|
-
[attribute]: metadata.list
|
3355
|
-
};
|
3356
3628
|
},
|
3357
|
-
{
|
3358
|
-
|
3359
|
-
|
3360
|
-
|
3361
|
-
|
3362
|
-
|
3363
|
-
|
3364
|
-
|
3365
|
-
|
3366
|
-
|
3367
|
-
|
3368
|
-
|
3369
|
-
|
3370
|
-
|
3371
|
-
|
3372
|
-
|
3373
|
-
|
3629
|
+
dialog: {
|
3630
|
+
type: "modal",
|
3631
|
+
title: formatMessage({
|
3632
|
+
id: "content-manager.containers.list.autoCloneModal.header",
|
3633
|
+
defaultMessage: "Duplicate"
|
3634
|
+
}),
|
3635
|
+
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3636
|
+
footer: ({ onClose }) => {
|
3637
|
+
return /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
|
3638
|
+
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3639
|
+
id: "cancel",
|
3640
|
+
defaultMessage: "Cancel"
|
3641
|
+
}) }),
|
3642
|
+
/* @__PURE__ */ jsx(
|
3643
|
+
LinkButton,
|
3644
|
+
{
|
3645
|
+
tag: NavLink,
|
3646
|
+
to: {
|
3647
|
+
pathname: `clone/${documentId}`
|
3648
|
+
},
|
3649
|
+
children: formatMessage({
|
3650
|
+
id: "content-manager.containers.list.autoCloneModal.create",
|
3651
|
+
defaultMessage: "Create"
|
3652
|
+
})
|
3653
|
+
}
|
3654
|
+
)
|
3655
|
+
] });
|
3656
|
+
}
|
3374
3657
|
}
|
3375
3658
|
};
|
3376
3659
|
};
|
3377
|
-
|
3378
|
-
|
3379
|
-
|
3380
|
-
|
3381
|
-
|
3660
|
+
CloneAction.type = "clone";
|
3661
|
+
const StyledDuplicate = styled(Duplicate)`
|
3662
|
+
path {
|
3663
|
+
fill: currentColor;
|
3664
|
+
}
|
3665
|
+
`;
|
3666
|
+
const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
|
3667
|
+
class ContentManagerPlugin {
|
3668
|
+
/**
|
3669
|
+
* The following properties are the stored ones provided by any plugins registering with
|
3670
|
+
* the content-manager. The function calls however, need to be called at runtime in the
|
3671
|
+
* application, so instead we collate them and run them later with the complete list incl.
|
3672
|
+
* ones already registered & the context of the view.
|
3673
|
+
*/
|
3674
|
+
bulkActions = [...DEFAULT_BULK_ACTIONS];
|
3675
|
+
documentActions = [
|
3676
|
+
...DEFAULT_ACTIONS,
|
3677
|
+
...DEFAULT_TABLE_ROW_ACTIONS,
|
3678
|
+
...DEFAULT_HEADER_ACTIONS,
|
3679
|
+
HistoryAction
|
3680
|
+
];
|
3681
|
+
editViewSidePanels = [ActionsPanel];
|
3682
|
+
headerActions = [];
|
3683
|
+
constructor() {
|
3684
|
+
}
|
3685
|
+
addEditViewSidePanel(panels) {
|
3686
|
+
if (Array.isArray(panels)) {
|
3687
|
+
this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
|
3688
|
+
} else if (typeof panels === "function") {
|
3689
|
+
this.editViewSidePanels = panels(this.editViewSidePanels);
|
3690
|
+
} else {
|
3691
|
+
throw new Error(
|
3692
|
+
`Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
|
3693
|
+
panels
|
3694
|
+
)}`
|
3695
|
+
);
|
3382
3696
|
}
|
3383
|
-
|
3384
|
-
|
3697
|
+
}
|
3698
|
+
addDocumentAction(actions2) {
|
3699
|
+
if (Array.isArray(actions2)) {
|
3700
|
+
this.documentActions = [...this.documentActions, ...actions2];
|
3701
|
+
} else if (typeof actions2 === "function") {
|
3702
|
+
this.documentActions = actions2(this.documentActions);
|
3703
|
+
} else {
|
3704
|
+
throw new Error(
|
3705
|
+
`Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
|
3706
|
+
actions2
|
3707
|
+
)}`
|
3708
|
+
);
|
3709
|
+
}
|
3710
|
+
}
|
3711
|
+
addDocumentHeaderAction(actions2) {
|
3712
|
+
if (Array.isArray(actions2)) {
|
3713
|
+
this.headerActions = [...this.headerActions, ...actions2];
|
3714
|
+
} else if (typeof actions2 === "function") {
|
3715
|
+
this.headerActions = actions2(this.headerActions);
|
3716
|
+
} else {
|
3717
|
+
throw new Error(
|
3718
|
+
`Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
|
3719
|
+
actions2
|
3720
|
+
)}`
|
3721
|
+
);
|
3722
|
+
}
|
3723
|
+
}
|
3724
|
+
addBulkAction(actions2) {
|
3725
|
+
if (Array.isArray(actions2)) {
|
3726
|
+
this.bulkActions = [...this.bulkActions, ...actions2];
|
3727
|
+
} else if (typeof actions2 === "function") {
|
3728
|
+
this.bulkActions = actions2(this.bulkActions);
|
3729
|
+
} else {
|
3730
|
+
throw new Error(
|
3731
|
+
`Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
|
3732
|
+
actions2
|
3733
|
+
)}`
|
3734
|
+
);
|
3735
|
+
}
|
3736
|
+
}
|
3737
|
+
get config() {
|
3385
3738
|
return {
|
3386
|
-
|
3387
|
-
|
3388
|
-
|
3389
|
-
|
3390
|
-
|
3391
|
-
|
3392
|
-
|
3393
|
-
|
3394
|
-
|
3739
|
+
id: PLUGIN_ID,
|
3740
|
+
name: "Content Manager",
|
3741
|
+
injectionZones: INJECTION_ZONES,
|
3742
|
+
apis: {
|
3743
|
+
addBulkAction: this.addBulkAction.bind(this),
|
3744
|
+
addDocumentAction: this.addDocumentAction.bind(this),
|
3745
|
+
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3746
|
+
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3747
|
+
getBulkActions: () => this.bulkActions,
|
3748
|
+
getDocumentActions: () => this.documentActions,
|
3749
|
+
getEditViewSidePanels: () => this.editViewSidePanels,
|
3750
|
+
getHeaderActions: () => this.headerActions
|
3751
|
+
}
|
3395
3752
|
};
|
3396
|
-
}
|
3753
|
+
}
|
3754
|
+
}
|
3755
|
+
const getPrintableType = (value) => {
|
3756
|
+
const nativeType = typeof value;
|
3757
|
+
if (nativeType === "object") {
|
3758
|
+
if (value === null)
|
3759
|
+
return "null";
|
3760
|
+
if (Array.isArray(value))
|
3761
|
+
return "array";
|
3762
|
+
if (value instanceof Object && value.constructor.name !== "Object") {
|
3763
|
+
return value.constructor.name;
|
3764
|
+
}
|
3765
|
+
}
|
3766
|
+
return nativeType;
|
3767
|
+
};
|
3768
|
+
const initialState = {
|
3769
|
+
collectionTypeLinks: [],
|
3770
|
+
components: [],
|
3771
|
+
fieldSizes: {},
|
3772
|
+
models: [],
|
3773
|
+
singleTypeLinks: [],
|
3774
|
+
isLoading: true
|
3397
3775
|
};
|
3776
|
+
const appSlice = createSlice({
|
3777
|
+
name: "app",
|
3778
|
+
initialState,
|
3779
|
+
reducers: {
|
3780
|
+
setInitialData(state, action) {
|
3781
|
+
const {
|
3782
|
+
authorizedCollectionTypeLinks,
|
3783
|
+
authorizedSingleTypeLinks,
|
3784
|
+
components,
|
3785
|
+
contentTypeSchemas,
|
3786
|
+
fieldSizes
|
3787
|
+
} = action.payload;
|
3788
|
+
state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
|
3789
|
+
({ isDisplayed }) => isDisplayed
|
3790
|
+
);
|
3791
|
+
state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
|
3792
|
+
state.components = components;
|
3793
|
+
state.models = contentTypeSchemas;
|
3794
|
+
state.fieldSizes = fieldSizes;
|
3795
|
+
state.isLoading = false;
|
3796
|
+
}
|
3797
|
+
}
|
3798
|
+
});
|
3799
|
+
const { actions, reducer: reducer$1 } = appSlice;
|
3800
|
+
const { setInitialData } = actions;
|
3801
|
+
const reducer = combineReducers({
|
3802
|
+
app: reducer$1
|
3803
|
+
});
|
3398
3804
|
const index = {
|
3399
3805
|
register(app) {
|
3400
3806
|
const cm = new ContentManagerPlugin();
|
@@ -3409,15 +3815,24 @@ const index = {
|
|
3409
3815
|
defaultMessage: "Content Manager"
|
3410
3816
|
},
|
3411
3817
|
permissions: [],
|
3412
|
-
Component: () => import("./layout-BinjszSQ.mjs").then((mod) => ({ default: mod.Layout })),
|
3413
3818
|
position: 1
|
3414
3819
|
});
|
3820
|
+
app.router.addRoute({
|
3821
|
+
path: "content-manager/*",
|
3822
|
+
lazy: async () => {
|
3823
|
+
const { Layout } = await import("./layout-DHe2GdT4.mjs");
|
3824
|
+
return {
|
3825
|
+
Component: Layout
|
3826
|
+
};
|
3827
|
+
},
|
3828
|
+
children: routes
|
3829
|
+
});
|
3415
3830
|
app.registerPlugin(cm.config);
|
3416
3831
|
},
|
3417
3832
|
async registerTrads({ locales }) {
|
3418
3833
|
const importedTrads = await Promise.all(
|
3419
3834
|
locales.map((locale) => {
|
3420
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-
|
3835
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-BrCTWlZv.mjs"), "./translations/es.json": () => import("./es-CeXiYflN.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr-CD9VFbPM.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-CtsUxOvk.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
|
3421
3836
|
return {
|
3422
3837
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3423
3838
|
locale
|
@@ -3438,43 +3853,42 @@ export {
|
|
3438
3853
|
BulkActionsRenderer as B,
|
3439
3854
|
COLLECTION_TYPES as C,
|
3440
3855
|
DocumentStatus as D,
|
3441
|
-
|
3442
|
-
|
3443
|
-
|
3856
|
+
DEFAULT_SETTINGS as E,
|
3857
|
+
convertEditLayoutToFieldLayouts as F,
|
3858
|
+
useDocument as G,
|
3444
3859
|
HOOKS as H,
|
3445
3860
|
InjectionZone as I,
|
3446
|
-
|
3447
|
-
|
3448
|
-
useDocumentActions as L,
|
3861
|
+
index as J,
|
3862
|
+
useDocumentActions as K,
|
3449
3863
|
Panels as P,
|
3450
3864
|
RelativeTime as R,
|
3451
3865
|
SINGLE_TYPES as S,
|
3452
3866
|
TableActions as T,
|
3453
|
-
|
3454
|
-
|
3455
|
-
|
3456
|
-
|
3457
|
-
|
3458
|
-
|
3867
|
+
useGetInitialDataQuery as a,
|
3868
|
+
useGetAllContentTypeSettingsQuery as b,
|
3869
|
+
useDoc as c,
|
3870
|
+
buildValidParams as d,
|
3871
|
+
contentManagerApi as e,
|
3872
|
+
useDocumentRBAC as f,
|
3459
3873
|
getTranslation as g,
|
3460
|
-
|
3461
|
-
|
3462
|
-
|
3463
|
-
|
3464
|
-
|
3465
|
-
|
3466
|
-
|
3874
|
+
useDocumentLayout as h,
|
3875
|
+
createYupSchema as i,
|
3876
|
+
Header as j,
|
3877
|
+
PERMISSIONS as k,
|
3878
|
+
DocumentRBAC as l,
|
3879
|
+
DOCUMENT_META_FIELDS as m,
|
3880
|
+
useDocLayout as n,
|
3467
3881
|
useGetContentTypeConfigurationQuery as o,
|
3468
3882
|
CREATOR_FIELDS as p,
|
3469
3883
|
getMainField as q,
|
3470
|
-
|
3884
|
+
getDisplayName as r,
|
3471
3885
|
setInitialData as s,
|
3472
|
-
|
3473
|
-
|
3474
|
-
|
3475
|
-
|
3476
|
-
|
3477
|
-
|
3478
|
-
|
3479
|
-
};
|
3480
|
-
//# sourceMappingURL=index-
|
3886
|
+
checkIfAttributeIsDisplayable as t,
|
3887
|
+
useContentTypeSchema as u,
|
3888
|
+
useGetAllDocumentsQuery as v,
|
3889
|
+
convertListLayoutToFieldLayouts as w,
|
3890
|
+
capitalise as x,
|
3891
|
+
useUpdateContentTypeConfigurationMutation as y,
|
3892
|
+
extractContentTypeComponents as z
|
3893
|
+
};
|
3894
|
+
//# sourceMappingURL=index-DIQ7Io-l.mjs.map
|