@strapi/content-manager 0.0.0-experimental.bd712ad3930045f4a5d2144c119e0b7856e97fc4 → 0.0.0-experimental.bec5a58066c034a7ebf5b14df62560e68a456fa3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{ComponentConfigurationPage-C7ImeKGM.mjs → ComponentConfigurationPage-BaJMOQyq.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-C7ImeKGM.mjs.map → ComponentConfigurationPage-BaJMOQyq.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BWQv6yRj.js → ComponentConfigurationPage-N-CTtgQa.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BWQv6yRj.js.map → ComponentConfigurationPage-N-CTtgQa.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CEGwxV-L.js → EditConfigurationPage-BHkjAbxH.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-CEGwxV-L.js.map → EditConfigurationPage-BHkjAbxH.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-MItFGzT9.mjs → EditConfigurationPage-CKK-5LfX.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-MItFGzT9.mjs.map → EditConfigurationPage-CKK-5LfX.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-DhmAg0NK.mjs → EditViewPage-B11aeMcf.mjs} +63 -12
- package/dist/_chunks/EditViewPage-B11aeMcf.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-CmMi2Xsn.js → EditViewPage-QPUftxUd.js} +62 -11
- package/dist/_chunks/EditViewPage-QPUftxUd.js.map +1 -0
- package/dist/_chunks/{Field-Cs62u5pl.mjs → Field-Bj_RgtGo.mjs} +215 -124
- package/dist/_chunks/Field-Bj_RgtGo.mjs.map +1 -0
- package/dist/_chunks/{Field-1DLtcLAI.js → Field-DUK83cfh.js} +216 -125
- package/dist/_chunks/Field-DUK83cfh.js.map +1 -0
- package/dist/_chunks/{Form-CqFA7F_V.js → Form-DHmBRlHd.js} +36 -17
- package/dist/_chunks/Form-DHmBRlHd.js.map +1 -0
- package/dist/_chunks/{Form-zYHtzGUX.mjs → Form-DLMSoXV7.mjs} +36 -17
- package/dist/_chunks/Form-DLMSoXV7.mjs.map +1 -0
- package/dist/_chunks/{History-DalgFQ3D.mjs → History-CfCSNlG9.mjs} +59 -106
- package/dist/_chunks/History-CfCSNlG9.mjs.map +1 -0
- package/dist/_chunks/{History-BblwXv7-.js → History-Di3zm4HT.js} +57 -104
- package/dist/_chunks/History-Di3zm4HT.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DWy-vRzs.mjs → ListConfigurationPage-0mtv_iqk.mjs} +18 -7
- package/dist/_chunks/ListConfigurationPage-0mtv_iqk.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Cpy4QqNd.js → ListConfigurationPage-Cq361KIt.js} +17 -6
- package/dist/_chunks/ListConfigurationPage-Cq361KIt.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BkAwIW9s.mjs → ListViewPage-BxLVROX8.mjs} +106 -74
- package/dist/_chunks/ListViewPage-BxLVROX8.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-DFjn1DNW.js → ListViewPage-DFDcG8gM.js} +108 -76
- package/dist/_chunks/ListViewPage-DFDcG8gM.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-B9BCNNdL.mjs → NoContentTypePage-BRfDd67_.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-B9BCNNdL.mjs.map → NoContentTypePage-BRfDd67_.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-C-3ykoxs.js → NoContentTypePage-BSyvnDZZ.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-C-3ykoxs.js.map → NoContentTypePage-BSyvnDZZ.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-Bt_HWGat.mjs → NoPermissionsPage-CV9V8KWa.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-Bt_HWGat.mjs.map → NoPermissionsPage-CV9V8KWa.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DKLmDZnZ.js → NoPermissionsPage-DyLphsn_.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DKLmDZnZ.js.map → NoPermissionsPage-DyLphsn_.js.map} +1 -1
- package/dist/_chunks/Preview-C_B1nx3g.mjs +272 -0
- package/dist/_chunks/Preview-C_B1nx3g.mjs.map +1 -0
- package/dist/_chunks/Preview-D_3aO6Ly.js +291 -0
- package/dist/_chunks/Preview-D_3aO6Ly.js.map +1 -0
- package/dist/_chunks/{Relations-CJmTbZ8T.mjs → Relations-C6pwmDXh.mjs} +73 -37
- package/dist/_chunks/Relations-C6pwmDXh.mjs.map +1 -0
- package/dist/_chunks/{Relations-CrxfoH2n.js → Relations-Cne2AlrL.js} +72 -36
- package/dist/_chunks/Relations-Cne2AlrL.js.map +1 -0
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-DhFUjrNW.mjs} +31 -18
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-DhFUjrNW.mjs.map} +1 -1
- package/dist/_chunks/{en-fbKQxLGn.js → en-Ic0kXjxB.js} +31 -18
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-Ic0kXjxB.js.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/{index-D1344xdw.mjs → index-BpxR3En4.mjs} +1092 -721
- package/dist/_chunks/index-BpxR3En4.mjs.map +1 -0
- package/dist/_chunks/{index-Buwn78Rt.js → index-T-aWjbj2.js} +1073 -701
- package/dist/_chunks/index-T-aWjbj2.js.map +1 -0
- package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
- package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
- package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
- package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
- package/dist/_chunks/{layout-DRuJUpas.js → layout-BEuNwv-F.js} +21 -8
- package/dist/_chunks/layout-BEuNwv-F.js.map +1 -0
- package/dist/_chunks/{layout-ChVuUpa1.mjs → layout-DhMZ_lDx.mjs} +22 -9
- package/dist/_chunks/layout-DhMZ_lDx.mjs.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-B-deMCy4.mjs → relations-BdnxoX6f.mjs} +6 -7
- package/dist/_chunks/relations-BdnxoX6f.mjs.map +1 -0
- package/dist/_chunks/{relations-DuoUwyJr.js → relations-kLcuobLk.js} +6 -7
- package/dist/_chunks/relations-kLcuobLk.js.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +5 -4
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/constants.d.ts +1 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/router.d.ts +1 -1
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +19 -20
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +591 -261
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +592 -262
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/uid.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
- package/dist/server/src/history/services/history.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 +4 -4
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/constants.d.ts +2 -0
- package/dist/server/src/preview/constants.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +13 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +16 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +32 -0
- package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview.d.ts +12 -0
- package/dist/server/src/preview/services/preview.d.ts.map +1 -0
- package/dist/server/src/preview/utils.d.ts +19 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +8 -8
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -4
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
- package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/preview.d.ts +27 -0
- package/dist/shared/contracts/preview.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +4 -0
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +14 -14
- package/dist/_chunks/EditViewPage-CmMi2Xsn.js.map +0 -1
- package/dist/_chunks/EditViewPage-DhmAg0NK.mjs.map +0 -1
- package/dist/_chunks/Field-1DLtcLAI.js.map +0 -1
- package/dist/_chunks/Field-Cs62u5pl.mjs.map +0 -1
- package/dist/_chunks/Form-CqFA7F_V.js.map +0 -1
- package/dist/_chunks/Form-zYHtzGUX.mjs.map +0 -1
- package/dist/_chunks/History-BblwXv7-.js.map +0 -1
- package/dist/_chunks/History-DalgFQ3D.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Cpy4QqNd.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DWy-vRzs.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-BkAwIW9s.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-DFjn1DNW.js.map +0 -1
- package/dist/_chunks/Relations-CJmTbZ8T.mjs.map +0 -1
- package/dist/_chunks/Relations-CrxfoH2n.js.map +0 -1
- package/dist/_chunks/index-Buwn78Rt.js.map +0 -1
- package/dist/_chunks/index-D1344xdw.mjs.map +0 -1
- package/dist/_chunks/layout-ChVuUpa1.mjs.map +0 -1
- package/dist/_chunks/layout-DRuJUpas.js.map +0 -1
- package/dist/_chunks/relations-B-deMCy4.mjs.map +0 -1
- package/dist/_chunks/relations-DuoUwyJr.js.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
@@ -1,15 +1,16 @@
|
|
1
|
-
import {
|
1
|
+
import { More, Cross, WarningCircle, ListPlus, Pencil, Trash, Check, CrossCircle, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, ClockCounterClockwise, Feather } from "@strapi/icons";
|
2
2
|
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
3
|
-
import { useStrapiApp,
|
4
|
-
import { stringify } from "qs";
|
5
|
-
import { useIntl } from "react-intl";
|
6
|
-
import { useNavigate, useParams, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
|
3
|
+
import { useStrapiApp, createContext, useQueryParams, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useForm, useTracking, useGuidedTour, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
|
7
4
|
import * as React from "react";
|
8
5
|
import { lazy } from "react";
|
9
|
-
import {
|
6
|
+
import { Menu, Button, VisuallyHidden, Flex, Dialog, Modal, Typography, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
|
7
|
+
import mapValues from "lodash/fp/mapValues";
|
8
|
+
import { useIntl } from "react-intl";
|
9
|
+
import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
|
10
10
|
import { styled } from "styled-components";
|
11
11
|
import * as yup from "yup";
|
12
12
|
import { ValidationError } from "yup";
|
13
|
+
import { stringify } from "qs";
|
13
14
|
import pipe from "lodash/fp/pipe";
|
14
15
|
import { intervalToDuration, isPast } from "date-fns";
|
15
16
|
import { createSlice, combineReducers } from "@reduxjs/toolkit";
|
@@ -49,42 +50,6 @@ const useInjectionZone = (area) => {
|
|
49
50
|
const [page, position] = area.split(".");
|
50
51
|
return contentManagerPlugin.getInjectedComponents(page, position);
|
51
52
|
};
|
52
|
-
const HistoryAction = ({ model, document }) => {
|
53
|
-
const { formatMessage } = useIntl();
|
54
|
-
const [{ query }] = useQueryParams();
|
55
|
-
const navigate = useNavigate();
|
56
|
-
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
57
|
-
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
58
|
-
return null;
|
59
|
-
}
|
60
|
-
return {
|
61
|
-
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
62
|
-
label: formatMessage({
|
63
|
-
id: "content-manager.history.document-action",
|
64
|
-
defaultMessage: "Content History"
|
65
|
-
}),
|
66
|
-
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
67
|
-
disabled: (
|
68
|
-
/**
|
69
|
-
* The user is creating a new document.
|
70
|
-
* It hasn't been saved yet, so there's no history to go to
|
71
|
-
*/
|
72
|
-
!document || /**
|
73
|
-
* The document has been created but the current dimension has never been saved.
|
74
|
-
* For example, the user is creating a new locale in an existing document,
|
75
|
-
* so there's no history for the document in that locale
|
76
|
-
*/
|
77
|
-
!document.id || /**
|
78
|
-
* History is only available for content types created by the user.
|
79
|
-
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
80
|
-
* which start with `admin::` or `plugin::`
|
81
|
-
*/
|
82
|
-
!model.startsWith("api::")
|
83
|
-
),
|
84
|
-
position: "header"
|
85
|
-
};
|
86
|
-
};
|
87
|
-
HistoryAction.type = "history";
|
88
53
|
const ID = "id";
|
89
54
|
const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
|
90
55
|
const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
|
@@ -136,6 +101,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
136
101
|
if (!slug) {
|
137
102
|
throw new Error("Cannot find the slug param in the URL");
|
138
103
|
}
|
104
|
+
const [{ rawQuery }] = useQueryParams();
|
139
105
|
const userPermissions = useAuth("DocumentRBAC", (state) => state.permissions);
|
140
106
|
const contentTypePermissions = React.useMemo(() => {
|
141
107
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -146,7 +112,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
146
112
|
return { ...acc, [action]: [permission] };
|
147
113
|
}, {});
|
148
114
|
}, [slug, userPermissions]);
|
149
|
-
const { isLoading, allowedActions } = useRBAC(
|
115
|
+
const { isLoading, allowedActions } = useRBAC(
|
116
|
+
contentTypePermissions,
|
117
|
+
permissions ?? void 0,
|
118
|
+
// TODO: useRBAC context should be typed and built differently
|
119
|
+
// We are passing raw query as context to the hook so that it can
|
120
|
+
// rely on the locale provided from DocumentRBAC for its permission calculations.
|
121
|
+
rawQuery
|
122
|
+
);
|
150
123
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
151
124
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
152
125
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -194,7 +167,8 @@ const contentManagerApi = adminApi.enhanceEndpoints({
|
|
194
167
|
"Document",
|
195
168
|
"InitialData",
|
196
169
|
"HistoryVersion",
|
197
|
-
"Relations"
|
170
|
+
"Relations",
|
171
|
+
"UidAvailability"
|
198
172
|
]
|
199
173
|
});
|
200
174
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -208,7 +182,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
208
182
|
params: query
|
209
183
|
}
|
210
184
|
}),
|
211
|
-
invalidatesTags: (_result,
|
185
|
+
invalidatesTags: (_result, error, { model }) => {
|
186
|
+
if (error) {
|
187
|
+
return [];
|
188
|
+
}
|
189
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
190
|
+
}
|
212
191
|
}),
|
213
192
|
cloneDocument: builder.mutation({
|
214
193
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -219,7 +198,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
219
198
|
params
|
220
199
|
}
|
221
200
|
}),
|
222
|
-
invalidatesTags: (_result, _error, { model }) => [
|
201
|
+
invalidatesTags: (_result, _error, { model }) => [
|
202
|
+
{ type: "Document", id: `${model}_LIST` },
|
203
|
+
{ type: "UidAvailability", id: model }
|
204
|
+
]
|
223
205
|
}),
|
224
206
|
/**
|
225
207
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -236,7 +218,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
236
218
|
}),
|
237
219
|
invalidatesTags: (result, _error, { model }) => [
|
238
220
|
{ type: "Document", id: `${model}_LIST` },
|
239
|
-
"Relations"
|
221
|
+
"Relations",
|
222
|
+
{ type: "UidAvailability", id: model }
|
240
223
|
]
|
241
224
|
}),
|
242
225
|
deleteDocument: builder.mutation({
|
@@ -277,7 +260,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
277
260
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
278
261
|
},
|
279
262
|
{ type: "Document", id: `${model}_LIST` },
|
280
|
-
"Relations"
|
263
|
+
"Relations",
|
264
|
+
{ type: "UidAvailability", id: model }
|
281
265
|
];
|
282
266
|
}
|
283
267
|
}),
|
@@ -290,11 +274,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
290
274
|
url: `/content-manager/collection-types/${model}`,
|
291
275
|
method: "GET",
|
292
276
|
config: {
|
293
|
-
params
|
277
|
+
params: stringify(params, { encode: true })
|
294
278
|
}
|
295
279
|
}),
|
296
280
|
providesTags: (result, _error, arg) => {
|
297
281
|
return [
|
282
|
+
{ type: "Document", id: `ALL_LIST` },
|
298
283
|
{ type: "Document", id: `${arg.model}_LIST` },
|
299
284
|
...result?.results.map(({ documentId }) => ({
|
300
285
|
type: "Document",
|
@@ -333,6 +318,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
333
318
|
{
|
334
319
|
type: "Document",
|
335
320
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
321
|
+
},
|
322
|
+
// Make it easy to invalidate all individual documents queries for a model
|
323
|
+
{
|
324
|
+
type: "Document",
|
325
|
+
id: `${model}_ALL_ITEMS`
|
336
326
|
}
|
337
327
|
];
|
338
328
|
}
|
@@ -396,8 +386,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
396
386
|
type: "Document",
|
397
387
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
398
388
|
},
|
399
|
-
"Relations"
|
389
|
+
"Relations",
|
390
|
+
{ type: "UidAvailability", id: model }
|
400
391
|
];
|
392
|
+
},
|
393
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
394
|
+
const patchResult = dispatch(
|
395
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
396
|
+
Object.assign(draft.data, data);
|
397
|
+
})
|
398
|
+
);
|
399
|
+
try {
|
400
|
+
await queryFulfilled;
|
401
|
+
} catch {
|
402
|
+
patchResult.undo();
|
403
|
+
}
|
401
404
|
}
|
402
405
|
}),
|
403
406
|
unpublishDocument: builder.mutation({
|
@@ -459,28 +462,44 @@ const buildValidParams = (query) => {
|
|
459
462
|
{}
|
460
463
|
)
|
461
464
|
};
|
462
|
-
if ("_q" in validQueryParams) {
|
463
|
-
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
464
|
-
}
|
465
465
|
return validQueryParams;
|
466
466
|
};
|
467
467
|
const isBaseQueryError = (error) => {
|
468
468
|
return error.name !== void 0;
|
469
469
|
};
|
470
|
-
const
|
470
|
+
const arrayValidator = (attribute, options) => ({
|
471
|
+
message: translatedErrors.required,
|
472
|
+
test(value) {
|
473
|
+
if (options.status === "draft") {
|
474
|
+
return true;
|
475
|
+
}
|
476
|
+
if (!attribute.required) {
|
477
|
+
return true;
|
478
|
+
}
|
479
|
+
if (!value) {
|
480
|
+
return false;
|
481
|
+
}
|
482
|
+
if (Array.isArray(value) && value.length === 0) {
|
483
|
+
return false;
|
484
|
+
}
|
485
|
+
return true;
|
486
|
+
}
|
487
|
+
});
|
488
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
471
489
|
const createModelSchema = (attributes2) => yup.object().shape(
|
472
490
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
473
491
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
474
492
|
return acc;
|
475
493
|
}
|
476
494
|
const validations = [
|
495
|
+
addNullableValidation,
|
477
496
|
addRequiredValidation,
|
478
497
|
addMinLengthValidation,
|
479
498
|
addMaxLengthValidation,
|
480
499
|
addMinValidation,
|
481
500
|
addMaxValidation,
|
482
501
|
addRegexValidation
|
483
|
-
].map((fn) => fn(attribute));
|
502
|
+
].map((fn) => fn(attribute, options));
|
484
503
|
const transformSchema = pipe(...validations);
|
485
504
|
switch (attribute.type) {
|
486
505
|
case "component": {
|
@@ -490,12 +509,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
490
509
|
...acc,
|
491
510
|
[name]: transformSchema(
|
492
511
|
yup.array().of(createModelSchema(attributes3).nullable(false))
|
493
|
-
)
|
512
|
+
).test(arrayValidator(attribute, options))
|
494
513
|
};
|
495
514
|
} else {
|
496
515
|
return {
|
497
516
|
...acc,
|
498
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
517
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
499
518
|
};
|
500
519
|
}
|
501
520
|
}
|
@@ -517,7 +536,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
517
536
|
}
|
518
537
|
)
|
519
538
|
)
|
520
|
-
)
|
539
|
+
).test(arrayValidator(attribute, options))
|
521
540
|
};
|
522
541
|
case "relation":
|
523
542
|
return {
|
@@ -529,7 +548,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
529
548
|
} else if (Array.isArray(value)) {
|
530
549
|
return yup.array().of(
|
531
550
|
yup.object().shape({
|
532
|
-
id: yup.
|
551
|
+
id: yup.number().required()
|
533
552
|
})
|
534
553
|
);
|
535
554
|
} else if (typeof value === "object") {
|
@@ -581,6 +600,14 @@ const createAttributeSchema = (attribute) => {
|
|
581
600
|
if (!value || typeof value === "string" && value.length === 0) {
|
582
601
|
return true;
|
583
602
|
}
|
603
|
+
if (typeof value === "object") {
|
604
|
+
try {
|
605
|
+
JSON.stringify(value);
|
606
|
+
return true;
|
607
|
+
} catch (err) {
|
608
|
+
return false;
|
609
|
+
}
|
610
|
+
}
|
584
611
|
try {
|
585
612
|
JSON.parse(value);
|
586
613
|
return true;
|
@@ -599,13 +626,7 @@ const createAttributeSchema = (attribute) => {
|
|
599
626
|
return yup.mixed();
|
600
627
|
}
|
601
628
|
};
|
602
|
-
const
|
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);
|
608
|
-
}
|
629
|
+
const nullableSchema = (schema) => {
|
609
630
|
return schema?.nullable ? schema.nullable() : (
|
610
631
|
// In some cases '.nullable' will not be available on the schema.
|
611
632
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -613,7 +634,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
613
634
|
schema
|
614
635
|
);
|
615
636
|
};
|
616
|
-
const
|
637
|
+
const addNullableValidation = () => (schema) => {
|
638
|
+
return nullableSchema(schema);
|
639
|
+
};
|
640
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
641
|
+
if (options.status === "draft" || !attribute.required) {
|
642
|
+
return schema;
|
643
|
+
}
|
644
|
+
if (attribute.required && "required" in schema) {
|
645
|
+
return schema.required(translatedErrors.required);
|
646
|
+
}
|
647
|
+
return schema;
|
648
|
+
};
|
649
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
650
|
+
if (options.status === "draft") {
|
651
|
+
return schema;
|
652
|
+
}
|
617
653
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
618
654
|
return schema.min(attribute.minLength, {
|
619
655
|
...translatedErrors.minLength,
|
@@ -635,32 +671,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
635
671
|
}
|
636
672
|
return schema;
|
637
673
|
};
|
638
|
-
const addMinValidation = (attribute) => (schema) => {
|
639
|
-
if ("
|
674
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
675
|
+
if (options.status === "draft") {
|
676
|
+
return schema;
|
677
|
+
}
|
678
|
+
if ("min" in attribute && "min" in schema) {
|
640
679
|
const min = toInteger(attribute.min);
|
641
|
-
if (
|
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
|
-
}
|
663
|
-
if ("min" in schema && min) {
|
680
|
+
if (min) {
|
664
681
|
return schema.min(min, {
|
665
682
|
...translatedErrors.min,
|
666
683
|
values: {
|
@@ -778,19 +795,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
778
795
|
}, {});
|
779
796
|
return componentsByKey;
|
780
797
|
};
|
781
|
-
const
|
798
|
+
const HOOKS = {
|
799
|
+
/**
|
800
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
801
|
+
* @constant
|
802
|
+
* @type {string}
|
803
|
+
*/
|
804
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
805
|
+
/**
|
806
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
807
|
+
* @constant
|
808
|
+
* @type {string}
|
809
|
+
*/
|
810
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
811
|
+
/**
|
812
|
+
* Hook that allows to mutate the CM's edit view layout
|
813
|
+
* @constant
|
814
|
+
* @type {string}
|
815
|
+
*/
|
816
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
817
|
+
/**
|
818
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
819
|
+
* @constant
|
820
|
+
* @type {string}
|
821
|
+
*/
|
822
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
823
|
+
};
|
824
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
825
|
+
endpoints: (builder) => ({
|
826
|
+
getContentTypeConfiguration: builder.query({
|
827
|
+
query: (uid) => ({
|
828
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
829
|
+
method: "GET"
|
830
|
+
}),
|
831
|
+
transformResponse: (response) => response.data,
|
832
|
+
providesTags: (_result, _error, uid) => [
|
833
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
834
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
835
|
+
]
|
836
|
+
}),
|
837
|
+
getAllContentTypeSettings: builder.query({
|
838
|
+
query: () => "/content-manager/content-types-settings",
|
839
|
+
transformResponse: (response) => response.data,
|
840
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
841
|
+
}),
|
842
|
+
updateContentTypeConfiguration: builder.mutation({
|
843
|
+
query: ({ uid, ...body }) => ({
|
844
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
845
|
+
method: "PUT",
|
846
|
+
data: body
|
847
|
+
}),
|
848
|
+
transformResponse: (response) => response.data,
|
849
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
850
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
851
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
852
|
+
// Is this necessary?
|
853
|
+
{ type: "InitialData" }
|
854
|
+
]
|
855
|
+
})
|
856
|
+
})
|
857
|
+
});
|
858
|
+
const {
|
859
|
+
useGetContentTypeConfigurationQuery,
|
860
|
+
useGetAllContentTypeSettingsQuery,
|
861
|
+
useUpdateContentTypeConfigurationMutation
|
862
|
+
} = contentTypesApi;
|
863
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
864
|
+
const { type } = attribute;
|
865
|
+
if (type === "relation") {
|
866
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
867
|
+
}
|
868
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
869
|
+
};
|
870
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
871
|
+
if (!mainFieldName) {
|
872
|
+
return void 0;
|
873
|
+
}
|
874
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
875
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
876
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
877
|
+
);
|
878
|
+
return {
|
879
|
+
name: mainFieldName,
|
880
|
+
type: mainFieldType ?? "string"
|
881
|
+
};
|
882
|
+
};
|
883
|
+
const DEFAULT_SETTINGS = {
|
884
|
+
bulkable: false,
|
885
|
+
filterable: false,
|
886
|
+
searchable: false,
|
887
|
+
pagination: false,
|
888
|
+
defaultSortBy: "",
|
889
|
+
defaultSortOrder: "asc",
|
890
|
+
mainField: "id",
|
891
|
+
pageSize: 10
|
892
|
+
};
|
893
|
+
const useDocumentLayout = (model) => {
|
894
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
895
|
+
const [{ query }] = useQueryParams();
|
896
|
+
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
782
897
|
const { toggleNotification } = useNotification();
|
783
898
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
899
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
784
900
|
const {
|
785
|
-
|
786
|
-
isLoading:
|
787
|
-
|
788
|
-
|
789
|
-
} =
|
790
|
-
|
791
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
792
|
-
});
|
793
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
901
|
+
data,
|
902
|
+
isLoading: isLoadingConfigs,
|
903
|
+
error,
|
904
|
+
isFetching: isFetchingConfigs
|
905
|
+
} = useGetContentTypeConfigurationQuery(model);
|
906
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
794
907
|
React.useEffect(() => {
|
795
908
|
if (error) {
|
796
909
|
toggleNotification({
|
@@ -798,39 +911,255 @@ const useDocument = (args, opts) => {
|
|
798
911
|
message: formatAPIError(error)
|
799
912
|
});
|
800
913
|
}
|
801
|
-
}, [
|
802
|
-
const
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
(document) => {
|
810
|
-
if (!validationSchema) {
|
811
|
-
throw new Error(
|
812
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
813
|
-
);
|
814
|
-
}
|
815
|
-
try {
|
816
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
817
|
-
return null;
|
818
|
-
} catch (error2) {
|
819
|
-
if (error2 instanceof ValidationError) {
|
820
|
-
return getYupValidationErrors(error2);
|
821
|
-
}
|
822
|
-
throw error2;
|
823
|
-
}
|
914
|
+
}, [error, formatAPIError, toggleNotification]);
|
915
|
+
const editLayout = React.useMemo(
|
916
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
917
|
+
layout: [],
|
918
|
+
components: {},
|
919
|
+
metadatas: {},
|
920
|
+
options: {},
|
921
|
+
settings: DEFAULT_SETTINGS
|
824
922
|
},
|
825
|
-
[
|
923
|
+
[data, isLoading, schemas, schema, components]
|
924
|
+
);
|
925
|
+
const listLayout = React.useMemo(() => {
|
926
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
927
|
+
layout: [],
|
928
|
+
metadatas: {},
|
929
|
+
options: {},
|
930
|
+
settings: DEFAULT_SETTINGS
|
931
|
+
};
|
932
|
+
}, [data, isLoading, schemas, schema, components]);
|
933
|
+
const { layout: edit } = React.useMemo(
|
934
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
935
|
+
layout: editLayout,
|
936
|
+
query
|
937
|
+
}),
|
938
|
+
[editLayout, query, runHookWaterfall]
|
826
939
|
);
|
827
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
828
940
|
return {
|
829
|
-
|
830
|
-
document: data?.data,
|
831
|
-
meta: data?.meta,
|
941
|
+
error,
|
832
942
|
isLoading,
|
943
|
+
edit,
|
944
|
+
list: listLayout
|
945
|
+
};
|
946
|
+
};
|
947
|
+
const useDocLayout = () => {
|
948
|
+
const { model } = useDoc();
|
949
|
+
return useDocumentLayout(model);
|
950
|
+
};
|
951
|
+
const formatEditLayout = (data, {
|
952
|
+
schemas,
|
953
|
+
schema,
|
954
|
+
components
|
955
|
+
}) => {
|
956
|
+
let currentPanelIndex = 0;
|
957
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
958
|
+
data.contentType.layouts.edit,
|
959
|
+
schema?.attributes,
|
960
|
+
data.contentType.metadatas,
|
961
|
+
{ configurations: data.components, schemas: components },
|
962
|
+
schemas
|
963
|
+
).reduce((panels, row) => {
|
964
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
965
|
+
panels.push([row]);
|
966
|
+
currentPanelIndex += 2;
|
967
|
+
} else {
|
968
|
+
if (!panels[currentPanelIndex]) {
|
969
|
+
panels.push([row]);
|
970
|
+
} else {
|
971
|
+
panels[currentPanelIndex].push(row);
|
972
|
+
}
|
973
|
+
}
|
974
|
+
return panels;
|
975
|
+
}, []);
|
976
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
977
|
+
(acc, [uid, configuration]) => {
|
978
|
+
acc[uid] = {
|
979
|
+
layout: convertEditLayoutToFieldLayouts(
|
980
|
+
configuration.layouts.edit,
|
981
|
+
components[uid].attributes,
|
982
|
+
configuration.metadatas,
|
983
|
+
{ configurations: data.components, schemas: components }
|
984
|
+
),
|
985
|
+
settings: {
|
986
|
+
...configuration.settings,
|
987
|
+
icon: components[uid].info.icon,
|
988
|
+
displayName: components[uid].info.displayName
|
989
|
+
}
|
990
|
+
};
|
991
|
+
return acc;
|
992
|
+
},
|
993
|
+
{}
|
994
|
+
);
|
995
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
996
|
+
(acc, [attribute, metadata]) => {
|
997
|
+
return {
|
998
|
+
...acc,
|
999
|
+
[attribute]: metadata.edit
|
1000
|
+
};
|
1001
|
+
},
|
1002
|
+
{}
|
1003
|
+
);
|
1004
|
+
return {
|
1005
|
+
layout: panelledEditAttributes,
|
1006
|
+
components: componentEditAttributes,
|
1007
|
+
metadatas: editMetadatas,
|
1008
|
+
settings: {
|
1009
|
+
...data.contentType.settings,
|
1010
|
+
displayName: schema?.info.displayName
|
1011
|
+
},
|
1012
|
+
options: {
|
1013
|
+
...schema?.options,
|
1014
|
+
...schema?.pluginOptions,
|
1015
|
+
...data.contentType.options
|
1016
|
+
}
|
1017
|
+
};
|
1018
|
+
};
|
1019
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1020
|
+
return rows.map(
|
1021
|
+
(row) => row.map((field) => {
|
1022
|
+
const attribute = attributes[field.name];
|
1023
|
+
if (!attribute) {
|
1024
|
+
return null;
|
1025
|
+
}
|
1026
|
+
const { edit: metadata } = metadatas[field.name];
|
1027
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1028
|
+
return {
|
1029
|
+
attribute,
|
1030
|
+
disabled: !metadata.editable,
|
1031
|
+
hint: metadata.description,
|
1032
|
+
label: metadata.label ?? "",
|
1033
|
+
name: field.name,
|
1034
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1035
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1036
|
+
schemas,
|
1037
|
+
components: components?.schemas ?? {}
|
1038
|
+
}),
|
1039
|
+
placeholder: metadata.placeholder ?? "",
|
1040
|
+
required: attribute.required ?? false,
|
1041
|
+
size: field.size,
|
1042
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1043
|
+
visible: metadata.visible ?? true,
|
1044
|
+
type: attribute.type
|
1045
|
+
};
|
1046
|
+
}).filter((field) => field !== null)
|
1047
|
+
);
|
1048
|
+
};
|
1049
|
+
const formatListLayout = (data, {
|
1050
|
+
schemas,
|
1051
|
+
schema,
|
1052
|
+
components
|
1053
|
+
}) => {
|
1054
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1055
|
+
(acc, [attribute, metadata]) => {
|
1056
|
+
return {
|
1057
|
+
...acc,
|
1058
|
+
[attribute]: metadata.list
|
1059
|
+
};
|
1060
|
+
},
|
1061
|
+
{}
|
1062
|
+
);
|
1063
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1064
|
+
data.contentType.layouts.list,
|
1065
|
+
schema?.attributes,
|
1066
|
+
listMetadatas,
|
1067
|
+
{ configurations: data.components, schemas: components },
|
1068
|
+
schemas
|
1069
|
+
);
|
1070
|
+
return {
|
1071
|
+
layout: listAttributes,
|
1072
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1073
|
+
metadatas: listMetadatas,
|
1074
|
+
options: {
|
1075
|
+
...schema?.options,
|
1076
|
+
...schema?.pluginOptions,
|
1077
|
+
...data.contentType.options
|
1078
|
+
}
|
1079
|
+
};
|
1080
|
+
};
|
1081
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1082
|
+
return columns.map((name) => {
|
1083
|
+
const attribute = attributes[name];
|
1084
|
+
if (!attribute) {
|
1085
|
+
return null;
|
1086
|
+
}
|
1087
|
+
const metadata = metadatas[name];
|
1088
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1089
|
+
return {
|
1090
|
+
attribute,
|
1091
|
+
label: metadata.label ?? "",
|
1092
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1093
|
+
schemas,
|
1094
|
+
components: components?.schemas ?? {}
|
1095
|
+
}),
|
1096
|
+
name,
|
1097
|
+
searchable: metadata.searchable ?? true,
|
1098
|
+
sortable: metadata.sortable ?? true
|
1099
|
+
};
|
1100
|
+
}).filter((field) => field !== null);
|
1101
|
+
};
|
1102
|
+
const useDocument = (args, opts) => {
|
1103
|
+
const { toggleNotification } = useNotification();
|
1104
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1105
|
+
const {
|
1106
|
+
currentData: data,
|
1107
|
+
isLoading: isLoadingDocument,
|
1108
|
+
isFetching: isFetchingDocument,
|
1109
|
+
error
|
1110
|
+
} = useGetDocumentQuery(args, {
|
1111
|
+
...opts,
|
1112
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1113
|
+
});
|
1114
|
+
const {
|
1115
|
+
components,
|
1116
|
+
schema,
|
1117
|
+
schemas,
|
1118
|
+
isLoading: isLoadingSchema
|
1119
|
+
} = useContentTypeSchema(args.model);
|
1120
|
+
React.useEffect(() => {
|
1121
|
+
if (error) {
|
1122
|
+
toggleNotification({
|
1123
|
+
type: "danger",
|
1124
|
+
message: formatAPIError(error)
|
1125
|
+
});
|
1126
|
+
}
|
1127
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1128
|
+
const validationSchema = React.useMemo(() => {
|
1129
|
+
if (!schema) {
|
1130
|
+
return null;
|
1131
|
+
}
|
1132
|
+
return createYupSchema(schema.attributes, components);
|
1133
|
+
}, [schema, components]);
|
1134
|
+
const validate = React.useCallback(
|
1135
|
+
(document) => {
|
1136
|
+
if (!validationSchema) {
|
1137
|
+
throw new Error(
|
1138
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1139
|
+
);
|
1140
|
+
}
|
1141
|
+
try {
|
1142
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1143
|
+
return null;
|
1144
|
+
} catch (error2) {
|
1145
|
+
if (error2 instanceof ValidationError) {
|
1146
|
+
return getYupValidationErrors(error2);
|
1147
|
+
}
|
1148
|
+
throw error2;
|
1149
|
+
}
|
1150
|
+
},
|
1151
|
+
[validationSchema]
|
1152
|
+
);
|
1153
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1154
|
+
const hasError = !!error;
|
1155
|
+
return {
|
1156
|
+
components,
|
1157
|
+
document: data?.data,
|
1158
|
+
meta: data?.meta,
|
1159
|
+
isLoading,
|
1160
|
+
hasError,
|
833
1161
|
schema,
|
1162
|
+
schemas,
|
834
1163
|
validate
|
835
1164
|
};
|
836
1165
|
};
|
@@ -844,22 +1173,60 @@ const useDoc = () => {
|
|
844
1173
|
if (!slug) {
|
845
1174
|
throw new Error("Could not find model in url params");
|
846
1175
|
}
|
1176
|
+
const document = useDocument(
|
1177
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1178
|
+
{
|
1179
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1180
|
+
}
|
1181
|
+
);
|
1182
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
847
1183
|
return {
|
848
1184
|
collectionType,
|
849
1185
|
model: slug,
|
850
|
-
id:
|
851
|
-
...
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
1186
|
+
id: returnId,
|
1187
|
+
...document
|
1188
|
+
};
|
1189
|
+
};
|
1190
|
+
const useContentManagerContext = () => {
|
1191
|
+
const {
|
1192
|
+
collectionType,
|
1193
|
+
model,
|
1194
|
+
id,
|
1195
|
+
components,
|
1196
|
+
isLoading: isLoadingDoc,
|
1197
|
+
schema,
|
1198
|
+
schemas
|
1199
|
+
} = useDoc();
|
1200
|
+
const layout = useDocumentLayout(model);
|
1201
|
+
const form = useForm("useContentManagerContext", (state) => state);
|
1202
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1203
|
+
const slug = model;
|
1204
|
+
const isCreatingEntry = id === "create";
|
1205
|
+
useContentTypeSchema();
|
1206
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1207
|
+
const error = layout.error;
|
1208
|
+
return {
|
1209
|
+
error,
|
1210
|
+
isLoading,
|
1211
|
+
// Base metadata
|
1212
|
+
model,
|
1213
|
+
collectionType,
|
1214
|
+
id,
|
1215
|
+
slug,
|
1216
|
+
isCreatingEntry,
|
1217
|
+
isSingleType,
|
1218
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1219
|
+
// All schema infos
|
1220
|
+
components,
|
1221
|
+
contentType: schema,
|
1222
|
+
contentTypes: schemas,
|
1223
|
+
// Form state
|
1224
|
+
form,
|
1225
|
+
// layout infos
|
1226
|
+
layout
|
857
1227
|
};
|
858
1228
|
};
|
859
1229
|
const prefixPluginTranslations = (trad, pluginId) => {
|
860
|
-
if (!pluginId) {
|
861
|
-
throw new TypeError("pluginId can't be empty");
|
862
|
-
}
|
863
1230
|
return Object.keys(trad).reduce((acc, current) => {
|
864
1231
|
acc[`${pluginId}.${current}`] = trad[current];
|
865
1232
|
return acc;
|
@@ -875,6 +1242,8 @@ const useDocumentActions = () => {
|
|
875
1242
|
const { formatMessage } = useIntl();
|
876
1243
|
const { trackUsage } = useTracking();
|
877
1244
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1245
|
+
const navigate = useNavigate();
|
1246
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
878
1247
|
const [deleteDocument] = useDeleteDocumentMutation();
|
879
1248
|
const _delete = React.useCallback(
|
880
1249
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1189,6 +1558,7 @@ const useDocumentActions = () => {
|
|
1189
1558
|
defaultMessage: "Saved document"
|
1190
1559
|
})
|
1191
1560
|
});
|
1561
|
+
setCurrentStep("contentManager.success");
|
1192
1562
|
return res.data;
|
1193
1563
|
} catch (err) {
|
1194
1564
|
toggleNotification({
|
@@ -1210,7 +1580,6 @@ const useDocumentActions = () => {
|
|
1210
1580
|
sourceId
|
1211
1581
|
});
|
1212
1582
|
if ("error" in res) {
|
1213
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1214
1583
|
return { error: res.error };
|
1215
1584
|
}
|
1216
1585
|
toggleNotification({
|
@@ -1229,7 +1598,7 @@ const useDocumentActions = () => {
|
|
1229
1598
|
throw err;
|
1230
1599
|
}
|
1231
1600
|
},
|
1232
|
-
[autoCloneDocument,
|
1601
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1233
1602
|
);
|
1234
1603
|
const [cloneDocument] = useCloneDocumentMutation();
|
1235
1604
|
const clone = React.useCallback(
|
@@ -1255,6 +1624,7 @@ const useDocumentActions = () => {
|
|
1255
1624
|
defaultMessage: "Cloned document"
|
1256
1625
|
})
|
1257
1626
|
});
|
1627
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1258
1628
|
return res.data;
|
1259
1629
|
} catch (err) {
|
1260
1630
|
toggleNotification({
|
@@ -1265,7 +1635,7 @@ const useDocumentActions = () => {
|
|
1265
1635
|
throw err;
|
1266
1636
|
}
|
1267
1637
|
},
|
1268
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1638
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1269
1639
|
);
|
1270
1640
|
const [getDoc] = useLazyGetDocumentQuery();
|
1271
1641
|
const getDocument = React.useCallback(
|
@@ -1290,10 +1660,10 @@ const useDocumentActions = () => {
|
|
1290
1660
|
update
|
1291
1661
|
};
|
1292
1662
|
};
|
1293
|
-
const ProtectedHistoryPage = lazy(
|
1294
|
-
() => import("./History-
|
1663
|
+
const ProtectedHistoryPage = React.lazy(
|
1664
|
+
() => import("./History-CfCSNlG9.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1295
1665
|
);
|
1296
|
-
const routes$
|
1666
|
+
const routes$2 = [
|
1297
1667
|
{
|
1298
1668
|
path: ":collectionType/:slug/:id/history",
|
1299
1669
|
Component: ProtectedHistoryPage
|
@@ -1303,32 +1673,45 @@ const routes$1 = [
|
|
1303
1673
|
Component: ProtectedHistoryPage
|
1304
1674
|
}
|
1305
1675
|
];
|
1676
|
+
const ProtectedPreviewPage = React.lazy(
|
1677
|
+
() => import("./Preview-C_B1nx3g.mjs").then((mod) => ({ default: mod.ProtectedPreviewPage }))
|
1678
|
+
);
|
1679
|
+
const routes$1 = [
|
1680
|
+
{
|
1681
|
+
path: ":collectionType/:slug/:id/preview",
|
1682
|
+
Component: ProtectedPreviewPage
|
1683
|
+
},
|
1684
|
+
{
|
1685
|
+
path: ":collectionType/:slug/preview",
|
1686
|
+
Component: ProtectedPreviewPage
|
1687
|
+
}
|
1688
|
+
];
|
1306
1689
|
const ProtectedEditViewPage = lazy(
|
1307
|
-
() => import("./EditViewPage-
|
1690
|
+
() => import("./EditViewPage-B11aeMcf.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1308
1691
|
);
|
1309
1692
|
const ProtectedListViewPage = lazy(
|
1310
|
-
() => import("./ListViewPage-
|
1693
|
+
() => import("./ListViewPage-BxLVROX8.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1311
1694
|
);
|
1312
1695
|
const ProtectedListConfiguration = lazy(
|
1313
|
-
() => import("./ListConfigurationPage-
|
1696
|
+
() => import("./ListConfigurationPage-0mtv_iqk.mjs").then((mod) => ({
|
1314
1697
|
default: mod.ProtectedListConfiguration
|
1315
1698
|
}))
|
1316
1699
|
);
|
1317
1700
|
const ProtectedEditConfigurationPage = lazy(
|
1318
|
-
() => import("./EditConfigurationPage-
|
1701
|
+
() => import("./EditConfigurationPage-CKK-5LfX.mjs").then((mod) => ({
|
1319
1702
|
default: mod.ProtectedEditConfigurationPage
|
1320
1703
|
}))
|
1321
1704
|
);
|
1322
1705
|
const ProtectedComponentConfigurationPage = lazy(
|
1323
|
-
() => import("./ComponentConfigurationPage-
|
1706
|
+
() => import("./ComponentConfigurationPage-BaJMOQyq.mjs").then((mod) => ({
|
1324
1707
|
default: mod.ProtectedComponentConfigurationPage
|
1325
1708
|
}))
|
1326
1709
|
);
|
1327
1710
|
const NoPermissions = lazy(
|
1328
|
-
() => import("./NoPermissionsPage-
|
1711
|
+
() => import("./NoPermissionsPage-CV9V8KWa.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1329
1712
|
);
|
1330
1713
|
const NoContentType = lazy(
|
1331
|
-
() => import("./NoContentTypePage-
|
1714
|
+
() => import("./NoContentTypePage-BRfDd67_.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1332
1715
|
);
|
1333
1716
|
const CollectionTypePages = () => {
|
1334
1717
|
const { collectionType } = useParams();
|
@@ -1340,7 +1723,7 @@ const CollectionTypePages = () => {
|
|
1340
1723
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1341
1724
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1342
1725
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1343
|
-
const LIST_PATH = `/content-manager
|
1726
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1344
1727
|
const routes = [
|
1345
1728
|
{
|
1346
1729
|
path: LIST_RELATIVE_PATH,
|
@@ -1374,6 +1757,7 @@ const routes = [
|
|
1374
1757
|
path: "no-content-types",
|
1375
1758
|
Component: NoContentType
|
1376
1759
|
},
|
1760
|
+
...routes$2,
|
1377
1761
|
...routes$1
|
1378
1762
|
];
|
1379
1763
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1442,12 +1826,14 @@ const DocumentActionButton = (action) => {
|
|
1442
1826
|
/* @__PURE__ */ jsx(
|
1443
1827
|
Button,
|
1444
1828
|
{
|
1445
|
-
flex:
|
1829
|
+
flex: "auto",
|
1446
1830
|
startIcon: action.icon,
|
1447
1831
|
disabled: action.disabled,
|
1448
1832
|
onClick: handleClick(action),
|
1449
1833
|
justifyContent: "center",
|
1450
1834
|
variant: action.variant || "default",
|
1835
|
+
paddingTop: "7px",
|
1836
|
+
paddingBottom: "7px",
|
1451
1837
|
children: action.label
|
1452
1838
|
}
|
1453
1839
|
),
|
@@ -1455,7 +1841,7 @@ const DocumentActionButton = (action) => {
|
|
1455
1841
|
DocumentActionConfirmDialog,
|
1456
1842
|
{
|
1457
1843
|
...action.dialog,
|
1458
|
-
variant: action.variant,
|
1844
|
+
variant: action.dialog?.variant ?? action.variant,
|
1459
1845
|
isOpen: dialogId === action.id,
|
1460
1846
|
onClose: handleClose
|
1461
1847
|
}
|
@@ -1470,6 +1856,11 @@ const DocumentActionButton = (action) => {
|
|
1470
1856
|
) : null
|
1471
1857
|
] });
|
1472
1858
|
};
|
1859
|
+
const MenuItem = styled(Menu.Item)`
|
1860
|
+
&:hover {
|
1861
|
+
background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
|
1862
|
+
}
|
1863
|
+
`;
|
1473
1864
|
const DocumentActionsMenu = ({
|
1474
1865
|
actions: actions2,
|
1475
1866
|
children,
|
@@ -1512,9 +1903,9 @@ const DocumentActionsMenu = ({
|
|
1512
1903
|
disabled: isDisabled,
|
1513
1904
|
size: "S",
|
1514
1905
|
endIcon: null,
|
1515
|
-
paddingTop: "
|
1516
|
-
paddingLeft: "
|
1517
|
-
paddingRight: "
|
1906
|
+
paddingTop: "4px",
|
1907
|
+
paddingLeft: "7px",
|
1908
|
+
paddingRight: "7px",
|
1518
1909
|
variant,
|
1519
1910
|
children: [
|
1520
1911
|
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
@@ -1525,36 +1916,35 @@ const DocumentActionsMenu = ({
|
|
1525
1916
|
]
|
1526
1917
|
}
|
1527
1918
|
),
|
1528
|
-
/* @__PURE__ */ jsxs(Menu.Content, {
|
1919
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1529
1920
|
actions2.map((action) => {
|
1530
1921
|
return /* @__PURE__ */ jsx(
|
1531
|
-
|
1922
|
+
MenuItem,
|
1532
1923
|
{
|
1533
1924
|
disabled: action.disabled,
|
1534
1925
|
onSelect: handleClick(action),
|
1535
1926
|
display: "block",
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
] })
|
1927
|
+
isVariantDanger: action.variant === "danger",
|
1928
|
+
isDisabled: action.disabled,
|
1929
|
+
children: /* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxs(
|
1930
|
+
Flex,
|
1931
|
+
{
|
1932
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1933
|
+
gap: 2,
|
1934
|
+
tag: "span",
|
1935
|
+
children: [
|
1936
|
+
/* @__PURE__ */ jsx(
|
1937
|
+
Flex,
|
1938
|
+
{
|
1939
|
+
tag: "span",
|
1940
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1941
|
+
children: action.icon
|
1942
|
+
}
|
1943
|
+
),
|
1944
|
+
action.label
|
1945
|
+
]
|
1946
|
+
}
|
1947
|
+
) })
|
1558
1948
|
},
|
1559
1949
|
action.id
|
1560
1950
|
);
|
@@ -1634,11 +2024,11 @@ const DocumentActionConfirmDialog = ({
|
|
1634
2024
|
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1635
2025
|
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1636
2026
|
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1637
|
-
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
2027
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1638
2028
|
id: "app.components.Button.cancel",
|
1639
2029
|
defaultMessage: "Cancel"
|
1640
2030
|
}) }) }),
|
1641
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2031
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1642
2032
|
id: "app.components.Button.confirm",
|
1643
2033
|
defaultMessage: "Confirm"
|
1644
2034
|
}) })
|
@@ -1661,10 +2051,22 @@ const DocumentActionModal = ({
|
|
1661
2051
|
};
|
1662
2052
|
return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
1663
2053
|
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
|
1664
|
-
|
1665
|
-
|
2054
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
|
2055
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1666
2056
|
] }) });
|
1667
2057
|
};
|
2058
|
+
const transformData = (data) => {
|
2059
|
+
if (Array.isArray(data)) {
|
2060
|
+
return data.map(transformData);
|
2061
|
+
}
|
2062
|
+
if (typeof data === "object" && data !== null) {
|
2063
|
+
if ("apiData" in data) {
|
2064
|
+
return data.apiData;
|
2065
|
+
}
|
2066
|
+
return mapValues(transformData)(data);
|
2067
|
+
}
|
2068
|
+
return data;
|
2069
|
+
};
|
1668
2070
|
const PublishAction$1 = ({
|
1669
2071
|
activeTab,
|
1670
2072
|
documentId,
|
@@ -1677,13 +2079,18 @@ const PublishAction$1 = ({
|
|
1677
2079
|
const navigate = useNavigate();
|
1678
2080
|
const { toggleNotification } = useNotification();
|
1679
2081
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2082
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
1680
2083
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2084
|
+
const { id } = useParams();
|
1681
2085
|
const { formatMessage } = useIntl();
|
1682
|
-
const { canPublish
|
1683
|
-
"PublishAction",
|
1684
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1685
|
-
);
|
2086
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1686
2087
|
const { publish } = useDocumentActions();
|
2088
|
+
const [
|
2089
|
+
countDraftRelations,
|
2090
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2091
|
+
] = useLazyGetDraftRelationCountQuery();
|
2092
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
2093
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1687
2094
|
const [{ query, rawQuery }] = useQueryParams();
|
1688
2095
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1689
2096
|
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1692,10 +2099,107 @@ const PublishAction$1 = ({
|
|
1692
2099
|
const validate = useForm("PublishAction", (state) => state.validate);
|
1693
2100
|
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1694
2101
|
const formValues = useForm("PublishAction", ({ values }) => values);
|
1695
|
-
|
2102
|
+
React.useEffect(() => {
|
2103
|
+
if (isErrorDraftRelations) {
|
2104
|
+
toggleNotification({
|
2105
|
+
type: "danger",
|
2106
|
+
message: formatMessage({
|
2107
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2108
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2109
|
+
})
|
2110
|
+
});
|
2111
|
+
}
|
2112
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2113
|
+
React.useEffect(() => {
|
2114
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2115
|
+
const extractDraftRelations = (data) => {
|
2116
|
+
const relations = data.connect || [];
|
2117
|
+
relations.forEach((relation) => {
|
2118
|
+
if (relation.status === "draft") {
|
2119
|
+
localDraftRelations.add(relation.id);
|
2120
|
+
}
|
2121
|
+
});
|
2122
|
+
};
|
2123
|
+
const traverseAndExtract = (data) => {
|
2124
|
+
Object.entries(data).forEach(([key, value]) => {
|
2125
|
+
if (key === "connect" && Array.isArray(value)) {
|
2126
|
+
extractDraftRelations({ connect: value });
|
2127
|
+
} else if (typeof value === "object" && value !== null) {
|
2128
|
+
traverseAndExtract(value);
|
2129
|
+
}
|
2130
|
+
});
|
2131
|
+
};
|
2132
|
+
if (!documentId || modified) {
|
2133
|
+
traverseAndExtract(formValues);
|
2134
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2135
|
+
}
|
2136
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2137
|
+
React.useEffect(() => {
|
2138
|
+
if (!document || !document.documentId || isListView) {
|
2139
|
+
return;
|
2140
|
+
}
|
2141
|
+
const fetchDraftRelationsCount = async () => {
|
2142
|
+
const { data, error } = await countDraftRelations({
|
2143
|
+
collectionType,
|
2144
|
+
model,
|
2145
|
+
documentId,
|
2146
|
+
params
|
2147
|
+
});
|
2148
|
+
if (error) {
|
2149
|
+
throw error;
|
2150
|
+
}
|
2151
|
+
if (data) {
|
2152
|
+
setServerCountOfDraftRelations(data.data);
|
2153
|
+
}
|
2154
|
+
};
|
2155
|
+
fetchDraftRelationsCount();
|
2156
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2157
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1696
2158
|
if (!schema?.options?.draftAndPublish) {
|
1697
2159
|
return null;
|
1698
2160
|
}
|
2161
|
+
const performPublish = async () => {
|
2162
|
+
setSubmitting(true);
|
2163
|
+
try {
|
2164
|
+
const { errors } = await validate(true, {
|
2165
|
+
status: "published"
|
2166
|
+
});
|
2167
|
+
if (errors) {
|
2168
|
+
toggleNotification({
|
2169
|
+
type: "danger",
|
2170
|
+
message: formatMessage({
|
2171
|
+
id: "content-manager.validation.error",
|
2172
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2173
|
+
})
|
2174
|
+
});
|
2175
|
+
return;
|
2176
|
+
}
|
2177
|
+
const res = await publish(
|
2178
|
+
{
|
2179
|
+
collectionType,
|
2180
|
+
model,
|
2181
|
+
documentId,
|
2182
|
+
params
|
2183
|
+
},
|
2184
|
+
transformData(formValues)
|
2185
|
+
);
|
2186
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2187
|
+
if (id === "create") {
|
2188
|
+
navigate({
|
2189
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2190
|
+
search: rawQuery
|
2191
|
+
});
|
2192
|
+
}
|
2193
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2194
|
+
setErrors(formatValidationErrors(res.error));
|
2195
|
+
}
|
2196
|
+
} finally {
|
2197
|
+
setSubmitting(false);
|
2198
|
+
}
|
2199
|
+
};
|
2200
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2201
|
+
const enableDraftRelationsCount = false;
|
2202
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1699
2203
|
return {
|
1700
2204
|
/**
|
1701
2205
|
* Disabled when:
|
@@ -1705,49 +2209,36 @@ const PublishAction$1 = ({
|
|
1705
2209
|
* - the document is already published & not modified
|
1706
2210
|
* - the document is being created & not modified
|
1707
2211
|
* - the user doesn't have the permission to publish
|
1708
|
-
* - the user doesn't have the permission to create a new document
|
1709
|
-
* - the user doesn't have the permission to update the document
|
1710
2212
|
*/
|
1711
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2213
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1712
2214
|
label: formatMessage({
|
1713
2215
|
id: "app.utils.publish",
|
1714
2216
|
defaultMessage: "Publish"
|
1715
2217
|
}),
|
1716
2218
|
onClick: async () => {
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
documentId,
|
1735
|
-
params
|
1736
|
-
},
|
1737
|
-
formValues
|
1738
|
-
);
|
1739
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1740
|
-
navigate({
|
1741
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1742
|
-
search: rawQuery
|
1743
|
-
});
|
1744
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1745
|
-
setErrors(formatValidationErrors(res.error));
|
2219
|
+
await performPublish();
|
2220
|
+
},
|
2221
|
+
dialog: hasDraftRelations ? {
|
2222
|
+
type: "dialog",
|
2223
|
+
variant: "danger",
|
2224
|
+
footer: null,
|
2225
|
+
title: formatMessage({
|
2226
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2227
|
+
defaultMessage: "Confirmation"
|
2228
|
+
}),
|
2229
|
+
content: formatMessage(
|
2230
|
+
{
|
2231
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2232
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2233
|
+
},
|
2234
|
+
{
|
2235
|
+
count: totalDraftRelations
|
1746
2236
|
}
|
1747
|
-
|
1748
|
-
|
2237
|
+
),
|
2238
|
+
onConfirm: async () => {
|
2239
|
+
await performPublish();
|
1749
2240
|
}
|
1750
|
-
}
|
2241
|
+
} : void 0
|
1751
2242
|
};
|
1752
2243
|
};
|
1753
2244
|
PublishAction$1.type = "publish";
|
@@ -1763,10 +2254,6 @@ const UpdateAction = ({
|
|
1763
2254
|
const cloneMatch = useMatch(CLONE_PATH);
|
1764
2255
|
const isCloning = cloneMatch !== null;
|
1765
2256
|
const { formatMessage } = useIntl();
|
1766
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1767
|
-
canCreate: canCreate2,
|
1768
|
-
canUpdate: canUpdate2
|
1769
|
-
}));
|
1770
2257
|
const { create, update, clone } = useDocumentActions();
|
1771
2258
|
const [{ query, rawQuery }] = useQueryParams();
|
1772
2259
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
@@ -1783,18 +2270,18 @@ const UpdateAction = ({
|
|
1783
2270
|
* - the form is submitting
|
1784
2271
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1785
2272
|
* - the active tab is the published tab
|
1786
|
-
* - the user doesn't have the permission to create a new document
|
1787
|
-
* - the user doesn't have the permission to update the document
|
1788
2273
|
*/
|
1789
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2274
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1790
2275
|
label: formatMessage({
|
1791
|
-
id: "
|
2276
|
+
id: "global.save",
|
1792
2277
|
defaultMessage: "Save"
|
1793
2278
|
}),
|
1794
2279
|
onClick: async () => {
|
1795
2280
|
setSubmitting(true);
|
1796
2281
|
try {
|
1797
|
-
const { errors } = await validate(
|
2282
|
+
const { errors } = await validate(true, {
|
2283
|
+
status: "draft"
|
2284
|
+
});
|
1798
2285
|
if (errors) {
|
1799
2286
|
toggleNotification({
|
1800
2287
|
type: "danger",
|
@@ -1812,13 +2299,16 @@ const UpdateAction = ({
|
|
1812
2299
|
documentId: cloneMatch.params.origin,
|
1813
2300
|
params
|
1814
2301
|
},
|
1815
|
-
document
|
2302
|
+
transformData(document)
|
1816
2303
|
);
|
1817
2304
|
if ("data" in res) {
|
1818
|
-
navigate(
|
1819
|
-
|
1820
|
-
|
1821
|
-
|
2305
|
+
navigate(
|
2306
|
+
{
|
2307
|
+
pathname: `../${res.data.documentId}`,
|
2308
|
+
search: rawQuery
|
2309
|
+
},
|
2310
|
+
{ relative: "path" }
|
2311
|
+
);
|
1822
2312
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1823
2313
|
setErrors(formatValidationErrors(res.error));
|
1824
2314
|
}
|
@@ -1830,7 +2320,7 @@ const UpdateAction = ({
|
|
1830
2320
|
documentId,
|
1831
2321
|
params
|
1832
2322
|
},
|
1833
|
-
document
|
2323
|
+
transformData(document)
|
1834
2324
|
);
|
1835
2325
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1836
2326
|
setErrors(formatValidationErrors(res.error));
|
@@ -1843,15 +2333,15 @@ const UpdateAction = ({
|
|
1843
2333
|
model,
|
1844
2334
|
params
|
1845
2335
|
},
|
1846
|
-
document
|
2336
|
+
transformData(document)
|
1847
2337
|
);
|
1848
2338
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1849
2339
|
navigate(
|
1850
2340
|
{
|
1851
|
-
pathname: `../${
|
2341
|
+
pathname: `../${res.data.documentId}`,
|
1852
2342
|
search: rawQuery
|
1853
2343
|
},
|
1854
|
-
{ replace: true }
|
2344
|
+
{ replace: true, relative: "path" }
|
1855
2345
|
);
|
1856
2346
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1857
2347
|
setErrors(formatValidationErrors(res.error));
|
@@ -1896,7 +2386,7 @@ const UnpublishAction$1 = ({
|
|
1896
2386
|
id: "app.utils.unpublish",
|
1897
2387
|
defaultMessage: "Unpublish"
|
1898
2388
|
}),
|
1899
|
-
icon: /* @__PURE__ */ jsx(
|
2389
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1900
2390
|
onClick: async () => {
|
1901
2391
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1902
2392
|
if (!documentId) {
|
@@ -2008,7 +2498,7 @@ const DiscardAction = ({
|
|
2008
2498
|
id: "content-manager.actions.discard.label",
|
2009
2499
|
defaultMessage: "Discard changes"
|
2010
2500
|
}),
|
2011
|
-
icon: /* @__PURE__ */ jsx(
|
2501
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2012
2502
|
position: ["panel", "table-row"],
|
2013
2503
|
variant: "danger",
|
2014
2504
|
dialog: {
|
@@ -2036,11 +2526,6 @@ const DiscardAction = ({
|
|
2036
2526
|
};
|
2037
2527
|
};
|
2038
2528
|
DiscardAction.type = "discard";
|
2039
|
-
const StyledCrossCircle = styled(CrossCircle)`
|
2040
|
-
path {
|
2041
|
-
fill: currentColor;
|
2042
|
-
}
|
2043
|
-
`;
|
2044
2529
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2045
2530
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2046
2531
|
const RelativeTime = React.forwardRef(
|
@@ -2053,7 +2538,7 @@ const RelativeTime = React.forwardRef(
|
|
2053
2538
|
});
|
2054
2539
|
const unit = intervals.find((intervalUnit) => {
|
2055
2540
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2056
|
-
});
|
2541
|
+
}) ?? "seconds";
|
2057
2542
|
const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
|
2058
2543
|
const customInterval = customIntervals.find(
|
2059
2544
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2087,34 +2572,34 @@ const getDisplayName = ({
|
|
2087
2572
|
return email ?? "";
|
2088
2573
|
};
|
2089
2574
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2090
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2091
|
-
const statusVariant = status === "draft" ? "
|
2092
|
-
|
2575
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2576
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2577
|
+
const { formatMessage } = useIntl();
|
2578
|
+
return /* @__PURE__ */ jsx(Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2579
|
+
id: `content-manager.containers.List.${status}`,
|
2580
|
+
defaultMessage: capitalise(status)
|
2581
|
+
}) }) });
|
2093
2582
|
};
|
2094
2583
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2095
2584
|
const { formatMessage } = useIntl();
|
2096
2585
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2586
|
+
const params = useParams();
|
2097
2587
|
const title = isCreating ? formatMessage({
|
2098
2588
|
id: "content-manager.containers.edit.title.new",
|
2099
2589
|
defaultMessage: "Create an entry"
|
2100
2590
|
}) : documentTitle;
|
2101
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2102
|
-
/* @__PURE__ */ jsx(
|
2103
|
-
|
2104
|
-
Flex,
|
2591
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2592
|
+
/* @__PURE__ */ jsx(
|
2593
|
+
BackButton,
|
2105
2594
|
{
|
2106
|
-
|
2107
|
-
justifyContent: "space-between",
|
2108
|
-
paddingTop: 1,
|
2109
|
-
gap: "80px",
|
2110
|
-
alignItems: "flex-start",
|
2111
|
-
children: [
|
2112
|
-
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2113
|
-
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2114
|
-
]
|
2595
|
+
fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
|
2115
2596
|
}
|
2116
2597
|
),
|
2117
|
-
|
2598
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2599
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2600
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2601
|
+
] }),
|
2602
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2118
2603
|
] });
|
2119
2604
|
};
|
2120
2605
|
const HeaderToolbar = () => {
|
@@ -2197,12 +2682,12 @@ const Information = ({ activeTab }) => {
|
|
2197
2682
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2198
2683
|
label: formatMessage({
|
2199
2684
|
id: "content-manager.containers.edit.information.last-published.label",
|
2200
|
-
defaultMessage: "
|
2685
|
+
defaultMessage: "Published"
|
2201
2686
|
}),
|
2202
2687
|
value: formatMessage(
|
2203
2688
|
{
|
2204
2689
|
id: "content-manager.containers.edit.information.last-published.value",
|
2205
|
-
defaultMessage: `
|
2690
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2206
2691
|
},
|
2207
2692
|
{
|
2208
2693
|
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2215,12 +2700,12 @@ const Information = ({ activeTab }) => {
|
|
2215
2700
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2216
2701
|
label: formatMessage({
|
2217
2702
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2218
|
-
defaultMessage: "
|
2703
|
+
defaultMessage: "Updated"
|
2219
2704
|
}),
|
2220
2705
|
value: formatMessage(
|
2221
2706
|
{
|
2222
2707
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2223
|
-
defaultMessage: `
|
2708
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2224
2709
|
},
|
2225
2710
|
{
|
2226
2711
|
time: /* @__PURE__ */ jsx(
|
@@ -2238,12 +2723,12 @@ const Information = ({ activeTab }) => {
|
|
2238
2723
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2239
2724
|
label: formatMessage({
|
2240
2725
|
id: "content-manager.containers.edit.information.document.label",
|
2241
|
-
defaultMessage: "
|
2726
|
+
defaultMessage: "Created"
|
2242
2727
|
}),
|
2243
2728
|
value: formatMessage(
|
2244
2729
|
{
|
2245
2730
|
id: "content-manager.containers.edit.information.document.value",
|
2246
|
-
defaultMessage: `
|
2731
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2247
2732
|
},
|
2248
2733
|
{
|
2249
2734
|
time: /* @__PURE__ */ jsx(
|
@@ -2281,25 +2766,77 @@ const Information = ({ activeTab }) => {
|
|
2281
2766
|
);
|
2282
2767
|
};
|
2283
2768
|
const HeaderActions = ({ actions: actions2 }) => {
|
2284
|
-
|
2285
|
-
|
2769
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2770
|
+
const handleClick = (action) => async (e) => {
|
2771
|
+
if (!("options" in action)) {
|
2772
|
+
const { onClick = () => false, dialog, id } = action;
|
2773
|
+
const muteDialog = await onClick(e);
|
2774
|
+
if (dialog && !muteDialog) {
|
2775
|
+
e.preventDefault();
|
2776
|
+
setDialogId(id);
|
2777
|
+
}
|
2778
|
+
}
|
2779
|
+
};
|
2780
|
+
const handleClose = () => {
|
2781
|
+
setDialogId(null);
|
2782
|
+
};
|
2783
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2784
|
+
if (action.options) {
|
2286
2785
|
return /* @__PURE__ */ jsx(
|
2287
2786
|
SingleSelect,
|
2288
2787
|
{
|
2289
2788
|
size: "S",
|
2290
|
-
disabled: action.disabled,
|
2291
|
-
"aria-label": action.label,
|
2292
2789
|
onChange: action.onSelect,
|
2293
|
-
|
2790
|
+
"aria-label": action.label,
|
2791
|
+
...action,
|
2294
2792
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2295
2793
|
},
|
2296
2794
|
action.id
|
2297
2795
|
);
|
2298
2796
|
} else {
|
2299
|
-
|
2797
|
+
if (action.type === "icon") {
|
2798
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2799
|
+
/* @__PURE__ */ jsx(
|
2800
|
+
IconButton,
|
2801
|
+
{
|
2802
|
+
disabled: action.disabled,
|
2803
|
+
label: action.label,
|
2804
|
+
size: "S",
|
2805
|
+
onClick: handleClick(action),
|
2806
|
+
children: action.icon
|
2807
|
+
}
|
2808
|
+
),
|
2809
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2810
|
+
HeaderActionDialog,
|
2811
|
+
{
|
2812
|
+
...action.dialog,
|
2813
|
+
isOpen: dialogId === action.id,
|
2814
|
+
onClose: handleClose
|
2815
|
+
}
|
2816
|
+
) : null
|
2817
|
+
] }, action.id);
|
2818
|
+
}
|
2300
2819
|
}
|
2301
2820
|
}) });
|
2302
2821
|
};
|
2822
|
+
const HeaderActionDialog = ({
|
2823
|
+
onClose,
|
2824
|
+
onCancel,
|
2825
|
+
title,
|
2826
|
+
content: Content,
|
2827
|
+
isOpen
|
2828
|
+
}) => {
|
2829
|
+
const handleClose = async () => {
|
2830
|
+
if (onCancel) {
|
2831
|
+
await onCancel();
|
2832
|
+
}
|
2833
|
+
onClose();
|
2834
|
+
};
|
2835
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2836
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2837
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2838
|
+
] }) });
|
2839
|
+
};
|
2303
2840
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2304
2841
|
const navigate = useNavigate();
|
2305
2842
|
const { formatMessage } = useIntl();
|
@@ -2340,12 +2877,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2340
2877
|
const { delete: deleteAction } = useDocumentActions();
|
2341
2878
|
const { toggleNotification } = useNotification();
|
2342
2879
|
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2880
|
+
const isLocalized = document?.locale != null;
|
2343
2881
|
return {
|
2344
2882
|
disabled: !canDelete || !document,
|
2345
|
-
label: formatMessage(
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2883
|
+
label: formatMessage(
|
2884
|
+
{
|
2885
|
+
id: "content-manager.actions.delete.label",
|
2886
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2887
|
+
},
|
2888
|
+
{ isLocalized }
|
2889
|
+
),
|
2349
2890
|
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2350
2891
|
dialog: {
|
2351
2892
|
type: "dialog",
|
@@ -2396,408 +2937,106 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2396
2937
|
}
|
2397
2938
|
}
|
2398
2939
|
},
|
2399
|
-
variant: "danger",
|
2400
|
-
position: ["header", "table-row"]
|
2401
|
-
};
|
2402
|
-
};
|
2403
|
-
DeleteAction$1.type = "delete";
|
2404
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2405
|
-
const Panels = () => {
|
2406
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2407
|
-
const [
|
2408
|
-
{
|
2409
|
-
query: { status }
|
2410
|
-
}
|
2411
|
-
] = useQueryParams({
|
2412
|
-
status: "draft"
|
2413
|
-
});
|
2414
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2415
|
-
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2416
|
-
const props = {
|
2417
|
-
activeTab: status,
|
2418
|
-
model,
|
2419
|
-
documentId: id,
|
2420
|
-
document: isCloning ? void 0 : document,
|
2421
|
-
meta: isCloning ? void 0 : meta,
|
2422
|
-
collectionType
|
2423
|
-
};
|
2424
|
-
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2425
|
-
DescriptionComponentRenderer,
|
2426
|
-
{
|
2427
|
-
props,
|
2428
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2429
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2430
|
-
}
|
2431
|
-
) });
|
2432
|
-
};
|
2433
|
-
const ActionsPanel = () => {
|
2434
|
-
const { formatMessage } = useIntl();
|
2435
|
-
return {
|
2436
|
-
title: formatMessage({
|
2437
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2438
|
-
defaultMessage: "Document"
|
2439
|
-
}),
|
2440
|
-
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2441
|
-
};
|
2442
|
-
};
|
2443
|
-
ActionsPanel.type = "actions";
|
2444
|
-
const ActionsPanelContent = () => {
|
2445
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2446
|
-
const [
|
2447
|
-
{
|
2448
|
-
query: { status = "draft" }
|
2449
|
-
}
|
2450
|
-
] = useQueryParams();
|
2451
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2452
|
-
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2453
|
-
const props = {
|
2454
|
-
activeTab: status,
|
2455
|
-
model,
|
2456
|
-
documentId: id,
|
2457
|
-
document: isCloning ? void 0 : document,
|
2458
|
-
meta: isCloning ? void 0 : meta,
|
2459
|
-
collectionType
|
2460
|
-
};
|
2461
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2462
|
-
/* @__PURE__ */ jsx(
|
2463
|
-
DescriptionComponentRenderer,
|
2464
|
-
{
|
2465
|
-
props,
|
2466
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2467
|
-
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2468
|
-
}
|
2469
|
-
),
|
2470
|
-
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2471
|
-
] });
|
2472
|
-
};
|
2473
|
-
const Panel = React.forwardRef(({ children, title }, ref) => {
|
2474
|
-
return /* @__PURE__ */ jsxs(
|
2475
|
-
Flex,
|
2476
|
-
{
|
2477
|
-
ref,
|
2478
|
-
tag: "aside",
|
2479
|
-
"aria-labelledby": "additional-information",
|
2480
|
-
background: "neutral0",
|
2481
|
-
borderColor: "neutral150",
|
2482
|
-
hasRadius: true,
|
2483
|
-
paddingBottom: 4,
|
2484
|
-
paddingLeft: 4,
|
2485
|
-
paddingRight: 4,
|
2486
|
-
paddingTop: 4,
|
2487
|
-
shadow: "tableShadow",
|
2488
|
-
gap: 3,
|
2489
|
-
direction: "column",
|
2490
|
-
justifyContent: "stretch",
|
2491
|
-
alignItems: "flex-start",
|
2492
|
-
children: [
|
2493
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2494
|
-
children
|
2495
|
-
]
|
2496
|
-
}
|
2497
|
-
);
|
2498
|
-
});
|
2499
|
-
const HOOKS = {
|
2500
|
-
/**
|
2501
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2502
|
-
* @constant
|
2503
|
-
* @type {string}
|
2504
|
-
*/
|
2505
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2506
|
-
/**
|
2507
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2508
|
-
* @constant
|
2509
|
-
* @type {string}
|
2510
|
-
*/
|
2511
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2512
|
-
/**
|
2513
|
-
* Hook that allows to mutate the CM's edit view layout
|
2514
|
-
* @constant
|
2515
|
-
* @type {string}
|
2516
|
-
*/
|
2517
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2518
|
-
/**
|
2519
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2520
|
-
* @constant
|
2521
|
-
* @type {string}
|
2522
|
-
*/
|
2523
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2524
|
-
};
|
2525
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2526
|
-
endpoints: (builder) => ({
|
2527
|
-
getContentTypeConfiguration: builder.query({
|
2528
|
-
query: (uid) => ({
|
2529
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2530
|
-
method: "GET"
|
2531
|
-
}),
|
2532
|
-
transformResponse: (response) => response.data,
|
2533
|
-
providesTags: (_result, _error, uid) => [
|
2534
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2535
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2536
|
-
]
|
2537
|
-
}),
|
2538
|
-
getAllContentTypeSettings: builder.query({
|
2539
|
-
query: () => "/content-manager/content-types-settings",
|
2540
|
-
transformResponse: (response) => response.data,
|
2541
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2542
|
-
}),
|
2543
|
-
updateContentTypeConfiguration: builder.mutation({
|
2544
|
-
query: ({ uid, ...body }) => ({
|
2545
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2546
|
-
method: "PUT",
|
2547
|
-
data: body
|
2548
|
-
}),
|
2549
|
-
transformResponse: (response) => response.data,
|
2550
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2551
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2552
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2553
|
-
// Is this necessary?
|
2554
|
-
{ type: "InitialData" }
|
2555
|
-
]
|
2556
|
-
})
|
2557
|
-
})
|
2558
|
-
});
|
2559
|
-
const {
|
2560
|
-
useGetContentTypeConfigurationQuery,
|
2561
|
-
useGetAllContentTypeSettingsQuery,
|
2562
|
-
useUpdateContentTypeConfigurationMutation
|
2563
|
-
} = contentTypesApi;
|
2564
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2565
|
-
const { type } = attribute;
|
2566
|
-
if (type === "relation") {
|
2567
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2568
|
-
}
|
2569
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2570
|
-
};
|
2571
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2572
|
-
if (!mainFieldName) {
|
2573
|
-
return void 0;
|
2574
|
-
}
|
2575
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2576
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2577
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2578
|
-
);
|
2579
|
-
return {
|
2580
|
-
name: mainFieldName,
|
2581
|
-
type: mainFieldType ?? "string"
|
2582
|
-
};
|
2583
|
-
};
|
2584
|
-
const DEFAULT_SETTINGS = {
|
2585
|
-
bulkable: false,
|
2586
|
-
filterable: false,
|
2587
|
-
searchable: false,
|
2588
|
-
pagination: false,
|
2589
|
-
defaultSortBy: "",
|
2590
|
-
defaultSortOrder: "asc",
|
2591
|
-
mainField: "id",
|
2592
|
-
pageSize: 10
|
2593
|
-
};
|
2594
|
-
const useDocumentLayout = (model) => {
|
2595
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2596
|
-
const [{ query }] = useQueryParams();
|
2597
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2598
|
-
const { toggleNotification } = useNotification();
|
2599
|
-
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2600
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2601
|
-
const {
|
2602
|
-
data,
|
2603
|
-
isLoading: isLoadingConfigs,
|
2604
|
-
error,
|
2605
|
-
isFetching: isFetchingConfigs
|
2606
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2607
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2608
|
-
React.useEffect(() => {
|
2609
|
-
if (error) {
|
2610
|
-
toggleNotification({
|
2611
|
-
type: "danger",
|
2612
|
-
message: formatAPIError(error)
|
2613
|
-
});
|
2614
|
-
}
|
2615
|
-
}, [error, formatAPIError, toggleNotification]);
|
2616
|
-
const editLayout = React.useMemo(
|
2617
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2618
|
-
layout: [],
|
2619
|
-
components: {},
|
2620
|
-
metadatas: {},
|
2621
|
-
options: {},
|
2622
|
-
settings: DEFAULT_SETTINGS
|
2623
|
-
},
|
2624
|
-
[data, isLoading, schemas, schema, components]
|
2625
|
-
);
|
2626
|
-
const listLayout = React.useMemo(() => {
|
2627
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2628
|
-
layout: [],
|
2629
|
-
metadatas: {},
|
2630
|
-
options: {},
|
2631
|
-
settings: DEFAULT_SETTINGS
|
2632
|
-
};
|
2633
|
-
}, [data, isLoading, schemas, schema, components]);
|
2634
|
-
const { layout: edit } = React.useMemo(
|
2635
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2636
|
-
layout: editLayout,
|
2637
|
-
query
|
2638
|
-
}),
|
2639
|
-
[editLayout, query, runHookWaterfall]
|
2640
|
-
);
|
2641
|
-
return {
|
2642
|
-
error,
|
2643
|
-
isLoading,
|
2644
|
-
edit,
|
2645
|
-
list: listLayout
|
2646
|
-
};
|
2647
|
-
};
|
2648
|
-
const useDocLayout = () => {
|
2649
|
-
const { model } = useDoc();
|
2650
|
-
return useDocumentLayout(model);
|
2651
|
-
};
|
2652
|
-
const formatEditLayout = (data, {
|
2653
|
-
schemas,
|
2654
|
-
schema,
|
2655
|
-
components
|
2656
|
-
}) => {
|
2657
|
-
let currentPanelIndex = 0;
|
2658
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2659
|
-
data.contentType.layouts.edit,
|
2660
|
-
schema?.attributes,
|
2661
|
-
data.contentType.metadatas,
|
2662
|
-
{ configurations: data.components, schemas: components },
|
2663
|
-
schemas
|
2664
|
-
).reduce((panels, row) => {
|
2665
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2666
|
-
panels.push([row]);
|
2667
|
-
currentPanelIndex += 2;
|
2668
|
-
} else {
|
2669
|
-
if (!panels[currentPanelIndex]) {
|
2670
|
-
panels.push([]);
|
2671
|
-
}
|
2672
|
-
panels[currentPanelIndex].push(row);
|
2673
|
-
}
|
2674
|
-
return panels;
|
2675
|
-
}, []);
|
2676
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2677
|
-
(acc, [uid, configuration]) => {
|
2678
|
-
acc[uid] = {
|
2679
|
-
layout: convertEditLayoutToFieldLayouts(
|
2680
|
-
configuration.layouts.edit,
|
2681
|
-
components[uid].attributes,
|
2682
|
-
configuration.metadatas
|
2683
|
-
),
|
2684
|
-
settings: {
|
2685
|
-
...configuration.settings,
|
2686
|
-
icon: components[uid].info.icon,
|
2687
|
-
displayName: components[uid].info.displayName
|
2688
|
-
}
|
2689
|
-
};
|
2690
|
-
return acc;
|
2691
|
-
},
|
2692
|
-
{}
|
2693
|
-
);
|
2694
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2695
|
-
(acc, [attribute, metadata]) => {
|
2696
|
-
return {
|
2697
|
-
...acc,
|
2698
|
-
[attribute]: metadata.edit
|
2699
|
-
};
|
2700
|
-
},
|
2701
|
-
{}
|
2702
|
-
);
|
2703
|
-
return {
|
2704
|
-
layout: panelledEditAttributes,
|
2705
|
-
components: componentEditAttributes,
|
2706
|
-
metadatas: editMetadatas,
|
2707
|
-
settings: {
|
2708
|
-
...data.contentType.settings,
|
2709
|
-
displayName: schema?.info.displayName
|
2710
|
-
},
|
2711
|
-
options: {
|
2712
|
-
...schema?.options,
|
2713
|
-
...schema?.pluginOptions,
|
2714
|
-
...data.contentType.options
|
2715
|
-
}
|
2940
|
+
variant: "danger",
|
2941
|
+
position: ["header", "table-row"]
|
2716
2942
|
};
|
2717
2943
|
};
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
|
2724
|
-
}
|
2725
|
-
|
2726
|
-
|
2727
|
-
|
2728
|
-
|
2729
|
-
|
2730
|
-
|
2731
|
-
|
2732
|
-
|
2733
|
-
|
2734
|
-
|
2735
|
-
|
2736
|
-
|
2737
|
-
|
2738
|
-
|
2739
|
-
|
2740
|
-
|
2741
|
-
|
2742
|
-
|
2743
|
-
|
2744
|
-
}
|
2745
|
-
}
|
2746
|
-
);
|
2944
|
+
DeleteAction$1.type = "delete";
|
2945
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2946
|
+
const Panels = () => {
|
2947
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2948
|
+
const [
|
2949
|
+
{
|
2950
|
+
query: { status }
|
2951
|
+
}
|
2952
|
+
] = useQueryParams({
|
2953
|
+
status: "draft"
|
2954
|
+
});
|
2955
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2956
|
+
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2957
|
+
const props = {
|
2958
|
+
activeTab: status,
|
2959
|
+
model,
|
2960
|
+
documentId: id,
|
2961
|
+
document: isCloning ? void 0 : document,
|
2962
|
+
meta: isCloning ? void 0 : meta,
|
2963
|
+
collectionType
|
2964
|
+
};
|
2965
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2966
|
+
DescriptionComponentRenderer,
|
2967
|
+
{
|
2968
|
+
props,
|
2969
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2970
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2971
|
+
}
|
2972
|
+
) });
|
2747
2973
|
};
|
2748
|
-
const
|
2749
|
-
|
2750
|
-
schema,
|
2751
|
-
components
|
2752
|
-
}) => {
|
2753
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2754
|
-
(acc, [attribute, metadata]) => {
|
2755
|
-
return {
|
2756
|
-
...acc,
|
2757
|
-
[attribute]: metadata.list
|
2758
|
-
};
|
2759
|
-
},
|
2760
|
-
{}
|
2761
|
-
);
|
2762
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2763
|
-
data.contentType.layouts.list,
|
2764
|
-
schema?.attributes,
|
2765
|
-
listMetadatas,
|
2766
|
-
{ configurations: data.components, schemas: components },
|
2767
|
-
schemas
|
2768
|
-
);
|
2974
|
+
const ActionsPanel = () => {
|
2975
|
+
const { formatMessage } = useIntl();
|
2769
2976
|
return {
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
|
2775
|
-
...schema?.pluginOptions,
|
2776
|
-
...data.contentType.options
|
2777
|
-
}
|
2977
|
+
title: formatMessage({
|
2978
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2979
|
+
defaultMessage: "Entry"
|
2980
|
+
}),
|
2981
|
+
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2778
2982
|
};
|
2779
2983
|
};
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2984
|
+
ActionsPanel.type = "actions";
|
2985
|
+
const ActionsPanelContent = () => {
|
2986
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2987
|
+
const [
|
2988
|
+
{
|
2989
|
+
query: { status = "draft" }
|
2785
2990
|
}
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
|
2991
|
+
] = useQueryParams();
|
2992
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2993
|
+
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2994
|
+
const props = {
|
2995
|
+
activeTab: status,
|
2996
|
+
model,
|
2997
|
+
documentId: id,
|
2998
|
+
document: isCloning ? void 0 : document,
|
2999
|
+
meta: isCloning ? void 0 : meta,
|
3000
|
+
collectionType
|
3001
|
+
};
|
3002
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3003
|
+
/* @__PURE__ */ jsx(
|
3004
|
+
DescriptionComponentRenderer,
|
3005
|
+
{
|
3006
|
+
props,
|
3007
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3008
|
+
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
3009
|
+
}
|
3010
|
+
),
|
3011
|
+
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3012
|
+
] });
|
2800
3013
|
};
|
3014
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
3015
|
+
return /* @__PURE__ */ jsxs(
|
3016
|
+
Flex,
|
3017
|
+
{
|
3018
|
+
ref,
|
3019
|
+
tag: "aside",
|
3020
|
+
"aria-labelledby": "additional-information",
|
3021
|
+
background: "neutral0",
|
3022
|
+
borderColor: "neutral150",
|
3023
|
+
hasRadius: true,
|
3024
|
+
paddingBottom: 4,
|
3025
|
+
paddingLeft: 4,
|
3026
|
+
paddingRight: 4,
|
3027
|
+
paddingTop: 4,
|
3028
|
+
shadow: "tableShadow",
|
3029
|
+
gap: 3,
|
3030
|
+
direction: "column",
|
3031
|
+
justifyContent: "stretch",
|
3032
|
+
alignItems: "flex-start",
|
3033
|
+
children: [
|
3034
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3035
|
+
children
|
3036
|
+
]
|
3037
|
+
}
|
3038
|
+
);
|
3039
|
+
});
|
2801
3040
|
const ConfirmBulkActionDialog = ({
|
2802
3041
|
onToggleDialog,
|
2803
3042
|
isOpen = false,
|
@@ -2805,7 +3044,7 @@ const ConfirmBulkActionDialog = ({
|
|
2805
3044
|
endAction
|
2806
3045
|
}) => {
|
2807
3046
|
const { formatMessage } = useIntl();
|
2808
|
-
return /* @__PURE__ */ jsx(Dialog.Root, {
|
3047
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2809
3048
|
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
|
2810
3049
|
id: "app.components.ConfirmDialog.title",
|
2811
3050
|
defaultMessage: "Confirmation"
|
@@ -2836,6 +3075,7 @@ const ConfirmDialogPublishAll = ({
|
|
2836
3075
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2837
3076
|
const { model, schema } = useDoc();
|
2838
3077
|
const [{ query }] = useQueryParams();
|
3078
|
+
const enableDraftRelationsCount = false;
|
2839
3079
|
const {
|
2840
3080
|
data: countDraftRelations = 0,
|
2841
3081
|
isLoading,
|
@@ -2847,7 +3087,7 @@ const ConfirmDialogPublishAll = ({
|
|
2847
3087
|
locale: query?.plugins?.i18n?.locale
|
2848
3088
|
},
|
2849
3089
|
{
|
2850
|
-
skip:
|
3090
|
+
skip: !enableDraftRelationsCount
|
2851
3091
|
}
|
2852
3092
|
);
|
2853
3093
|
React.useEffect(() => {
|
@@ -3032,7 +3272,7 @@ const SelectedEntriesTableContent = ({
|
|
3032
3272
|
status: row.status
|
3033
3273
|
}
|
3034
3274
|
) }),
|
3035
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3275
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3036
3276
|
IconButton,
|
3037
3277
|
{
|
3038
3278
|
tag: Link,
|
@@ -3041,23 +3281,16 @@ const SelectedEntriesTableContent = ({
|
|
3041
3281
|
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3042
3282
|
},
|
3043
3283
|
state: { from: pathname },
|
3044
|
-
label: formatMessage(
|
3045
|
-
|
3046
|
-
|
3047
|
-
|
3048
|
-
{
|
3049
|
-
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3050
|
-
defaultMessage: "item line {number}"
|
3051
|
-
},
|
3052
|
-
{ number: index2 + 1 }
|
3053
|
-
)
|
3054
|
-
}
|
3055
|
-
),
|
3284
|
+
label: formatMessage({
|
3285
|
+
id: "content-manager.bulk-publish.edit",
|
3286
|
+
defaultMessage: "Edit"
|
3287
|
+
}),
|
3056
3288
|
target: "_blank",
|
3057
3289
|
marginLeft: "auto",
|
3058
|
-
|
3290
|
+
variant: "ghost",
|
3291
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3059
3292
|
}
|
3060
|
-
) })
|
3293
|
+
) }) })
|
3061
3294
|
] }, row.id)) })
|
3062
3295
|
] });
|
3063
3296
|
};
|
@@ -3094,7 +3327,13 @@ const SelectedEntriesModalContent = ({
|
|
3094
3327
|
);
|
3095
3328
|
const { rows, validationErrors } = React.useMemo(() => {
|
3096
3329
|
if (data.length > 0 && schema) {
|
3097
|
-
const validate = createYupSchema(
|
3330
|
+
const validate = createYupSchema(
|
3331
|
+
schema.attributes,
|
3332
|
+
components,
|
3333
|
+
// Since this is the "Publish" action, the validation
|
3334
|
+
// schema must enforce the rules for published entities
|
3335
|
+
{ status: "published" }
|
3336
|
+
);
|
3098
3337
|
const validationErrors2 = {};
|
3099
3338
|
const rows2 = data.map((entry) => {
|
3100
3339
|
try {
|
@@ -3444,7 +3683,7 @@ const TableActions = ({ document }) => {
|
|
3444
3683
|
DescriptionComponentRenderer,
|
3445
3684
|
{
|
3446
3685
|
props,
|
3447
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3686
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3448
3687
|
children: (actions2) => {
|
3449
3688
|
const tableRowActions = actions2.filter((action) => {
|
3450
3689
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3555,7 +3794,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3555
3794
|
}),
|
3556
3795
|
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3557
3796
|
footer: ({ onClose }) => {
|
3558
|
-
return /* @__PURE__ */ jsxs(
|
3797
|
+
return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3559
3798
|
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3560
3799
|
id: "cancel",
|
3561
3800
|
defaultMessage: "Cancel"
|
@@ -3596,8 +3835,7 @@ class ContentManagerPlugin {
|
|
3596
3835
|
documentActions = [
|
3597
3836
|
...DEFAULT_ACTIONS,
|
3598
3837
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3599
|
-
...DEFAULT_HEADER_ACTIONS
|
3600
|
-
HistoryAction
|
3838
|
+
...DEFAULT_HEADER_ACTIONS
|
3601
3839
|
];
|
3602
3840
|
editViewSidePanels = [ActionsPanel];
|
3603
3841
|
headerActions = [];
|
@@ -3686,6 +3924,62 @@ const getPrintableType = (value) => {
|
|
3686
3924
|
}
|
3687
3925
|
return nativeType;
|
3688
3926
|
};
|
3927
|
+
const HistoryAction = ({ model, document }) => {
|
3928
|
+
const { formatMessage } = useIntl();
|
3929
|
+
const [{ query }] = useQueryParams();
|
3930
|
+
const navigate = useNavigate();
|
3931
|
+
const { trackUsage } = useTracking();
|
3932
|
+
const { pathname } = useLocation();
|
3933
|
+
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3934
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3935
|
+
return null;
|
3936
|
+
}
|
3937
|
+
const handleOnClick = () => {
|
3938
|
+
const destination = { pathname: "history", search: pluginsQueryParams };
|
3939
|
+
trackUsage("willNavigate", {
|
3940
|
+
from: pathname,
|
3941
|
+
to: `${pathname}/${destination.pathname}`
|
3942
|
+
});
|
3943
|
+
navigate(destination);
|
3944
|
+
};
|
3945
|
+
return {
|
3946
|
+
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3947
|
+
label: formatMessage({
|
3948
|
+
id: "content-manager.history.document-action",
|
3949
|
+
defaultMessage: "Content History"
|
3950
|
+
}),
|
3951
|
+
onClick: handleOnClick,
|
3952
|
+
disabled: (
|
3953
|
+
/**
|
3954
|
+
* The user is creating a new document.
|
3955
|
+
* It hasn't been saved yet, so there's no history to go to
|
3956
|
+
*/
|
3957
|
+
!document || /**
|
3958
|
+
* The document has been created but the current dimension has never been saved.
|
3959
|
+
* For example, the user is creating a new locale in an existing document,
|
3960
|
+
* so there's no history for the document in that locale
|
3961
|
+
*/
|
3962
|
+
!document.id || /**
|
3963
|
+
* History is only available for content types created by the user.
|
3964
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3965
|
+
* which start with `admin::` or `plugin::`
|
3966
|
+
*/
|
3967
|
+
!model.startsWith("api::")
|
3968
|
+
),
|
3969
|
+
position: "header"
|
3970
|
+
};
|
3971
|
+
};
|
3972
|
+
HistoryAction.type = "history";
|
3973
|
+
const historyAdmin = {
|
3974
|
+
bootstrap(app) {
|
3975
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3976
|
+
addDocumentAction((actions2) => {
|
3977
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3978
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3979
|
+
return actions2;
|
3980
|
+
});
|
3981
|
+
}
|
3982
|
+
};
|
3689
3983
|
const initialState = {
|
3690
3984
|
collectionTypeLinks: [],
|
3691
3985
|
components: [],
|
@@ -3722,6 +4016,72 @@ const { setInitialData } = actions;
|
|
3722
4016
|
const reducer = combineReducers({
|
3723
4017
|
app: reducer$1
|
3724
4018
|
});
|
4019
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4020
|
+
endpoints: (builder) => ({
|
4021
|
+
getPreviewUrl: builder.query({
|
4022
|
+
query({ query, params }) {
|
4023
|
+
return {
|
4024
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4025
|
+
method: "GET",
|
4026
|
+
config: {
|
4027
|
+
params: query
|
4028
|
+
}
|
4029
|
+
};
|
4030
|
+
}
|
4031
|
+
})
|
4032
|
+
})
|
4033
|
+
});
|
4034
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4035
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4036
|
+
const { formatMessage } = useIntl();
|
4037
|
+
const { trackUsage } = useTracking();
|
4038
|
+
const { pathname } = useLocation();
|
4039
|
+
const [{ query }] = useQueryParams();
|
4040
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4041
|
+
params: {
|
4042
|
+
contentType: model
|
4043
|
+
},
|
4044
|
+
query: {
|
4045
|
+
documentId,
|
4046
|
+
locale: document?.locale,
|
4047
|
+
status: document?.status
|
4048
|
+
}
|
4049
|
+
});
|
4050
|
+
if (!data?.data?.url || error) {
|
4051
|
+
return null;
|
4052
|
+
}
|
4053
|
+
const trackNavigation = () => {
|
4054
|
+
const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
|
4055
|
+
trackUsage("willNavigate", { from: pathname, to: destinationPathname });
|
4056
|
+
};
|
4057
|
+
return {
|
4058
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4059
|
+
content: /* @__PURE__ */ jsx(Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsx(
|
4060
|
+
Button,
|
4061
|
+
{
|
4062
|
+
variant: "tertiary",
|
4063
|
+
tag: Link,
|
4064
|
+
to: { pathname: "preview", search: stringify(query, { encode: false }) },
|
4065
|
+
onClick: trackNavigation,
|
4066
|
+
flex: "auto",
|
4067
|
+
children: formatMessage({
|
4068
|
+
id: "content-manager.preview.panel.button",
|
4069
|
+
defaultMessage: "Open preview"
|
4070
|
+
})
|
4071
|
+
}
|
4072
|
+
) })
|
4073
|
+
};
|
4074
|
+
};
|
4075
|
+
const FEATURE_ID = "preview";
|
4076
|
+
const previewAdmin = {
|
4077
|
+
bootstrap(app) {
|
4078
|
+
if (!window.strapi.future.isEnabled(FEATURE_ID)) {
|
4079
|
+
return;
|
4080
|
+
}
|
4081
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4082
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4083
|
+
}
|
4084
|
+
};
|
3725
4085
|
const index = {
|
3726
4086
|
register(app) {
|
3727
4087
|
const cm = new ContentManagerPlugin();
|
@@ -3741,7 +4101,7 @@ const index = {
|
|
3741
4101
|
app.router.addRoute({
|
3742
4102
|
path: "content-manager/*",
|
3743
4103
|
lazy: async () => {
|
3744
|
-
const { Layout } = await import("./layout-
|
4104
|
+
const { Layout } = await import("./layout-DhMZ_lDx.mjs");
|
3745
4105
|
return {
|
3746
4106
|
Component: Layout
|
3747
4107
|
};
|
@@ -3750,10 +4110,18 @@ const index = {
|
|
3750
4110
|
});
|
3751
4111
|
app.registerPlugin(cm.config);
|
3752
4112
|
},
|
4113
|
+
bootstrap(app) {
|
4114
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4115
|
+
historyAdmin.bootstrap(app);
|
4116
|
+
}
|
4117
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4118
|
+
previewAdmin.bootstrap(app);
|
4119
|
+
}
|
4120
|
+
},
|
3753
4121
|
async registerTrads({ locales }) {
|
3754
4122
|
const importedTrads = await Promise.all(
|
3755
4123
|
locales.map((locale) => {
|
3756
|
-
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-
|
4124
|
+
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-DhFUjrNW.mjs"), "./translations/es.json": () => import("./es-D34tqjMw.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr--pg5jUbt.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-BHqhDq4V.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 }) => {
|
3757
4125
|
return {
|
3758
4126
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3759
4127
|
locale
|
@@ -3774,13 +4142,16 @@ export {
|
|
3774
4142
|
BulkActionsRenderer as B,
|
3775
4143
|
COLLECTION_TYPES as C,
|
3776
4144
|
DocumentStatus as D,
|
3777
|
-
|
3778
|
-
|
3779
|
-
|
4145
|
+
extractContentTypeComponents as E,
|
4146
|
+
DEFAULT_SETTINGS as F,
|
4147
|
+
convertEditLayoutToFieldLayouts as G,
|
3780
4148
|
HOOKS as H,
|
3781
4149
|
InjectionZone as I,
|
3782
|
-
|
3783
|
-
|
4150
|
+
useDocument as J,
|
4151
|
+
useGetPreviewUrlQuery as K,
|
4152
|
+
index as L,
|
4153
|
+
useContentManagerContext as M,
|
4154
|
+
useDocumentActions as N,
|
3784
4155
|
Panels as P,
|
3785
4156
|
RelativeTime as R,
|
3786
4157
|
SINGLE_TYPES as S,
|
@@ -3798,18 +4169,18 @@ export {
|
|
3798
4169
|
PERMISSIONS as k,
|
3799
4170
|
DocumentRBAC as l,
|
3800
4171
|
DOCUMENT_META_FIELDS as m,
|
3801
|
-
|
3802
|
-
|
3803
|
-
|
3804
|
-
|
3805
|
-
|
4172
|
+
CLONE_PATH as n,
|
4173
|
+
useDocLayout as o,
|
4174
|
+
useGetContentTypeConfigurationQuery as p,
|
4175
|
+
CREATOR_FIELDS as q,
|
4176
|
+
getMainField as r,
|
3806
4177
|
setInitialData as s,
|
3807
|
-
|
4178
|
+
getDisplayName as t,
|
3808
4179
|
useContentTypeSchema as u,
|
3809
|
-
|
3810
|
-
|
3811
|
-
|
3812
|
-
|
3813
|
-
|
4180
|
+
checkIfAttributeIsDisplayable as v,
|
4181
|
+
useGetAllDocumentsQuery as w,
|
4182
|
+
convertListLayoutToFieldLayouts as x,
|
4183
|
+
capitalise as y,
|
4184
|
+
useUpdateContentTypeConfigurationMutation as z
|
3814
4185
|
};
|
3815
|
-
//# sourceMappingURL=index-
|
4186
|
+
//# sourceMappingURL=index-BpxR3En4.mjs.map
|