@strapi/content-manager 0.0.0-experimental.745741d19e90275ca6f7c928ca19f9bb0fd9d933 → 0.0.0-experimental.76999222c105ee5da1bc2540e3b5e5f57747300c
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-DHNM3YBz.mjs → ComponentConfigurationPage-BUOQFZ08.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DHNM3YBz.mjs.map → ComponentConfigurationPage-BUOQFZ08.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js → ComponentConfigurationPage-WtZ2yaRP.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js.map → ComponentConfigurationPage-WtZ2yaRP.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js → EditConfigurationPage-BVrCP5lF.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js.map → EditConfigurationPage-BVrCP5lF.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs → EditConfigurationPage-D7HkxcAN.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs.map → EditConfigurationPage-D7HkxcAN.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-BqNpC6hO.js → EditViewPage-BKQ83NAk.js} +30 -9
- package/dist/_chunks/EditViewPage-BKQ83NAk.js.map +1 -0
- package/dist/_chunks/{EditViewPage-BtkEx339.mjs → EditViewPage-zKmMBER4.mjs} +30 -9
- package/dist/_chunks/EditViewPage-zKmMBER4.mjs.map +1 -0
- package/dist/_chunks/{Field-R5NbffTB.mjs → Field-BbrX_tUG.mjs} +249 -152
- package/dist/_chunks/Field-BbrX_tUG.mjs.map +1 -0
- package/dist/_chunks/{Field-lsPFnAmH.js → Field-BhN0lyyZ.js} +251 -154
- package/dist/_chunks/Field-BhN0lyyZ.js.map +1 -0
- package/dist/_chunks/{Form-BHmXSfyy.mjs → Form-B-E8l73g.mjs} +36 -17
- package/dist/_chunks/Form-B-E8l73g.mjs.map +1 -0
- package/dist/_chunks/{Form-CcGboku8.js → Form-CkbrtNZd.js} +36 -17
- package/dist/_chunks/Form-CkbrtNZd.js.map +1 -0
- package/dist/_chunks/{History-Bsud8jwh.js → History-B2Dg9q7H.js} +61 -54
- package/dist/_chunks/History-B2Dg9q7H.js.map +1 -0
- package/dist/_chunks/{History-ByUPL3T3.mjs → History-C72HQ0-i.mjs} +62 -55
- package/dist/_chunks/History-C72HQ0-i.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DiT463qx.js → ListConfigurationPage-BQCc3BnJ.js} +21 -9
- package/dist/_chunks/ListConfigurationPage-BQCc3BnJ.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Bm5HACXf.mjs → ListConfigurationPage-BalSo5dp.mjs} +21 -9
- package/dist/_chunks/ListConfigurationPage-BalSo5dp.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-CsrC9L_d.js → ListViewPage-Cu5dZKZe.js} +61 -41
- package/dist/_chunks/ListViewPage-Cu5dZKZe.js.map +1 -0
- package/dist/_chunks/{ListViewPage-JSyNAAYu.mjs → ListViewPage-Dfue5wQ2.mjs} +59 -39
- package/dist/_chunks/ListViewPage-Dfue5wQ2.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs → NoContentTypePage-BLC8M9U0.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs.map → NoContentTypePage-BLC8M9U0.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-Bsvng4II.js → NoContentTypePage-MGzn4JPu.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-Bsvng4II.js.map → NoContentTypePage-MGzn4JPu.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs → NoPermissionsPage-BpAoEQy_.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs.map → NoPermissionsPage-BpAoEQy_.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js → NoPermissionsPage-DJPwEpOD.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js.map → NoPermissionsPage-DJPwEpOD.js.map} +1 -1
- package/dist/_chunks/{Relations-u8-37jK0.mjs → Relations-BULOkyWN.mjs} +73 -37
- package/dist/_chunks/Relations-BULOkyWN.mjs.map +1 -0
- package/dist/_chunks/{Relations-CghaPv2D.js → Relations-DTiqnyGx.js} +72 -36
- package/dist/_chunks/Relations-DTiqnyGx.js.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-C-J4DGEe.js} +20 -16
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-C-J4DGEe.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-DPfZ6tPQ.mjs} +20 -16
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-DPfZ6tPQ.mjs.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-BOZx6IMg.js → index-76eawJUd.js} +1034 -671
- package/dist/_chunks/index-76eawJUd.js.map +1 -0
- package/dist/_chunks/{index-CaE6NG4a.mjs → index-DW7xp_LG.mjs} +1052 -690
- package/dist/_chunks/index-DW7xp_LG.mjs.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-Ciz224q5.js → layout-CVz8WiDC.js} +22 -9
- package/dist/_chunks/layout-CVz8WiDC.js.map +1 -0
- package/dist/_chunks/{layout-Bx7svTbY.mjs → layout-DNfLIjbP.mjs} +23 -10
- package/dist/_chunks/layout-DNfLIjbP.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-CP8sB2YZ.js → relations-B6K4WRjW.js} +3 -7
- package/dist/_chunks/relations-B6K4WRjW.js.map +1 -0
- package/dist/_chunks/{relations-Cxc1cEv3.mjs → relations-ByHSIjSe.mjs} +3 -7
- package/dist/_chunks/relations-ByHSIjSe.mjs.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/components/DocumentActions.d.ts +1 -0
- 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/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/services/preview.d.ts +3 -0
- 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 -17
- 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 +544 -261
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +545 -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 +15 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +30 -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 +18 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- 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 +13 -13
- package/dist/_chunks/EditViewPage-BqNpC6hO.js.map +0 -1
- package/dist/_chunks/EditViewPage-BtkEx339.mjs.map +0 -1
- package/dist/_chunks/Field-R5NbffTB.mjs.map +0 -1
- package/dist/_chunks/Field-lsPFnAmH.js.map +0 -1
- package/dist/_chunks/Form-BHmXSfyy.mjs.map +0 -1
- package/dist/_chunks/Form-CcGboku8.js.map +0 -1
- package/dist/_chunks/History-Bsud8jwh.js.map +0 -1
- package/dist/_chunks/History-ByUPL3T3.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Bm5HACXf.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DiT463qx.js.map +0 -1
- package/dist/_chunks/ListViewPage-CsrC9L_d.js.map +0 -1
- package/dist/_chunks/ListViewPage-JSyNAAYu.mjs.map +0 -1
- package/dist/_chunks/Relations-CghaPv2D.js.map +0 -1
- package/dist/_chunks/Relations-u8-37jK0.mjs.map +0 -1
- package/dist/_chunks/index-BOZx6IMg.js.map +0 -1
- package/dist/_chunks/index-CaE6NG4a.mjs.map +0 -1
- package/dist/_chunks/layout-Bx7svTbY.mjs.map +0 -1
- package/dist/_chunks/layout-Ciz224q5.js.map +0 -1
- package/dist/_chunks/relations-CP8sB2YZ.js.map +0 -1
- package/dist/_chunks/relations-Cxc1cEv3.mjs.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,17 +1,18 @@
|
|
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 { Button, Menu, VisuallyHidden, Flex,
|
10
|
-
import
|
6
|
+
import { Button, Menu, VisuallyHidden, Flex, Typography, Dialog, Modal, 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";
|
11
10
|
import * as yup from "yup";
|
12
11
|
import { ValidationError } from "yup";
|
13
12
|
import pipe from "lodash/fp/pipe";
|
14
13
|
import { intervalToDuration, isPast } from "date-fns";
|
14
|
+
import { styled } from "styled-components";
|
15
|
+
import { stringify } from "qs";
|
15
16
|
import { createSlice, combineReducers } from "@reduxjs/toolkit";
|
16
17
|
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
17
18
|
const v = glob[path];
|
@@ -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
|
}),
|
@@ -287,7 +271,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
287
271
|
*/
|
288
272
|
getAllDocuments: builder.query({
|
289
273
|
query: ({ model, params }) => ({
|
290
|
-
url: `/content-manager/collection-types/${model}`,
|
274
|
+
url: `/content-manager/collection-types/${model}${params ? `?${params}` : ""}`,
|
291
275
|
method: "GET",
|
292
276
|
config: {
|
293
277
|
params
|
@@ -295,6 +279,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
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({
|
@@ -467,20 +470,39 @@ const buildValidParams = (query) => {
|
|
467
470
|
const isBaseQueryError = (error) => {
|
468
471
|
return error.name !== void 0;
|
469
472
|
};
|
470
|
-
const
|
473
|
+
const arrayValidator = (attribute, options) => ({
|
474
|
+
message: translatedErrors.required,
|
475
|
+
test(value) {
|
476
|
+
if (options.status === "draft") {
|
477
|
+
return true;
|
478
|
+
}
|
479
|
+
if (!attribute.required) {
|
480
|
+
return true;
|
481
|
+
}
|
482
|
+
if (!value) {
|
483
|
+
return false;
|
484
|
+
}
|
485
|
+
if (Array.isArray(value) && value.length === 0) {
|
486
|
+
return false;
|
487
|
+
}
|
488
|
+
return true;
|
489
|
+
}
|
490
|
+
});
|
491
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
471
492
|
const createModelSchema = (attributes2) => yup.object().shape(
|
472
493
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
473
494
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
474
495
|
return acc;
|
475
496
|
}
|
476
497
|
const validations = [
|
498
|
+
addNullableValidation,
|
477
499
|
addRequiredValidation,
|
478
500
|
addMinLengthValidation,
|
479
501
|
addMaxLengthValidation,
|
480
502
|
addMinValidation,
|
481
503
|
addMaxValidation,
|
482
504
|
addRegexValidation
|
483
|
-
].map((fn) => fn(attribute));
|
505
|
+
].map((fn) => fn(attribute, options));
|
484
506
|
const transformSchema = pipe(...validations);
|
485
507
|
switch (attribute.type) {
|
486
508
|
case "component": {
|
@@ -490,12 +512,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
490
512
|
...acc,
|
491
513
|
[name]: transformSchema(
|
492
514
|
yup.array().of(createModelSchema(attributes3).nullable(false))
|
493
|
-
)
|
515
|
+
).test(arrayValidator(attribute, options))
|
494
516
|
};
|
495
517
|
} else {
|
496
518
|
return {
|
497
519
|
...acc,
|
498
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
520
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
499
521
|
};
|
500
522
|
}
|
501
523
|
}
|
@@ -517,7 +539,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
517
539
|
}
|
518
540
|
)
|
519
541
|
)
|
520
|
-
)
|
542
|
+
).test(arrayValidator(attribute, options))
|
521
543
|
};
|
522
544
|
case "relation":
|
523
545
|
return {
|
@@ -529,7 +551,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
529
551
|
} else if (Array.isArray(value)) {
|
530
552
|
return yup.array().of(
|
531
553
|
yup.object().shape({
|
532
|
-
id: yup.
|
554
|
+
id: yup.number().required()
|
533
555
|
})
|
534
556
|
);
|
535
557
|
} else if (typeof value === "object") {
|
@@ -581,6 +603,14 @@ const createAttributeSchema = (attribute) => {
|
|
581
603
|
if (!value || typeof value === "string" && value.length === 0) {
|
582
604
|
return true;
|
583
605
|
}
|
606
|
+
if (typeof value === "object") {
|
607
|
+
try {
|
608
|
+
JSON.stringify(value);
|
609
|
+
return true;
|
610
|
+
} catch (err) {
|
611
|
+
return false;
|
612
|
+
}
|
613
|
+
}
|
584
614
|
try {
|
585
615
|
JSON.parse(value);
|
586
616
|
return true;
|
@@ -599,13 +629,7 @@ const createAttributeSchema = (attribute) => {
|
|
599
629
|
return yup.mixed();
|
600
630
|
}
|
601
631
|
};
|
602
|
-
const
|
603
|
-
if (attribute.required && attribute.type !== "relation") {
|
604
|
-
return schema.required({
|
605
|
-
id: translatedErrors.required.id,
|
606
|
-
defaultMessage: "This field is required."
|
607
|
-
});
|
608
|
-
}
|
632
|
+
const nullableSchema = (schema) => {
|
609
633
|
return schema?.nullable ? schema.nullable() : (
|
610
634
|
// In some cases '.nullable' will not be available on the schema.
|
611
635
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -613,7 +637,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
613
637
|
schema
|
614
638
|
);
|
615
639
|
};
|
616
|
-
const
|
640
|
+
const addNullableValidation = () => (schema) => {
|
641
|
+
return nullableSchema(schema);
|
642
|
+
};
|
643
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
644
|
+
if (options.status === "draft" || !attribute.required) {
|
645
|
+
return schema;
|
646
|
+
}
|
647
|
+
if (attribute.required && "required" in schema) {
|
648
|
+
return schema.required(translatedErrors.required);
|
649
|
+
}
|
650
|
+
return schema;
|
651
|
+
};
|
652
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
653
|
+
if (options.status === "draft") {
|
654
|
+
return schema;
|
655
|
+
}
|
617
656
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
618
657
|
return schema.min(attribute.minLength, {
|
619
658
|
...translatedErrors.minLength,
|
@@ -635,10 +674,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
635
674
|
}
|
636
675
|
return schema;
|
637
676
|
};
|
638
|
-
const addMinValidation = (attribute) => (schema) => {
|
639
|
-
if ("
|
677
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
678
|
+
if (options.status === "draft") {
|
679
|
+
return schema;
|
680
|
+
}
|
681
|
+
if ("min" in attribute && "min" in schema) {
|
640
682
|
const min = toInteger(attribute.min);
|
641
|
-
if (
|
683
|
+
if (min) {
|
642
684
|
return schema.min(min, {
|
643
685
|
...translatedErrors.min,
|
644
686
|
values: {
|
@@ -756,19 +798,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
756
798
|
}, {});
|
757
799
|
return componentsByKey;
|
758
800
|
};
|
759
|
-
const
|
801
|
+
const HOOKS = {
|
802
|
+
/**
|
803
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
804
|
+
* @constant
|
805
|
+
* @type {string}
|
806
|
+
*/
|
807
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
808
|
+
/**
|
809
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
810
|
+
* @constant
|
811
|
+
* @type {string}
|
812
|
+
*/
|
813
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
814
|
+
/**
|
815
|
+
* Hook that allows to mutate the CM's edit view layout
|
816
|
+
* @constant
|
817
|
+
* @type {string}
|
818
|
+
*/
|
819
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
820
|
+
/**
|
821
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
822
|
+
* @constant
|
823
|
+
* @type {string}
|
824
|
+
*/
|
825
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
826
|
+
};
|
827
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
828
|
+
endpoints: (builder) => ({
|
829
|
+
getContentTypeConfiguration: builder.query({
|
830
|
+
query: (uid) => ({
|
831
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
832
|
+
method: "GET"
|
833
|
+
}),
|
834
|
+
transformResponse: (response) => response.data,
|
835
|
+
providesTags: (_result, _error, uid) => [
|
836
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
837
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
838
|
+
]
|
839
|
+
}),
|
840
|
+
getAllContentTypeSettings: builder.query({
|
841
|
+
query: () => "/content-manager/content-types-settings",
|
842
|
+
transformResponse: (response) => response.data,
|
843
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
844
|
+
}),
|
845
|
+
updateContentTypeConfiguration: builder.mutation({
|
846
|
+
query: ({ uid, ...body }) => ({
|
847
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
848
|
+
method: "PUT",
|
849
|
+
data: body
|
850
|
+
}),
|
851
|
+
transformResponse: (response) => response.data,
|
852
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
853
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
854
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
855
|
+
// Is this necessary?
|
856
|
+
{ type: "InitialData" }
|
857
|
+
]
|
858
|
+
})
|
859
|
+
})
|
860
|
+
});
|
861
|
+
const {
|
862
|
+
useGetContentTypeConfigurationQuery,
|
863
|
+
useGetAllContentTypeSettingsQuery,
|
864
|
+
useUpdateContentTypeConfigurationMutation
|
865
|
+
} = contentTypesApi;
|
866
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
867
|
+
const { type } = attribute;
|
868
|
+
if (type === "relation") {
|
869
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
870
|
+
}
|
871
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
872
|
+
};
|
873
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
874
|
+
if (!mainFieldName) {
|
875
|
+
return void 0;
|
876
|
+
}
|
877
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
878
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
879
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
880
|
+
);
|
881
|
+
return {
|
882
|
+
name: mainFieldName,
|
883
|
+
type: mainFieldType ?? "string"
|
884
|
+
};
|
885
|
+
};
|
886
|
+
const DEFAULT_SETTINGS = {
|
887
|
+
bulkable: false,
|
888
|
+
filterable: false,
|
889
|
+
searchable: false,
|
890
|
+
pagination: false,
|
891
|
+
defaultSortBy: "",
|
892
|
+
defaultSortOrder: "asc",
|
893
|
+
mainField: "id",
|
894
|
+
pageSize: 10
|
895
|
+
};
|
896
|
+
const useDocumentLayout = (model) => {
|
897
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
898
|
+
const [{ query }] = useQueryParams();
|
899
|
+
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
760
900
|
const { toggleNotification } = useNotification();
|
761
901
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
902
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
762
903
|
const {
|
763
|
-
|
764
|
-
isLoading:
|
765
|
-
|
766
|
-
|
767
|
-
} =
|
768
|
-
|
769
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
770
|
-
});
|
771
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
904
|
+
data,
|
905
|
+
isLoading: isLoadingConfigs,
|
906
|
+
error,
|
907
|
+
isFetching: isFetchingConfigs
|
908
|
+
} = useGetContentTypeConfigurationQuery(model);
|
909
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
772
910
|
React.useEffect(() => {
|
773
911
|
if (error) {
|
774
912
|
toggleNotification({
|
@@ -776,68 +914,322 @@ const useDocument = (args, opts) => {
|
|
776
914
|
message: formatAPIError(error)
|
777
915
|
});
|
778
916
|
}
|
779
|
-
}, [
|
780
|
-
const
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
(document) => {
|
788
|
-
if (!validationSchema) {
|
789
|
-
throw new Error(
|
790
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
791
|
-
);
|
792
|
-
}
|
793
|
-
try {
|
794
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
795
|
-
return null;
|
796
|
-
} catch (error2) {
|
797
|
-
if (error2 instanceof ValidationError) {
|
798
|
-
return getYupValidationErrors(error2);
|
799
|
-
}
|
800
|
-
throw error2;
|
801
|
-
}
|
917
|
+
}, [error, formatAPIError, toggleNotification]);
|
918
|
+
const editLayout = React.useMemo(
|
919
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
920
|
+
layout: [],
|
921
|
+
components: {},
|
922
|
+
metadatas: {},
|
923
|
+
options: {},
|
924
|
+
settings: DEFAULT_SETTINGS
|
802
925
|
},
|
803
|
-
[
|
926
|
+
[data, isLoading, schemas, schema, components]
|
927
|
+
);
|
928
|
+
const listLayout = React.useMemo(() => {
|
929
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
930
|
+
layout: [],
|
931
|
+
metadatas: {},
|
932
|
+
options: {},
|
933
|
+
settings: DEFAULT_SETTINGS
|
934
|
+
};
|
935
|
+
}, [data, isLoading, schemas, schema, components]);
|
936
|
+
const { layout: edit } = React.useMemo(
|
937
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
938
|
+
layout: editLayout,
|
939
|
+
query
|
940
|
+
}),
|
941
|
+
[editLayout, query, runHookWaterfall]
|
804
942
|
);
|
805
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
806
943
|
return {
|
807
|
-
|
808
|
-
document: data?.data,
|
809
|
-
meta: data?.meta,
|
944
|
+
error,
|
810
945
|
isLoading,
|
811
|
-
|
812
|
-
|
946
|
+
edit,
|
947
|
+
list: listLayout
|
813
948
|
};
|
814
949
|
};
|
815
|
-
const
|
816
|
-
const {
|
817
|
-
|
818
|
-
|
819
|
-
|
950
|
+
const useDocLayout = () => {
|
951
|
+
const { model } = useDoc();
|
952
|
+
return useDocumentLayout(model);
|
953
|
+
};
|
954
|
+
const formatEditLayout = (data, {
|
955
|
+
schemas,
|
956
|
+
schema,
|
957
|
+
components
|
958
|
+
}) => {
|
959
|
+
let currentPanelIndex = 0;
|
960
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
961
|
+
data.contentType.layouts.edit,
|
962
|
+
schema?.attributes,
|
963
|
+
data.contentType.metadatas,
|
964
|
+
{ configurations: data.components, schemas: components },
|
965
|
+
schemas
|
966
|
+
).reduce((panels, row) => {
|
967
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
968
|
+
panels.push([row]);
|
969
|
+
currentPanelIndex += 2;
|
970
|
+
} else {
|
971
|
+
if (!panels[currentPanelIndex]) {
|
972
|
+
panels.push([row]);
|
973
|
+
} else {
|
974
|
+
panels[currentPanelIndex].push(row);
|
975
|
+
}
|
976
|
+
}
|
977
|
+
return panels;
|
978
|
+
}, []);
|
979
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
980
|
+
(acc, [uid, configuration]) => {
|
981
|
+
acc[uid] = {
|
982
|
+
layout: convertEditLayoutToFieldLayouts(
|
983
|
+
configuration.layouts.edit,
|
984
|
+
components[uid].attributes,
|
985
|
+
configuration.metadatas,
|
986
|
+
{ configurations: data.components, schemas: components }
|
987
|
+
),
|
988
|
+
settings: {
|
989
|
+
...configuration.settings,
|
990
|
+
icon: components[uid].info.icon,
|
991
|
+
displayName: components[uid].info.displayName
|
992
|
+
}
|
993
|
+
};
|
994
|
+
return acc;
|
995
|
+
},
|
996
|
+
{}
|
997
|
+
);
|
998
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
999
|
+
(acc, [attribute, metadata]) => {
|
1000
|
+
return {
|
1001
|
+
...acc,
|
1002
|
+
[attribute]: metadata.edit
|
1003
|
+
};
|
1004
|
+
},
|
1005
|
+
{}
|
1006
|
+
);
|
1007
|
+
return {
|
1008
|
+
layout: panelledEditAttributes,
|
1009
|
+
components: componentEditAttributes,
|
1010
|
+
metadatas: editMetadatas,
|
1011
|
+
settings: {
|
1012
|
+
...data.contentType.settings,
|
1013
|
+
displayName: schema?.info.displayName
|
1014
|
+
},
|
1015
|
+
options: {
|
1016
|
+
...schema?.options,
|
1017
|
+
...schema?.pluginOptions,
|
1018
|
+
...data.contentType.options
|
1019
|
+
}
|
1020
|
+
};
|
1021
|
+
};
|
1022
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1023
|
+
return rows.map(
|
1024
|
+
(row) => row.map((field) => {
|
1025
|
+
const attribute = attributes[field.name];
|
1026
|
+
if (!attribute) {
|
1027
|
+
return null;
|
1028
|
+
}
|
1029
|
+
const { edit: metadata } = metadatas[field.name];
|
1030
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1031
|
+
return {
|
1032
|
+
attribute,
|
1033
|
+
disabled: !metadata.editable,
|
1034
|
+
hint: metadata.description,
|
1035
|
+
label: metadata.label ?? "",
|
1036
|
+
name: field.name,
|
1037
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1038
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1039
|
+
schemas,
|
1040
|
+
components: components?.schemas ?? {}
|
1041
|
+
}),
|
1042
|
+
placeholder: metadata.placeholder ?? "",
|
1043
|
+
required: attribute.required ?? false,
|
1044
|
+
size: field.size,
|
1045
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1046
|
+
visible: metadata.visible ?? true,
|
1047
|
+
type: attribute.type
|
1048
|
+
};
|
1049
|
+
}).filter((field) => field !== null)
|
1050
|
+
);
|
1051
|
+
};
|
1052
|
+
const formatListLayout = (data, {
|
1053
|
+
schemas,
|
1054
|
+
schema,
|
1055
|
+
components
|
1056
|
+
}) => {
|
1057
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1058
|
+
(acc, [attribute, metadata]) => {
|
1059
|
+
return {
|
1060
|
+
...acc,
|
1061
|
+
[attribute]: metadata.list
|
1062
|
+
};
|
1063
|
+
},
|
1064
|
+
{}
|
1065
|
+
);
|
1066
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1067
|
+
data.contentType.layouts.list,
|
1068
|
+
schema?.attributes,
|
1069
|
+
listMetadatas,
|
1070
|
+
{ configurations: data.components, schemas: components },
|
1071
|
+
schemas
|
1072
|
+
);
|
1073
|
+
return {
|
1074
|
+
layout: listAttributes,
|
1075
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1076
|
+
metadatas: listMetadatas,
|
1077
|
+
options: {
|
1078
|
+
...schema?.options,
|
1079
|
+
...schema?.pluginOptions,
|
1080
|
+
...data.contentType.options
|
1081
|
+
}
|
1082
|
+
};
|
1083
|
+
};
|
1084
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1085
|
+
return columns.map((name) => {
|
1086
|
+
const attribute = attributes[name];
|
1087
|
+
if (!attribute) {
|
1088
|
+
return null;
|
1089
|
+
}
|
1090
|
+
const metadata = metadatas[name];
|
1091
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1092
|
+
return {
|
1093
|
+
attribute,
|
1094
|
+
label: metadata.label ?? "",
|
1095
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1096
|
+
schemas,
|
1097
|
+
components: components?.schemas ?? {}
|
1098
|
+
}),
|
1099
|
+
name,
|
1100
|
+
searchable: metadata.searchable ?? true,
|
1101
|
+
sortable: metadata.sortable ?? true
|
1102
|
+
};
|
1103
|
+
}).filter((field) => field !== null);
|
1104
|
+
};
|
1105
|
+
const useDocument = (args, opts) => {
|
1106
|
+
const { toggleNotification } = useNotification();
|
1107
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1108
|
+
const {
|
1109
|
+
currentData: data,
|
1110
|
+
isLoading: isLoadingDocument,
|
1111
|
+
isFetching: isFetchingDocument,
|
1112
|
+
error
|
1113
|
+
} = useGetDocumentQuery(args, {
|
1114
|
+
...opts,
|
1115
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1116
|
+
});
|
1117
|
+
const {
|
1118
|
+
components,
|
1119
|
+
schema,
|
1120
|
+
schemas,
|
1121
|
+
isLoading: isLoadingSchema
|
1122
|
+
} = useContentTypeSchema(args.model);
|
1123
|
+
React.useEffect(() => {
|
1124
|
+
if (error) {
|
1125
|
+
toggleNotification({
|
1126
|
+
type: "danger",
|
1127
|
+
message: formatAPIError(error)
|
1128
|
+
});
|
1129
|
+
}
|
1130
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1131
|
+
const validationSchema = React.useMemo(() => {
|
1132
|
+
if (!schema) {
|
1133
|
+
return null;
|
1134
|
+
}
|
1135
|
+
return createYupSchema(schema.attributes, components);
|
1136
|
+
}, [schema, components]);
|
1137
|
+
const validate = React.useCallback(
|
1138
|
+
(document) => {
|
1139
|
+
if (!validationSchema) {
|
1140
|
+
throw new Error(
|
1141
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1142
|
+
);
|
1143
|
+
}
|
1144
|
+
try {
|
1145
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1146
|
+
return null;
|
1147
|
+
} catch (error2) {
|
1148
|
+
if (error2 instanceof ValidationError) {
|
1149
|
+
return getYupValidationErrors(error2);
|
1150
|
+
}
|
1151
|
+
throw error2;
|
1152
|
+
}
|
1153
|
+
},
|
1154
|
+
[validationSchema]
|
1155
|
+
);
|
1156
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1157
|
+
const hasError = !!error;
|
1158
|
+
return {
|
1159
|
+
components,
|
1160
|
+
document: data?.data,
|
1161
|
+
meta: data?.meta,
|
1162
|
+
isLoading,
|
1163
|
+
hasError,
|
1164
|
+
schema,
|
1165
|
+
schemas,
|
1166
|
+
validate
|
1167
|
+
};
|
1168
|
+
};
|
1169
|
+
const useDoc = () => {
|
1170
|
+
const { id, slug, collectionType, origin } = useParams();
|
1171
|
+
const [{ query }] = useQueryParams();
|
1172
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1173
|
+
if (!collectionType) {
|
820
1174
|
throw new Error("Could not find collectionType in url params");
|
821
1175
|
}
|
822
1176
|
if (!slug) {
|
823
1177
|
throw new Error("Could not find model in url params");
|
824
1178
|
}
|
1179
|
+
const document = useDocument(
|
1180
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1181
|
+
{
|
1182
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1183
|
+
}
|
1184
|
+
);
|
1185
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
825
1186
|
return {
|
826
1187
|
collectionType,
|
827
1188
|
model: slug,
|
828
|
-
id:
|
829
|
-
...
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
1189
|
+
id: returnId,
|
1190
|
+
...document
|
1191
|
+
};
|
1192
|
+
};
|
1193
|
+
const useContentManagerContext = () => {
|
1194
|
+
const {
|
1195
|
+
collectionType,
|
1196
|
+
model,
|
1197
|
+
id,
|
1198
|
+
components,
|
1199
|
+
isLoading: isLoadingDoc,
|
1200
|
+
schema,
|
1201
|
+
schemas
|
1202
|
+
} = useDoc();
|
1203
|
+
const layout = useDocumentLayout(model);
|
1204
|
+
const form = useForm("useContentManagerContext", (state) => state);
|
1205
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1206
|
+
const slug = model;
|
1207
|
+
const isCreatingEntry = id === "create";
|
1208
|
+
useContentTypeSchema();
|
1209
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1210
|
+
const error = layout.error;
|
1211
|
+
return {
|
1212
|
+
error,
|
1213
|
+
isLoading,
|
1214
|
+
// Base metadata
|
1215
|
+
model,
|
1216
|
+
collectionType,
|
1217
|
+
id,
|
1218
|
+
slug,
|
1219
|
+
isCreatingEntry,
|
1220
|
+
isSingleType,
|
1221
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1222
|
+
// All schema infos
|
1223
|
+
components,
|
1224
|
+
contentType: schema,
|
1225
|
+
contentTypes: schemas,
|
1226
|
+
// Form state
|
1227
|
+
form,
|
1228
|
+
// layout infos
|
1229
|
+
layout
|
835
1230
|
};
|
836
1231
|
};
|
837
1232
|
const prefixPluginTranslations = (trad, pluginId) => {
|
838
|
-
if (!pluginId) {
|
839
|
-
throw new TypeError("pluginId can't be empty");
|
840
|
-
}
|
841
1233
|
return Object.keys(trad).reduce((acc, current) => {
|
842
1234
|
acc[`${pluginId}.${current}`] = trad[current];
|
843
1235
|
return acc;
|
@@ -853,6 +1245,8 @@ const useDocumentActions = () => {
|
|
853
1245
|
const { formatMessage } = useIntl();
|
854
1246
|
const { trackUsage } = useTracking();
|
855
1247
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1248
|
+
const navigate = useNavigate();
|
1249
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
856
1250
|
const [deleteDocument] = useDeleteDocumentMutation();
|
857
1251
|
const _delete = React.useCallback(
|
858
1252
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1167,6 +1561,7 @@ const useDocumentActions = () => {
|
|
1167
1561
|
defaultMessage: "Saved document"
|
1168
1562
|
})
|
1169
1563
|
});
|
1564
|
+
setCurrentStep("contentManager.success");
|
1170
1565
|
return res.data;
|
1171
1566
|
} catch (err) {
|
1172
1567
|
toggleNotification({
|
@@ -1188,7 +1583,6 @@ const useDocumentActions = () => {
|
|
1188
1583
|
sourceId
|
1189
1584
|
});
|
1190
1585
|
if ("error" in res) {
|
1191
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1192
1586
|
return { error: res.error };
|
1193
1587
|
}
|
1194
1588
|
toggleNotification({
|
@@ -1207,7 +1601,7 @@ const useDocumentActions = () => {
|
|
1207
1601
|
throw err;
|
1208
1602
|
}
|
1209
1603
|
},
|
1210
|
-
[autoCloneDocument,
|
1604
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1211
1605
|
);
|
1212
1606
|
const [cloneDocument] = useCloneDocumentMutation();
|
1213
1607
|
const clone = React.useCallback(
|
@@ -1233,6 +1627,7 @@ const useDocumentActions = () => {
|
|
1233
1627
|
defaultMessage: "Cloned document"
|
1234
1628
|
})
|
1235
1629
|
});
|
1630
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1236
1631
|
return res.data;
|
1237
1632
|
} catch (err) {
|
1238
1633
|
toggleNotification({
|
@@ -1243,7 +1638,7 @@ const useDocumentActions = () => {
|
|
1243
1638
|
throw err;
|
1244
1639
|
}
|
1245
1640
|
},
|
1246
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1641
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1247
1642
|
);
|
1248
1643
|
const [getDoc] = useLazyGetDocumentQuery();
|
1249
1644
|
const getDocument = React.useCallback(
|
@@ -1269,7 +1664,7 @@ const useDocumentActions = () => {
|
|
1269
1664
|
};
|
1270
1665
|
};
|
1271
1666
|
const ProtectedHistoryPage = lazy(
|
1272
|
-
() => import("./History-
|
1667
|
+
() => import("./History-C72HQ0-i.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1273
1668
|
);
|
1274
1669
|
const routes$1 = [
|
1275
1670
|
{
|
@@ -1282,31 +1677,31 @@ const routes$1 = [
|
|
1282
1677
|
}
|
1283
1678
|
];
|
1284
1679
|
const ProtectedEditViewPage = lazy(
|
1285
|
-
() => import("./EditViewPage-
|
1680
|
+
() => import("./EditViewPage-zKmMBER4.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1286
1681
|
);
|
1287
1682
|
const ProtectedListViewPage = lazy(
|
1288
|
-
() => import("./ListViewPage-
|
1683
|
+
() => import("./ListViewPage-Dfue5wQ2.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1289
1684
|
);
|
1290
1685
|
const ProtectedListConfiguration = lazy(
|
1291
|
-
() => import("./ListConfigurationPage-
|
1686
|
+
() => import("./ListConfigurationPage-BalSo5dp.mjs").then((mod) => ({
|
1292
1687
|
default: mod.ProtectedListConfiguration
|
1293
1688
|
}))
|
1294
1689
|
);
|
1295
1690
|
const ProtectedEditConfigurationPage = lazy(
|
1296
|
-
() => import("./EditConfigurationPage-
|
1691
|
+
() => import("./EditConfigurationPage-D7HkxcAN.mjs").then((mod) => ({
|
1297
1692
|
default: mod.ProtectedEditConfigurationPage
|
1298
1693
|
}))
|
1299
1694
|
);
|
1300
1695
|
const ProtectedComponentConfigurationPage = lazy(
|
1301
|
-
() => import("./ComponentConfigurationPage-
|
1696
|
+
() => import("./ComponentConfigurationPage-BUOQFZ08.mjs").then((mod) => ({
|
1302
1697
|
default: mod.ProtectedComponentConfigurationPage
|
1303
1698
|
}))
|
1304
1699
|
);
|
1305
1700
|
const NoPermissions = lazy(
|
1306
|
-
() => import("./NoPermissionsPage-
|
1701
|
+
() => import("./NoPermissionsPage-BpAoEQy_.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1307
1702
|
);
|
1308
1703
|
const NoContentType = lazy(
|
1309
|
-
() => import("./NoContentTypePage-
|
1704
|
+
() => import("./NoContentTypePage-BLC8M9U0.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1310
1705
|
);
|
1311
1706
|
const CollectionTypePages = () => {
|
1312
1707
|
const { collectionType } = useParams();
|
@@ -1420,12 +1815,14 @@ const DocumentActionButton = (action) => {
|
|
1420
1815
|
/* @__PURE__ */ jsx(
|
1421
1816
|
Button,
|
1422
1817
|
{
|
1423
|
-
flex:
|
1818
|
+
flex: "auto",
|
1424
1819
|
startIcon: action.icon,
|
1425
1820
|
disabled: action.disabled,
|
1426
1821
|
onClick: handleClick(action),
|
1427
1822
|
justifyContent: "center",
|
1428
1823
|
variant: action.variant || "default",
|
1824
|
+
paddingTop: "7px",
|
1825
|
+
paddingBottom: "7px",
|
1429
1826
|
children: action.label
|
1430
1827
|
}
|
1431
1828
|
),
|
@@ -1433,7 +1830,7 @@ const DocumentActionButton = (action) => {
|
|
1433
1830
|
DocumentActionConfirmDialog,
|
1434
1831
|
{
|
1435
1832
|
...action.dialog,
|
1436
|
-
variant: action.variant,
|
1833
|
+
variant: action.dialog?.variant ?? action.variant,
|
1437
1834
|
isOpen: dialogId === action.id,
|
1438
1835
|
onClose: handleClose
|
1439
1836
|
}
|
@@ -1490,9 +1887,9 @@ const DocumentActionsMenu = ({
|
|
1490
1887
|
disabled: isDisabled,
|
1491
1888
|
size: "S",
|
1492
1889
|
endIcon: null,
|
1493
|
-
paddingTop: "
|
1494
|
-
paddingLeft: "
|
1495
|
-
paddingRight: "
|
1890
|
+
paddingTop: "4px",
|
1891
|
+
paddingLeft: "7px",
|
1892
|
+
paddingRight: "7px",
|
1496
1893
|
variant,
|
1497
1894
|
children: [
|
1498
1895
|
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
@@ -1503,7 +1900,7 @@ const DocumentActionsMenu = ({
|
|
1503
1900
|
]
|
1504
1901
|
}
|
1505
1902
|
),
|
1506
|
-
/* @__PURE__ */ jsxs(Menu.Content, {
|
1903
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1507
1904
|
actions2.map((action) => {
|
1508
1905
|
return /* @__PURE__ */ jsx(
|
1509
1906
|
Menu.Item,
|
@@ -1512,10 +1909,25 @@ const DocumentActionsMenu = ({
|
|
1512
1909
|
onSelect: handleClick(action),
|
1513
1910
|
display: "block",
|
1514
1911
|
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
|
1515
|
-
/* @__PURE__ */ jsxs(
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1912
|
+
/* @__PURE__ */ jsxs(
|
1913
|
+
Flex,
|
1914
|
+
{
|
1915
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1916
|
+
gap: 2,
|
1917
|
+
tag: "span",
|
1918
|
+
children: [
|
1919
|
+
/* @__PURE__ */ jsx(
|
1920
|
+
Flex,
|
1921
|
+
{
|
1922
|
+
tag: "span",
|
1923
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1924
|
+
children: action.icon
|
1925
|
+
}
|
1926
|
+
),
|
1927
|
+
action.label
|
1928
|
+
]
|
1929
|
+
}
|
1930
|
+
),
|
1519
1931
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
|
1520
1932
|
Flex,
|
1521
1933
|
{
|
@@ -1612,11 +2024,11 @@ const DocumentActionConfirmDialog = ({
|
|
1612
2024
|
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1613
2025
|
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1614
2026
|
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1615
|
-
/* @__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({
|
1616
2028
|
id: "app.components.Button.cancel",
|
1617
2029
|
defaultMessage: "Cancel"
|
1618
2030
|
}) }) }),
|
1619
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2031
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1620
2032
|
id: "app.components.Button.confirm",
|
1621
2033
|
defaultMessage: "Confirm"
|
1622
2034
|
}) })
|
@@ -1639,10 +2051,22 @@ const DocumentActionModal = ({
|
|
1639
2051
|
};
|
1640
2052
|
return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
1641
2053
|
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
|
1642
|
-
|
1643
|
-
|
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
|
1644
2056
|
] }) });
|
1645
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
|
+
};
|
1646
2070
|
const PublishAction$1 = ({
|
1647
2071
|
activeTab,
|
1648
2072
|
documentId,
|
@@ -1655,13 +2079,17 @@ const PublishAction$1 = ({
|
|
1655
2079
|
const navigate = useNavigate();
|
1656
2080
|
const { toggleNotification } = useNotification();
|
1657
2081
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2082
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
1658
2083
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
1659
2084
|
const { formatMessage } = useIntl();
|
1660
|
-
const { canPublish
|
1661
|
-
"PublishAction",
|
1662
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1663
|
-
);
|
2085
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1664
2086
|
const { publish } = useDocumentActions();
|
2087
|
+
const [
|
2088
|
+
countDraftRelations,
|
2089
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2090
|
+
] = useLazyGetDraftRelationCountQuery();
|
2091
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
2092
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1665
2093
|
const [{ query, rawQuery }] = useQueryParams();
|
1666
2094
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1667
2095
|
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1670,62 +2098,144 @@ const PublishAction$1 = ({
|
|
1670
2098
|
const validate = useForm("PublishAction", (state) => state.validate);
|
1671
2099
|
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1672
2100
|
const formValues = useForm("PublishAction", ({ values }) => values);
|
1673
|
-
|
1674
|
-
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
2101
|
+
React.useEffect(() => {
|
2102
|
+
if (isErrorDraftRelations) {
|
2103
|
+
toggleNotification({
|
2104
|
+
type: "danger",
|
2105
|
+
message: formatMessage({
|
2106
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2107
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2108
|
+
})
|
2109
|
+
});
|
2110
|
+
}
|
2111
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2112
|
+
React.useEffect(() => {
|
2113
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2114
|
+
const extractDraftRelations = (data) => {
|
2115
|
+
const relations = data.connect || [];
|
2116
|
+
relations.forEach((relation) => {
|
2117
|
+
if (relation.status === "draft") {
|
2118
|
+
localDraftRelations.add(relation.id);
|
2119
|
+
}
|
2120
|
+
});
|
2121
|
+
};
|
2122
|
+
const traverseAndExtract = (data) => {
|
2123
|
+
Object.entries(data).forEach(([key, value]) => {
|
2124
|
+
if (key === "connect" && Array.isArray(value)) {
|
2125
|
+
extractDraftRelations({ connect: value });
|
2126
|
+
} else if (typeof value === "object" && value !== null) {
|
2127
|
+
traverseAndExtract(value);
|
2128
|
+
}
|
2129
|
+
});
|
2130
|
+
};
|
2131
|
+
if (!documentId || modified) {
|
2132
|
+
traverseAndExtract(formValues);
|
2133
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2134
|
+
}
|
2135
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2136
|
+
React.useEffect(() => {
|
2137
|
+
if (!document || !document.documentId || isListView) {
|
2138
|
+
return;
|
2139
|
+
}
|
2140
|
+
const fetchDraftRelationsCount = async () => {
|
2141
|
+
const { data, error } = await countDraftRelations({
|
2142
|
+
collectionType,
|
2143
|
+
model,
|
2144
|
+
documentId,
|
2145
|
+
params
|
2146
|
+
});
|
2147
|
+
if (error) {
|
2148
|
+
throw error;
|
2149
|
+
}
|
2150
|
+
if (data) {
|
2151
|
+
setServerCountOfDraftRelations(data.data);
|
2152
|
+
}
|
2153
|
+
};
|
2154
|
+
fetchDraftRelationsCount();
|
2155
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2156
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
2157
|
+
if (!schema?.options?.draftAndPublish) {
|
2158
|
+
return null;
|
2159
|
+
}
|
2160
|
+
const performPublish = async () => {
|
2161
|
+
setSubmitting(true);
|
2162
|
+
try {
|
2163
|
+
const { errors } = await validate(true, {
|
2164
|
+
status: "published"
|
2165
|
+
});
|
2166
|
+
if (errors) {
|
2167
|
+
toggleNotification({
|
2168
|
+
type: "danger",
|
2169
|
+
message: formatMessage({
|
2170
|
+
id: "content-manager.validation.error",
|
2171
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2172
|
+
})
|
2173
|
+
});
|
2174
|
+
return;
|
2175
|
+
}
|
2176
|
+
const res = await publish(
|
2177
|
+
{
|
2178
|
+
collectionType,
|
2179
|
+
model,
|
2180
|
+
documentId,
|
2181
|
+
params
|
2182
|
+
},
|
2183
|
+
transformData(formValues)
|
2184
|
+
);
|
2185
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2186
|
+
navigate({
|
2187
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2188
|
+
search: rawQuery
|
2189
|
+
});
|
2190
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2191
|
+
setErrors(formatValidationErrors(res.error));
|
2192
|
+
}
|
2193
|
+
} finally {
|
2194
|
+
setSubmitting(false);
|
2195
|
+
}
|
2196
|
+
};
|
2197
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2198
|
+
const enableDraftRelationsCount = false;
|
2199
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
2200
|
+
return {
|
2201
|
+
/**
|
2202
|
+
* Disabled when:
|
2203
|
+
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
1681
2204
|
* - the form is submitting
|
1682
2205
|
* - the active tab is the published tab
|
1683
2206
|
* - the document is already published & not modified
|
1684
2207
|
* - the document is being created & not modified
|
1685
2208
|
* - the user doesn't have the permission to publish
|
1686
|
-
* - the user doesn't have the permission to create a new document
|
1687
|
-
* - the user doesn't have the permission to update the document
|
1688
2209
|
*/
|
1689
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2210
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1690
2211
|
label: formatMessage({
|
1691
2212
|
id: "app.utils.publish",
|
1692
2213
|
defaultMessage: "Publish"
|
1693
2214
|
}),
|
1694
2215
|
onClick: async () => {
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
documentId,
|
1713
|
-
params
|
1714
|
-
},
|
1715
|
-
formValues
|
1716
|
-
);
|
1717
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1718
|
-
navigate({
|
1719
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1720
|
-
search: rawQuery
|
1721
|
-
});
|
1722
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1723
|
-
setErrors(formatValidationErrors(res.error));
|
2216
|
+
await performPublish();
|
2217
|
+
},
|
2218
|
+
dialog: hasDraftRelations ? {
|
2219
|
+
type: "dialog",
|
2220
|
+
variant: "danger",
|
2221
|
+
footer: null,
|
2222
|
+
title: formatMessage({
|
2223
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2224
|
+
defaultMessage: "Confirmation"
|
2225
|
+
}),
|
2226
|
+
content: formatMessage(
|
2227
|
+
{
|
2228
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2229
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2230
|
+
},
|
2231
|
+
{
|
2232
|
+
count: totalDraftRelations
|
1724
2233
|
}
|
1725
|
-
|
1726
|
-
|
2234
|
+
),
|
2235
|
+
onConfirm: async () => {
|
2236
|
+
await performPublish();
|
1727
2237
|
}
|
1728
|
-
}
|
2238
|
+
} : void 0
|
1729
2239
|
};
|
1730
2240
|
};
|
1731
2241
|
PublishAction$1.type = "publish";
|
@@ -1741,10 +2251,6 @@ const UpdateAction = ({
|
|
1741
2251
|
const cloneMatch = useMatch(CLONE_PATH);
|
1742
2252
|
const isCloning = cloneMatch !== null;
|
1743
2253
|
const { formatMessage } = useIntl();
|
1744
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1745
|
-
canCreate: canCreate2,
|
1746
|
-
canUpdate: canUpdate2
|
1747
|
-
}));
|
1748
2254
|
const { create, update, clone } = useDocumentActions();
|
1749
2255
|
const [{ query, rawQuery }] = useQueryParams();
|
1750
2256
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
@@ -1761,10 +2267,8 @@ const UpdateAction = ({
|
|
1761
2267
|
* - the form is submitting
|
1762
2268
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1763
2269
|
* - the active tab is the published tab
|
1764
|
-
* - the user doesn't have the permission to create a new document
|
1765
|
-
* - the user doesn't have the permission to update the document
|
1766
2270
|
*/
|
1767
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2271
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1768
2272
|
label: formatMessage({
|
1769
2273
|
id: "content-manager.containers.Edit.save",
|
1770
2274
|
defaultMessage: "Save"
|
@@ -1772,7 +2276,9 @@ const UpdateAction = ({
|
|
1772
2276
|
onClick: async () => {
|
1773
2277
|
setSubmitting(true);
|
1774
2278
|
try {
|
1775
|
-
const { errors } = await validate(
|
2279
|
+
const { errors } = await validate(true, {
|
2280
|
+
status: "draft"
|
2281
|
+
});
|
1776
2282
|
if (errors) {
|
1777
2283
|
toggleNotification({
|
1778
2284
|
type: "danger",
|
@@ -1790,13 +2296,16 @@ const UpdateAction = ({
|
|
1790
2296
|
documentId: cloneMatch.params.origin,
|
1791
2297
|
params
|
1792
2298
|
},
|
1793
|
-
document
|
2299
|
+
transformData(document)
|
1794
2300
|
);
|
1795
2301
|
if ("data" in res) {
|
1796
|
-
navigate(
|
1797
|
-
|
1798
|
-
|
1799
|
-
|
2302
|
+
navigate(
|
2303
|
+
{
|
2304
|
+
pathname: `../${res.data.documentId}`,
|
2305
|
+
search: rawQuery
|
2306
|
+
},
|
2307
|
+
{ relative: "path" }
|
2308
|
+
);
|
1800
2309
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1801
2310
|
setErrors(formatValidationErrors(res.error));
|
1802
2311
|
}
|
@@ -1808,7 +2317,7 @@ const UpdateAction = ({
|
|
1808
2317
|
documentId,
|
1809
2318
|
params
|
1810
2319
|
},
|
1811
|
-
document
|
2320
|
+
transformData(document)
|
1812
2321
|
);
|
1813
2322
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1814
2323
|
setErrors(formatValidationErrors(res.error));
|
@@ -1821,15 +2330,15 @@ const UpdateAction = ({
|
|
1821
2330
|
model,
|
1822
2331
|
params
|
1823
2332
|
},
|
1824
|
-
document
|
2333
|
+
transformData(document)
|
1825
2334
|
);
|
1826
2335
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1827
2336
|
navigate(
|
1828
2337
|
{
|
1829
|
-
pathname: `../${
|
2338
|
+
pathname: `../${res.data.documentId}`,
|
1830
2339
|
search: rawQuery
|
1831
2340
|
},
|
1832
|
-
{ replace: true }
|
2341
|
+
{ replace: true, relative: "path" }
|
1833
2342
|
);
|
1834
2343
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1835
2344
|
setErrors(formatValidationErrors(res.error));
|
@@ -1874,7 +2383,7 @@ const UnpublishAction$1 = ({
|
|
1874
2383
|
id: "app.utils.unpublish",
|
1875
2384
|
defaultMessage: "Unpublish"
|
1876
2385
|
}),
|
1877
|
-
icon: /* @__PURE__ */ jsx(
|
2386
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1878
2387
|
onClick: async () => {
|
1879
2388
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1880
2389
|
if (!documentId) {
|
@@ -1986,7 +2495,7 @@ const DiscardAction = ({
|
|
1986
2495
|
id: "content-manager.actions.discard.label",
|
1987
2496
|
defaultMessage: "Discard changes"
|
1988
2497
|
}),
|
1989
|
-
icon: /* @__PURE__ */ jsx(
|
2498
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1990
2499
|
position: ["panel", "table-row"],
|
1991
2500
|
variant: "danger",
|
1992
2501
|
dialog: {
|
@@ -2014,11 +2523,6 @@ const DiscardAction = ({
|
|
2014
2523
|
};
|
2015
2524
|
};
|
2016
2525
|
DiscardAction.type = "discard";
|
2017
|
-
const StyledCrossCircle = styled(CrossCircle)`
|
2018
|
-
path {
|
2019
|
-
fill: currentColor;
|
2020
|
-
}
|
2021
|
-
`;
|
2022
2526
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2023
2527
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2024
2528
|
const RelativeTime = React.forwardRef(
|
@@ -2066,7 +2570,7 @@ const getDisplayName = ({
|
|
2066
2570
|
};
|
2067
2571
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2068
2572
|
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2069
|
-
const statusVariant = status === "draft" ? "
|
2573
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2070
2574
|
return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
|
2071
2575
|
};
|
2072
2576
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
@@ -2076,23 +2580,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2076
2580
|
id: "content-manager.containers.edit.title.new",
|
2077
2581
|
defaultMessage: "Create an entry"
|
2078
2582
|
}) : documentTitle;
|
2079
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2583
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2080
2584
|
/* @__PURE__ */ jsx(BackButton, {}),
|
2081
|
-
/* @__PURE__ */ jsxs(
|
2082
|
-
|
2083
|
-
{
|
2084
|
-
|
2085
|
-
|
2086
|
-
paddingTop: 1,
|
2087
|
-
gap: "80px",
|
2088
|
-
alignItems: "flex-start",
|
2089
|
-
children: [
|
2090
|
-
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2091
|
-
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2092
|
-
]
|
2093
|
-
}
|
2094
|
-
),
|
2095
|
-
status ? /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2585
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2586
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2587
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2588
|
+
] }),
|
2589
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2096
2590
|
] });
|
2097
2591
|
};
|
2098
2592
|
const HeaderToolbar = () => {
|
@@ -2175,12 +2669,12 @@ const Information = ({ activeTab }) => {
|
|
2175
2669
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2176
2670
|
label: formatMessage({
|
2177
2671
|
id: "content-manager.containers.edit.information.last-published.label",
|
2178
|
-
defaultMessage: "
|
2672
|
+
defaultMessage: "Published"
|
2179
2673
|
}),
|
2180
2674
|
value: formatMessage(
|
2181
2675
|
{
|
2182
2676
|
id: "content-manager.containers.edit.information.last-published.value",
|
2183
|
-
defaultMessage: `
|
2677
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2184
2678
|
},
|
2185
2679
|
{
|
2186
2680
|
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2193,12 +2687,12 @@ const Information = ({ activeTab }) => {
|
|
2193
2687
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2194
2688
|
label: formatMessage({
|
2195
2689
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2196
|
-
defaultMessage: "
|
2690
|
+
defaultMessage: "Updated"
|
2197
2691
|
}),
|
2198
2692
|
value: formatMessage(
|
2199
2693
|
{
|
2200
2694
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2201
|
-
defaultMessage: `
|
2695
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2202
2696
|
},
|
2203
2697
|
{
|
2204
2698
|
time: /* @__PURE__ */ jsx(
|
@@ -2216,12 +2710,12 @@ const Information = ({ activeTab }) => {
|
|
2216
2710
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2217
2711
|
label: formatMessage({
|
2218
2712
|
id: "content-manager.containers.edit.information.document.label",
|
2219
|
-
defaultMessage: "
|
2713
|
+
defaultMessage: "Created"
|
2220
2714
|
}),
|
2221
2715
|
value: formatMessage(
|
2222
2716
|
{
|
2223
2717
|
id: "content-manager.containers.edit.information.document.value",
|
2224
|
-
defaultMessage: `
|
2718
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2225
2719
|
},
|
2226
2720
|
{
|
2227
2721
|
time: /* @__PURE__ */ jsx(
|
@@ -2259,25 +2753,77 @@ const Information = ({ activeTab }) => {
|
|
2259
2753
|
);
|
2260
2754
|
};
|
2261
2755
|
const HeaderActions = ({ actions: actions2 }) => {
|
2262
|
-
|
2263
|
-
|
2756
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2757
|
+
const handleClick = (action) => async (e) => {
|
2758
|
+
if (!("options" in action)) {
|
2759
|
+
const { onClick = () => false, dialog, id } = action;
|
2760
|
+
const muteDialog = await onClick(e);
|
2761
|
+
if (dialog && !muteDialog) {
|
2762
|
+
e.preventDefault();
|
2763
|
+
setDialogId(id);
|
2764
|
+
}
|
2765
|
+
}
|
2766
|
+
};
|
2767
|
+
const handleClose = () => {
|
2768
|
+
setDialogId(null);
|
2769
|
+
};
|
2770
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2771
|
+
if (action.options) {
|
2264
2772
|
return /* @__PURE__ */ jsx(
|
2265
2773
|
SingleSelect,
|
2266
2774
|
{
|
2267
2775
|
size: "S",
|
2268
|
-
disabled: action.disabled,
|
2269
|
-
"aria-label": action.label,
|
2270
2776
|
onChange: action.onSelect,
|
2271
|
-
|
2777
|
+
"aria-label": action.label,
|
2778
|
+
...action,
|
2272
2779
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2273
2780
|
},
|
2274
2781
|
action.id
|
2275
2782
|
);
|
2276
2783
|
} else {
|
2277
|
-
|
2784
|
+
if (action.type === "icon") {
|
2785
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2786
|
+
/* @__PURE__ */ jsx(
|
2787
|
+
IconButton,
|
2788
|
+
{
|
2789
|
+
disabled: action.disabled,
|
2790
|
+
label: action.label,
|
2791
|
+
size: "S",
|
2792
|
+
onClick: handleClick(action),
|
2793
|
+
children: action.icon
|
2794
|
+
}
|
2795
|
+
),
|
2796
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2797
|
+
HeaderActionDialog,
|
2798
|
+
{
|
2799
|
+
...action.dialog,
|
2800
|
+
isOpen: dialogId === action.id,
|
2801
|
+
onClose: handleClose
|
2802
|
+
}
|
2803
|
+
) : null
|
2804
|
+
] }, action.id);
|
2805
|
+
}
|
2278
2806
|
}
|
2279
2807
|
}) });
|
2280
2808
|
};
|
2809
|
+
const HeaderActionDialog = ({
|
2810
|
+
onClose,
|
2811
|
+
onCancel,
|
2812
|
+
title,
|
2813
|
+
content: Content,
|
2814
|
+
isOpen
|
2815
|
+
}) => {
|
2816
|
+
const handleClose = async () => {
|
2817
|
+
if (onCancel) {
|
2818
|
+
await onCancel();
|
2819
|
+
}
|
2820
|
+
onClose();
|
2821
|
+
};
|
2822
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2823
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2824
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2825
|
+
] }) });
|
2826
|
+
};
|
2281
2827
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2282
2828
|
const navigate = useNavigate();
|
2283
2829
|
const { formatMessage } = useIntl();
|
@@ -2318,12 +2864,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2318
2864
|
const { delete: deleteAction } = useDocumentActions();
|
2319
2865
|
const { toggleNotification } = useNotification();
|
2320
2866
|
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2867
|
+
const isLocalized = document?.locale != null;
|
2321
2868
|
return {
|
2322
2869
|
disabled: !canDelete || !document,
|
2323
|
-
label: formatMessage(
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2870
|
+
label: formatMessage(
|
2871
|
+
{
|
2872
|
+
id: "content-manager.actions.delete.label",
|
2873
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2874
|
+
},
|
2875
|
+
{ isLocalized }
|
2876
|
+
),
|
2327
2877
|
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2328
2878
|
dialog: {
|
2329
2879
|
type: "dialog",
|
@@ -2358,424 +2908,122 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2358
2908
|
}
|
2359
2909
|
const res = await deleteAction({
|
2360
2910
|
documentId,
|
2361
|
-
model,
|
2362
|
-
collectionType,
|
2363
|
-
params: {
|
2364
|
-
locale: "*"
|
2365
|
-
}
|
2366
|
-
});
|
2367
|
-
if (!("error" in res)) {
|
2368
|
-
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2369
|
-
}
|
2370
|
-
} finally {
|
2371
|
-
if (!listViewPathMatch) {
|
2372
|
-
setSubmitting(false);
|
2373
|
-
}
|
2374
|
-
}
|
2375
|
-
}
|
2376
|
-
},
|
2377
|
-
variant: "danger",
|
2378
|
-
position: ["header", "table-row"]
|
2379
|
-
};
|
2380
|
-
};
|
2381
|
-
DeleteAction$1.type = "delete";
|
2382
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2383
|
-
const Panels = () => {
|
2384
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2385
|
-
const [
|
2386
|
-
{
|
2387
|
-
query: { status }
|
2388
|
-
}
|
2389
|
-
] = useQueryParams({
|
2390
|
-
status: "draft"
|
2391
|
-
});
|
2392
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2393
|
-
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2394
|
-
const props = {
|
2395
|
-
activeTab: status,
|
2396
|
-
model,
|
2397
|
-
documentId: id,
|
2398
|
-
document: isCloning ? void 0 : document,
|
2399
|
-
meta: isCloning ? void 0 : meta,
|
2400
|
-
collectionType
|
2401
|
-
};
|
2402
|
-
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2403
|
-
DescriptionComponentRenderer,
|
2404
|
-
{
|
2405
|
-
props,
|
2406
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2407
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2408
|
-
}
|
2409
|
-
) });
|
2410
|
-
};
|
2411
|
-
const ActionsPanel = () => {
|
2412
|
-
const { formatMessage } = useIntl();
|
2413
|
-
return {
|
2414
|
-
title: formatMessage({
|
2415
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2416
|
-
defaultMessage: "Document"
|
2417
|
-
}),
|
2418
|
-
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2419
|
-
};
|
2420
|
-
};
|
2421
|
-
ActionsPanel.type = "actions";
|
2422
|
-
const ActionsPanelContent = () => {
|
2423
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2424
|
-
const [
|
2425
|
-
{
|
2426
|
-
query: { status = "draft" }
|
2427
|
-
}
|
2428
|
-
] = useQueryParams();
|
2429
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2430
|
-
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2431
|
-
const props = {
|
2432
|
-
activeTab: status,
|
2433
|
-
model,
|
2434
|
-
documentId: id,
|
2435
|
-
document: isCloning ? void 0 : document,
|
2436
|
-
meta: isCloning ? void 0 : meta,
|
2437
|
-
collectionType
|
2438
|
-
};
|
2439
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2440
|
-
/* @__PURE__ */ jsx(
|
2441
|
-
DescriptionComponentRenderer,
|
2442
|
-
{
|
2443
|
-
props,
|
2444
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2445
|
-
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2446
|
-
}
|
2447
|
-
),
|
2448
|
-
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2449
|
-
] });
|
2450
|
-
};
|
2451
|
-
const Panel = React.forwardRef(({ children, title }, ref) => {
|
2452
|
-
return /* @__PURE__ */ jsxs(
|
2453
|
-
Flex,
|
2454
|
-
{
|
2455
|
-
ref,
|
2456
|
-
tag: "aside",
|
2457
|
-
"aria-labelledby": "additional-information",
|
2458
|
-
background: "neutral0",
|
2459
|
-
borderColor: "neutral150",
|
2460
|
-
hasRadius: true,
|
2461
|
-
paddingBottom: 4,
|
2462
|
-
paddingLeft: 4,
|
2463
|
-
paddingRight: 4,
|
2464
|
-
paddingTop: 4,
|
2465
|
-
shadow: "tableShadow",
|
2466
|
-
gap: 3,
|
2467
|
-
direction: "column",
|
2468
|
-
justifyContent: "stretch",
|
2469
|
-
alignItems: "flex-start",
|
2470
|
-
children: [
|
2471
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2472
|
-
children
|
2473
|
-
]
|
2474
|
-
}
|
2475
|
-
);
|
2476
|
-
});
|
2477
|
-
const HOOKS = {
|
2478
|
-
/**
|
2479
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2480
|
-
* @constant
|
2481
|
-
* @type {string}
|
2482
|
-
*/
|
2483
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2484
|
-
/**
|
2485
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2486
|
-
* @constant
|
2487
|
-
* @type {string}
|
2488
|
-
*/
|
2489
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2490
|
-
/**
|
2491
|
-
* Hook that allows to mutate the CM's edit view layout
|
2492
|
-
* @constant
|
2493
|
-
* @type {string}
|
2494
|
-
*/
|
2495
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2496
|
-
/**
|
2497
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2498
|
-
* @constant
|
2499
|
-
* @type {string}
|
2500
|
-
*/
|
2501
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2502
|
-
};
|
2503
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2504
|
-
endpoints: (builder) => ({
|
2505
|
-
getContentTypeConfiguration: builder.query({
|
2506
|
-
query: (uid) => ({
|
2507
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2508
|
-
method: "GET"
|
2509
|
-
}),
|
2510
|
-
transformResponse: (response) => response.data,
|
2511
|
-
providesTags: (_result, _error, uid) => [
|
2512
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2513
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2514
|
-
]
|
2515
|
-
}),
|
2516
|
-
getAllContentTypeSettings: builder.query({
|
2517
|
-
query: () => "/content-manager/content-types-settings",
|
2518
|
-
transformResponse: (response) => response.data,
|
2519
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2520
|
-
}),
|
2521
|
-
updateContentTypeConfiguration: builder.mutation({
|
2522
|
-
query: ({ uid, ...body }) => ({
|
2523
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2524
|
-
method: "PUT",
|
2525
|
-
data: body
|
2526
|
-
}),
|
2527
|
-
transformResponse: (response) => response.data,
|
2528
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2529
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2530
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2531
|
-
// Is this necessary?
|
2532
|
-
{ type: "InitialData" }
|
2533
|
-
]
|
2534
|
-
})
|
2535
|
-
})
|
2536
|
-
});
|
2537
|
-
const {
|
2538
|
-
useGetContentTypeConfigurationQuery,
|
2539
|
-
useGetAllContentTypeSettingsQuery,
|
2540
|
-
useUpdateContentTypeConfigurationMutation
|
2541
|
-
} = contentTypesApi;
|
2542
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2543
|
-
const { type } = attribute;
|
2544
|
-
if (type === "relation") {
|
2545
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2546
|
-
}
|
2547
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2548
|
-
};
|
2549
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2550
|
-
if (!mainFieldName) {
|
2551
|
-
return void 0;
|
2552
|
-
}
|
2553
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2554
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2555
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2556
|
-
);
|
2557
|
-
return {
|
2558
|
-
name: mainFieldName,
|
2559
|
-
type: mainFieldType ?? "string"
|
2560
|
-
};
|
2561
|
-
};
|
2562
|
-
const DEFAULT_SETTINGS = {
|
2563
|
-
bulkable: false,
|
2564
|
-
filterable: false,
|
2565
|
-
searchable: false,
|
2566
|
-
pagination: false,
|
2567
|
-
defaultSortBy: "",
|
2568
|
-
defaultSortOrder: "asc",
|
2569
|
-
mainField: "id",
|
2570
|
-
pageSize: 10
|
2571
|
-
};
|
2572
|
-
const useDocumentLayout = (model) => {
|
2573
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2574
|
-
const [{ query }] = useQueryParams();
|
2575
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2576
|
-
const { toggleNotification } = useNotification();
|
2577
|
-
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2578
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2579
|
-
const {
|
2580
|
-
data,
|
2581
|
-
isLoading: isLoadingConfigs,
|
2582
|
-
error,
|
2583
|
-
isFetching: isFetchingConfigs
|
2584
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2585
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2586
|
-
React.useEffect(() => {
|
2587
|
-
if (error) {
|
2588
|
-
toggleNotification({
|
2589
|
-
type: "danger",
|
2590
|
-
message: formatAPIError(error)
|
2591
|
-
});
|
2592
|
-
}
|
2593
|
-
}, [error, formatAPIError, toggleNotification]);
|
2594
|
-
const editLayout = React.useMemo(
|
2595
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2596
|
-
layout: [],
|
2597
|
-
components: {},
|
2598
|
-
metadatas: {},
|
2599
|
-
options: {},
|
2600
|
-
settings: DEFAULT_SETTINGS
|
2601
|
-
},
|
2602
|
-
[data, isLoading, schemas, schema, components]
|
2603
|
-
);
|
2604
|
-
const listLayout = React.useMemo(() => {
|
2605
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2606
|
-
layout: [],
|
2607
|
-
metadatas: {},
|
2608
|
-
options: {},
|
2609
|
-
settings: DEFAULT_SETTINGS
|
2610
|
-
};
|
2611
|
-
}, [data, isLoading, schemas, schema, components]);
|
2612
|
-
const { layout: edit } = React.useMemo(
|
2613
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2614
|
-
layout: editLayout,
|
2615
|
-
query
|
2616
|
-
}),
|
2617
|
-
[editLayout, query, runHookWaterfall]
|
2618
|
-
);
|
2619
|
-
return {
|
2620
|
-
error,
|
2621
|
-
isLoading,
|
2622
|
-
edit,
|
2623
|
-
list: listLayout
|
2624
|
-
};
|
2625
|
-
};
|
2626
|
-
const useDocLayout = () => {
|
2627
|
-
const { model } = useDoc();
|
2628
|
-
return useDocumentLayout(model);
|
2629
|
-
};
|
2630
|
-
const formatEditLayout = (data, {
|
2631
|
-
schemas,
|
2632
|
-
schema,
|
2633
|
-
components
|
2634
|
-
}) => {
|
2635
|
-
let currentPanelIndex = 0;
|
2636
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2637
|
-
data.contentType.layouts.edit,
|
2638
|
-
schema?.attributes,
|
2639
|
-
data.contentType.metadatas,
|
2640
|
-
{ configurations: data.components, schemas: components },
|
2641
|
-
schemas
|
2642
|
-
).reduce((panels, row) => {
|
2643
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2644
|
-
panels.push([row]);
|
2645
|
-
currentPanelIndex += 2;
|
2646
|
-
} else {
|
2647
|
-
if (!panels[currentPanelIndex]) {
|
2648
|
-
panels.push([]);
|
2649
|
-
}
|
2650
|
-
panels[currentPanelIndex].push(row);
|
2651
|
-
}
|
2652
|
-
return panels;
|
2653
|
-
}, []);
|
2654
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2655
|
-
(acc, [uid, configuration]) => {
|
2656
|
-
acc[uid] = {
|
2657
|
-
layout: convertEditLayoutToFieldLayouts(
|
2658
|
-
configuration.layouts.edit,
|
2659
|
-
components[uid].attributes,
|
2660
|
-
configuration.metadatas
|
2661
|
-
),
|
2662
|
-
settings: {
|
2663
|
-
...configuration.settings,
|
2664
|
-
icon: components[uid].info.icon,
|
2665
|
-
displayName: components[uid].info.displayName
|
2666
|
-
}
|
2667
|
-
};
|
2668
|
-
return acc;
|
2669
|
-
},
|
2670
|
-
{}
|
2671
|
-
);
|
2672
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2673
|
-
(acc, [attribute, metadata]) => {
|
2674
|
-
return {
|
2675
|
-
...acc,
|
2676
|
-
[attribute]: metadata.edit
|
2677
|
-
};
|
2678
|
-
},
|
2679
|
-
{}
|
2680
|
-
);
|
2681
|
-
return {
|
2682
|
-
layout: panelledEditAttributes,
|
2683
|
-
components: componentEditAttributes,
|
2684
|
-
metadatas: editMetadatas,
|
2685
|
-
settings: {
|
2686
|
-
...data.contentType.settings,
|
2687
|
-
displayName: schema?.info.displayName
|
2911
|
+
model,
|
2912
|
+
collectionType,
|
2913
|
+
params: {
|
2914
|
+
locale: "*"
|
2915
|
+
}
|
2916
|
+
});
|
2917
|
+
if (!("error" in res)) {
|
2918
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2919
|
+
}
|
2920
|
+
} finally {
|
2921
|
+
if (!listViewPathMatch) {
|
2922
|
+
setSubmitting(false);
|
2923
|
+
}
|
2924
|
+
}
|
2925
|
+
}
|
2688
2926
|
},
|
2689
|
-
|
2690
|
-
|
2691
|
-
...schema?.pluginOptions,
|
2692
|
-
...data.contentType.options
|
2693
|
-
}
|
2927
|
+
variant: "danger",
|
2928
|
+
position: ["header", "table-row"]
|
2694
2929
|
};
|
2695
2930
|
};
|
2696
|
-
|
2697
|
-
|
2698
|
-
|
2699
|
-
|
2700
|
-
|
2701
|
-
|
2702
|
-
}
|
2703
|
-
|
2704
|
-
|
2705
|
-
|
2706
|
-
|
2707
|
-
|
2708
|
-
|
2709
|
-
|
2710
|
-
|
2711
|
-
|
2712
|
-
|
2713
|
-
|
2714
|
-
|
2715
|
-
|
2716
|
-
|
2717
|
-
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
}
|
2723
|
-
}
|
2724
|
-
);
|
2931
|
+
DeleteAction$1.type = "delete";
|
2932
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2933
|
+
const Panels = () => {
|
2934
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2935
|
+
const [
|
2936
|
+
{
|
2937
|
+
query: { status }
|
2938
|
+
}
|
2939
|
+
] = useQueryParams({
|
2940
|
+
status: "draft"
|
2941
|
+
});
|
2942
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2943
|
+
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2944
|
+
const props = {
|
2945
|
+
activeTab: status,
|
2946
|
+
model,
|
2947
|
+
documentId: id,
|
2948
|
+
document: isCloning ? void 0 : document,
|
2949
|
+
meta: isCloning ? void 0 : meta,
|
2950
|
+
collectionType
|
2951
|
+
};
|
2952
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2953
|
+
DescriptionComponentRenderer,
|
2954
|
+
{
|
2955
|
+
props,
|
2956
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2957
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2958
|
+
}
|
2959
|
+
) });
|
2725
2960
|
};
|
2726
|
-
const
|
2727
|
-
|
2728
|
-
schema,
|
2729
|
-
components
|
2730
|
-
}) => {
|
2731
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2732
|
-
(acc, [attribute, metadata]) => {
|
2733
|
-
return {
|
2734
|
-
...acc,
|
2735
|
-
[attribute]: metadata.list
|
2736
|
-
};
|
2737
|
-
},
|
2738
|
-
{}
|
2739
|
-
);
|
2740
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2741
|
-
data.contentType.layouts.list,
|
2742
|
-
schema?.attributes,
|
2743
|
-
listMetadatas,
|
2744
|
-
{ configurations: data.components, schemas: components },
|
2745
|
-
schemas
|
2746
|
-
);
|
2961
|
+
const ActionsPanel = () => {
|
2962
|
+
const { formatMessage } = useIntl();
|
2747
2963
|
return {
|
2748
|
-
|
2749
|
-
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
...schema?.pluginOptions,
|
2754
|
-
...data.contentType.options
|
2755
|
-
}
|
2964
|
+
title: formatMessage({
|
2965
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2966
|
+
defaultMessage: "Entry"
|
2967
|
+
}),
|
2968
|
+
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2756
2969
|
};
|
2757
2970
|
};
|
2758
|
-
|
2759
|
-
|
2760
|
-
|
2761
|
-
|
2762
|
-
|
2971
|
+
ActionsPanel.type = "actions";
|
2972
|
+
const ActionsPanelContent = () => {
|
2973
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2974
|
+
const [
|
2975
|
+
{
|
2976
|
+
query: { status = "draft" }
|
2763
2977
|
}
|
2764
|
-
|
2765
|
-
|
2766
|
-
|
2767
|
-
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2978
|
+
] = useQueryParams();
|
2979
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2980
|
+
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2981
|
+
const props = {
|
2982
|
+
activeTab: status,
|
2983
|
+
model,
|
2984
|
+
documentId: id,
|
2985
|
+
document: isCloning ? void 0 : document,
|
2986
|
+
meta: isCloning ? void 0 : meta,
|
2987
|
+
collectionType
|
2988
|
+
};
|
2989
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2990
|
+
/* @__PURE__ */ jsx(
|
2991
|
+
DescriptionComponentRenderer,
|
2992
|
+
{
|
2993
|
+
props,
|
2994
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2995
|
+
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2996
|
+
}
|
2997
|
+
),
|
2998
|
+
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2999
|
+
] });
|
2778
3000
|
};
|
3001
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
3002
|
+
return /* @__PURE__ */ jsxs(
|
3003
|
+
Flex,
|
3004
|
+
{
|
3005
|
+
ref,
|
3006
|
+
tag: "aside",
|
3007
|
+
"aria-labelledby": "additional-information",
|
3008
|
+
background: "neutral0",
|
3009
|
+
borderColor: "neutral150",
|
3010
|
+
hasRadius: true,
|
3011
|
+
paddingBottom: 4,
|
3012
|
+
paddingLeft: 4,
|
3013
|
+
paddingRight: 4,
|
3014
|
+
paddingTop: 4,
|
3015
|
+
shadow: "tableShadow",
|
3016
|
+
gap: 3,
|
3017
|
+
direction: "column",
|
3018
|
+
justifyContent: "stretch",
|
3019
|
+
alignItems: "flex-start",
|
3020
|
+
children: [
|
3021
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3022
|
+
children
|
3023
|
+
]
|
3024
|
+
}
|
3025
|
+
);
|
3026
|
+
});
|
2779
3027
|
const ConfirmBulkActionDialog = ({
|
2780
3028
|
onToggleDialog,
|
2781
3029
|
isOpen = false,
|
@@ -2783,7 +3031,7 @@ const ConfirmBulkActionDialog = ({
|
|
2783
3031
|
endAction
|
2784
3032
|
}) => {
|
2785
3033
|
const { formatMessage } = useIntl();
|
2786
|
-
return /* @__PURE__ */ jsx(Dialog.Root, {
|
3034
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2787
3035
|
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
|
2788
3036
|
id: "app.components.ConfirmDialog.title",
|
2789
3037
|
defaultMessage: "Confirmation"
|
@@ -2814,6 +3062,7 @@ const ConfirmDialogPublishAll = ({
|
|
2814
3062
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2815
3063
|
const { model, schema } = useDoc();
|
2816
3064
|
const [{ query }] = useQueryParams();
|
3065
|
+
const enableDraftRelationsCount = false;
|
2817
3066
|
const {
|
2818
3067
|
data: countDraftRelations = 0,
|
2819
3068
|
isLoading,
|
@@ -2825,7 +3074,7 @@ const ConfirmDialogPublishAll = ({
|
|
2825
3074
|
locale: query?.plugins?.i18n?.locale
|
2826
3075
|
},
|
2827
3076
|
{
|
2828
|
-
skip:
|
3077
|
+
skip: !enableDraftRelationsCount
|
2829
3078
|
}
|
2830
3079
|
);
|
2831
3080
|
React.useEffect(() => {
|
@@ -3010,7 +3259,7 @@ const SelectedEntriesTableContent = ({
|
|
3010
3259
|
status: row.status
|
3011
3260
|
}
|
3012
3261
|
) }),
|
3013
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3262
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3014
3263
|
IconButton,
|
3015
3264
|
{
|
3016
3265
|
tag: Link,
|
@@ -3033,9 +3282,10 @@ const SelectedEntriesTableContent = ({
|
|
3033
3282
|
),
|
3034
3283
|
target: "_blank",
|
3035
3284
|
marginLeft: "auto",
|
3036
|
-
|
3285
|
+
variant: "ghost",
|
3286
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3037
3287
|
}
|
3038
|
-
) })
|
3288
|
+
) }) })
|
3039
3289
|
] }, row.id)) })
|
3040
3290
|
] });
|
3041
3291
|
};
|
@@ -3072,7 +3322,13 @@ const SelectedEntriesModalContent = ({
|
|
3072
3322
|
);
|
3073
3323
|
const { rows, validationErrors } = React.useMemo(() => {
|
3074
3324
|
if (data.length > 0 && schema) {
|
3075
|
-
const validate = createYupSchema(
|
3325
|
+
const validate = createYupSchema(
|
3326
|
+
schema.attributes,
|
3327
|
+
components,
|
3328
|
+
// Since this is the "Publish" action, the validation
|
3329
|
+
// schema must enforce the rules for published entities
|
3330
|
+
{ status: "published" }
|
3331
|
+
);
|
3076
3332
|
const validationErrors2 = {};
|
3077
3333
|
const rows2 = data.map((entry) => {
|
3078
3334
|
try {
|
@@ -3422,7 +3678,7 @@ const TableActions = ({ document }) => {
|
|
3422
3678
|
DescriptionComponentRenderer,
|
3423
3679
|
{
|
3424
3680
|
props,
|
3425
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3681
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3426
3682
|
children: (actions2) => {
|
3427
3683
|
const tableRowActions = actions2.filter((action) => {
|
3428
3684
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3533,7 +3789,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3533
3789
|
}),
|
3534
3790
|
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3535
3791
|
footer: ({ onClose }) => {
|
3536
|
-
return /* @__PURE__ */ jsxs(
|
3792
|
+
return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3537
3793
|
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3538
3794
|
id: "cancel",
|
3539
3795
|
defaultMessage: "Cancel"
|
@@ -3574,8 +3830,7 @@ class ContentManagerPlugin {
|
|
3574
3830
|
documentActions = [
|
3575
3831
|
...DEFAULT_ACTIONS,
|
3576
3832
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3577
|
-
...DEFAULT_HEADER_ACTIONS
|
3578
|
-
HistoryAction
|
3833
|
+
...DEFAULT_HEADER_ACTIONS
|
3579
3834
|
];
|
3580
3835
|
editViewSidePanels = [ActionsPanel];
|
3581
3836
|
headerActions = [];
|
@@ -3664,6 +3919,52 @@ const getPrintableType = (value) => {
|
|
3664
3919
|
}
|
3665
3920
|
return nativeType;
|
3666
3921
|
};
|
3922
|
+
const HistoryAction = ({ model, document }) => {
|
3923
|
+
const { formatMessage } = useIntl();
|
3924
|
+
const [{ query }] = useQueryParams();
|
3925
|
+
const navigate = useNavigate();
|
3926
|
+
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3927
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3928
|
+
return null;
|
3929
|
+
}
|
3930
|
+
return {
|
3931
|
+
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3932
|
+
label: formatMessage({
|
3933
|
+
id: "content-manager.history.document-action",
|
3934
|
+
defaultMessage: "Content History"
|
3935
|
+
}),
|
3936
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3937
|
+
disabled: (
|
3938
|
+
/**
|
3939
|
+
* The user is creating a new document.
|
3940
|
+
* It hasn't been saved yet, so there's no history to go to
|
3941
|
+
*/
|
3942
|
+
!document || /**
|
3943
|
+
* The document has been created but the current dimension has never been saved.
|
3944
|
+
* For example, the user is creating a new locale in an existing document,
|
3945
|
+
* so there's no history for the document in that locale
|
3946
|
+
*/
|
3947
|
+
!document.id || /**
|
3948
|
+
* History is only available for content types created by the user.
|
3949
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3950
|
+
* which start with `admin::` or `plugin::`
|
3951
|
+
*/
|
3952
|
+
!model.startsWith("api::")
|
3953
|
+
),
|
3954
|
+
position: "header"
|
3955
|
+
};
|
3956
|
+
};
|
3957
|
+
HistoryAction.type = "history";
|
3958
|
+
const historyAdmin = {
|
3959
|
+
bootstrap(app) {
|
3960
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3961
|
+
addDocumentAction((actions2) => {
|
3962
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3963
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3964
|
+
return actions2;
|
3965
|
+
});
|
3966
|
+
}
|
3967
|
+
};
|
3667
3968
|
const initialState = {
|
3668
3969
|
collectionTypeLinks: [],
|
3669
3970
|
components: [],
|
@@ -3700,6 +4001,57 @@ const { setInitialData } = actions;
|
|
3700
4001
|
const reducer = combineReducers({
|
3701
4002
|
app: reducer$1
|
3702
4003
|
});
|
4004
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4005
|
+
endpoints: (builder) => ({
|
4006
|
+
getPreviewUrl: builder.query({
|
4007
|
+
query({ query, params }) {
|
4008
|
+
return {
|
4009
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4010
|
+
method: "GET",
|
4011
|
+
config: {
|
4012
|
+
params: query
|
4013
|
+
}
|
4014
|
+
};
|
4015
|
+
}
|
4016
|
+
})
|
4017
|
+
})
|
4018
|
+
});
|
4019
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4020
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4021
|
+
const { formatMessage } = useIntl();
|
4022
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4023
|
+
params: {
|
4024
|
+
contentType: model
|
4025
|
+
},
|
4026
|
+
query: {
|
4027
|
+
documentId,
|
4028
|
+
locale: document?.locale,
|
4029
|
+
status: document?.status
|
4030
|
+
}
|
4031
|
+
});
|
4032
|
+
if (!data?.data?.url || error) {
|
4033
|
+
return null;
|
4034
|
+
}
|
4035
|
+
return {
|
4036
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4037
|
+
content: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, tag: Link, to: data.data.url, target: "_blank", children: formatMessage({
|
4038
|
+
id: "content-manager.preview.panel.button",
|
4039
|
+
defaultMessage: "Open preview"
|
4040
|
+
}) })
|
4041
|
+
};
|
4042
|
+
};
|
4043
|
+
const FEATURE_ID = "preview";
|
4044
|
+
const previewAdmin = {
|
4045
|
+
bootstrap(app) {
|
4046
|
+
if (!window.strapi.future.isEnabled(FEATURE_ID)) {
|
4047
|
+
return;
|
4048
|
+
}
|
4049
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4050
|
+
if ("addEditViewSidePanel" in contentManagerPluginApis && typeof contentManagerPluginApis.addEditViewSidePanel === "function") {
|
4051
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4052
|
+
}
|
4053
|
+
}
|
4054
|
+
};
|
3703
4055
|
const index = {
|
3704
4056
|
register(app) {
|
3705
4057
|
const cm = new ContentManagerPlugin();
|
@@ -3719,7 +4071,7 @@ const index = {
|
|
3719
4071
|
app.router.addRoute({
|
3720
4072
|
path: "content-manager/*",
|
3721
4073
|
lazy: async () => {
|
3722
|
-
const { Layout } = await import("./layout-
|
4074
|
+
const { Layout } = await import("./layout-DNfLIjbP.mjs");
|
3723
4075
|
return {
|
3724
4076
|
Component: Layout
|
3725
4077
|
};
|
@@ -3728,10 +4080,18 @@ const index = {
|
|
3728
4080
|
});
|
3729
4081
|
app.registerPlugin(cm.config);
|
3730
4082
|
},
|
4083
|
+
bootstrap(app) {
|
4084
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4085
|
+
historyAdmin.bootstrap(app);
|
4086
|
+
}
|
4087
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4088
|
+
previewAdmin.bootstrap(app);
|
4089
|
+
}
|
4090
|
+
},
|
3731
4091
|
async registerTrads({ locales }) {
|
3732
4092
|
const importedTrads = await Promise.all(
|
3733
4093
|
locales.map((locale) => {
|
3734
|
-
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-
|
4094
|
+
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-DPfZ6tPQ.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 }) => {
|
3735
4095
|
return {
|
3736
4096
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3737
4097
|
locale
|
@@ -3752,13 +4112,15 @@ export {
|
|
3752
4112
|
BulkActionsRenderer as B,
|
3753
4113
|
COLLECTION_TYPES as C,
|
3754
4114
|
DocumentStatus as D,
|
3755
|
-
|
3756
|
-
|
3757
|
-
|
4115
|
+
extractContentTypeComponents as E,
|
4116
|
+
DEFAULT_SETTINGS as F,
|
4117
|
+
convertEditLayoutToFieldLayouts as G,
|
3758
4118
|
HOOKS as H,
|
3759
4119
|
InjectionZone as I,
|
3760
|
-
|
3761
|
-
|
4120
|
+
useDocument as J,
|
4121
|
+
index as K,
|
4122
|
+
useContentManagerContext as L,
|
4123
|
+
useDocumentActions as M,
|
3762
4124
|
Panels as P,
|
3763
4125
|
RelativeTime as R,
|
3764
4126
|
SINGLE_TYPES as S,
|
@@ -3776,18 +4138,18 @@ export {
|
|
3776
4138
|
PERMISSIONS as k,
|
3777
4139
|
DocumentRBAC as l,
|
3778
4140
|
DOCUMENT_META_FIELDS as m,
|
3779
|
-
|
3780
|
-
|
3781
|
-
|
3782
|
-
|
3783
|
-
|
4141
|
+
CLONE_PATH as n,
|
4142
|
+
useDocLayout as o,
|
4143
|
+
useGetContentTypeConfigurationQuery as p,
|
4144
|
+
CREATOR_FIELDS as q,
|
4145
|
+
getMainField as r,
|
3784
4146
|
setInitialData as s,
|
3785
|
-
|
4147
|
+
getDisplayName as t,
|
3786
4148
|
useContentTypeSchema as u,
|
3787
|
-
|
3788
|
-
|
3789
|
-
|
3790
|
-
|
3791
|
-
|
4149
|
+
checkIfAttributeIsDisplayable as v,
|
4150
|
+
useGetAllDocumentsQuery as w,
|
4151
|
+
convertListLayoutToFieldLayouts as x,
|
4152
|
+
capitalise as y,
|
4153
|
+
useUpdateContentTypeConfigurationMutation as z
|
3792
4154
|
};
|
3793
|
-
//# sourceMappingURL=index-
|
4155
|
+
//# sourceMappingURL=index-DW7xp_LG.mjs.map
|