@strapi/content-manager 0.0.0-experimental.bd712ad3930045f4a5d2144c119e0b7856e97fc4 → 0.0.0-experimental.c222e1c4de12dd05c26938a605a1128fb3481d1d
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-BWQv6yRj.js → ComponentConfigurationPage--MCP7Aew.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BWQv6yRj.js.map → ComponentConfigurationPage--MCP7Aew.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-C7ImeKGM.mjs → ComponentConfigurationPage-DT41asyM.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-C7ImeKGM.mjs.map → ComponentConfigurationPage-DT41asyM.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-MItFGzT9.mjs → EditConfigurationPage-DznPxn9p.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-MItFGzT9.mjs.map → EditConfigurationPage-DznPxn9p.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CEGwxV-L.js → EditConfigurationPage-qgnNvv_u.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-CEGwxV-L.js.map → EditConfigurationPage-qgnNvv_u.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-DhmAg0NK.mjs → EditViewPage-B_k7z288.mjs} +33 -11
- package/dist/_chunks/EditViewPage-B_k7z288.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-CmMi2Xsn.js → EditViewPage-Bb4S7p8c.js} +32 -10
- package/dist/_chunks/EditViewPage-Bb4S7p8c.js.map +1 -0
- package/dist/_chunks/{Field-1DLtcLAI.js → Field-ByR1mllE.js} +181 -109
- package/dist/_chunks/Field-ByR1mllE.js.map +1 -0
- package/dist/_chunks/{Field-Cs62u5pl.mjs → Field-DmwbE0TL.mjs} +179 -107
- package/dist/_chunks/Field-DmwbE0TL.mjs.map +1 -0
- package/dist/_chunks/{Form-CqFA7F_V.js → Form-BpeyAyS1.js} +36 -17
- package/dist/_chunks/Form-BpeyAyS1.js.map +1 -0
- package/dist/_chunks/{Form-zYHtzGUX.mjs → Form-Dvt5eouJ.mjs} +36 -17
- package/dist/_chunks/Form-Dvt5eouJ.mjs.map +1 -0
- package/dist/_chunks/{History-DalgFQ3D.mjs → History-CAERKpYl.mjs} +54 -54
- package/dist/_chunks/History-CAERKpYl.mjs.map +1 -0
- package/dist/_chunks/{History-BblwXv7-.js → History-d-IgDGPl.js} +53 -53
- package/dist/_chunks/History-d-IgDGPl.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DWy-vRzs.mjs → ListConfigurationPage-CVVT45M8.mjs} +15 -5
- package/dist/_chunks/ListConfigurationPage-CVVT45M8.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Cpy4QqNd.js → ListConfigurationPage-DSX98CYb.js} +15 -5
- package/dist/_chunks/ListConfigurationPage-DSX98CYb.js.map +1 -0
- package/dist/_chunks/{ListViewPage-DFjn1DNW.js → ListViewPage-C9gPPp-V.js} +61 -41
- package/dist/_chunks/ListViewPage-C9gPPp-V.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BkAwIW9s.mjs → ListViewPage-Q4g6kHDl.mjs} +59 -39
- package/dist/_chunks/ListViewPage-Q4g6kHDl.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-B9BCNNdL.mjs → NoContentTypePage-BY4YRGs0.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-B9BCNNdL.mjs.map → NoContentTypePage-BY4YRGs0.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-C-3ykoxs.js → NoContentTypePage-D09gppmy.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-C-3ykoxs.js.map → NoContentTypePage-D09gppmy.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DKLmDZnZ.js → NoPermissionsPage-32WgThJG.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DKLmDZnZ.js.map → NoPermissionsPage-32WgThJG.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-Bt_HWGat.mjs → NoPermissionsPage-CyM16RKL.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-Bt_HWGat.mjs.map → NoPermissionsPage-CyM16RKL.mjs.map} +1 -1
- package/dist/_chunks/Preview-C2WFq4S8.mjs +267 -0
- package/dist/_chunks/Preview-C2WFq4S8.mjs.map +1 -0
- package/dist/_chunks/Preview-PpV3g9wJ.js +286 -0
- package/dist/_chunks/Preview-PpV3g9wJ.js.map +1 -0
- package/dist/_chunks/{Relations-CJmTbZ8T.mjs → Relations-B_Yn9xGB.mjs} +73 -37
- package/dist/_chunks/Relations-B_Yn9xGB.mjs.map +1 -0
- package/dist/_chunks/{Relations-CrxfoH2n.js → Relations-mWaebC5t.js} +72 -36
- package/dist/_chunks/Relations-mWaebC5t.js.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-CHOp_xJv.js} +27 -16
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-CHOp_xJv.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-D_BMf0hT.mjs} +27 -16
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-D_BMf0hT.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-D1344xdw.mjs → index-CbytGVdz.mjs} +1070 -698
- package/dist/_chunks/index-CbytGVdz.mjs.map +1 -0
- package/dist/_chunks/{index-Buwn78Rt.js → index-iun2i4xv.js} +1052 -679
- package/dist/_chunks/index-iun2i4xv.js.map +1 -0
- package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
- package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
- package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
- package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
- package/dist/_chunks/{layout-ChVuUpa1.mjs → layout-Btu_cMRF.mjs} +22 -9
- package/dist/_chunks/layout-Btu_cMRF.mjs.map +1 -0
- package/dist/_chunks/{layout-DRuJUpas.js → layout-CkaP4K5_.js} +21 -8
- package/dist/_chunks/layout-CkaP4K5_.js.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-B-deMCy4.mjs → relations-Cn5re8ia.mjs} +6 -7
- package/dist/_chunks/relations-Cn5re8ia.mjs.map +1 -0
- package/dist/_chunks/{relations-DuoUwyJr.js → relations-O_v9g0v_.js} +6 -7
- package/dist/_chunks/relations-O_v9g0v_.js.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +5 -4
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/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/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/constants.d.ts +1 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/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-CmMi2Xsn.js.map +0 -1
- package/dist/_chunks/EditViewPage-DhmAg0NK.mjs.map +0 -1
- package/dist/_chunks/Field-1DLtcLAI.js.map +0 -1
- package/dist/_chunks/Field-Cs62u5pl.mjs.map +0 -1
- package/dist/_chunks/Form-CqFA7F_V.js.map +0 -1
- package/dist/_chunks/Form-zYHtzGUX.mjs.map +0 -1
- package/dist/_chunks/History-BblwXv7-.js.map +0 -1
- package/dist/_chunks/History-DalgFQ3D.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Cpy4QqNd.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DWy-vRzs.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-BkAwIW9s.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-DFjn1DNW.js.map +0 -1
- package/dist/_chunks/Relations-CJmTbZ8T.mjs.map +0 -1
- package/dist/_chunks/Relations-CrxfoH2n.js.map +0 -1
- package/dist/_chunks/index-Buwn78Rt.js.map +0 -1
- package/dist/_chunks/index-D1344xdw.mjs.map +0 -1
- package/dist/_chunks/layout-ChVuUpa1.mjs.map +0 -1
- package/dist/_chunks/layout-DRuJUpas.js.map +0 -1
- package/dist/_chunks/relations-B-deMCy4.mjs.map +0 -1
- package/dist/_chunks/relations-DuoUwyJr.js.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
@@ -1,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
|
}),
|
@@ -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.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
604
|
-
return schema.min(1, translatedErrors.required);
|
605
|
-
}
|
606
|
-
if (attribute.required && attribute.type !== "relation") {
|
607
|
-
return schema.required(translatedErrors.required);
|
608
|
-
}
|
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,32 +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 (
|
642
|
-
if (!attribute.required && "test" in schema && min) {
|
643
|
-
return schema.test(
|
644
|
-
"custom-min",
|
645
|
-
{
|
646
|
-
...translatedErrors.min,
|
647
|
-
values: {
|
648
|
-
min: attribute.min
|
649
|
-
}
|
650
|
-
},
|
651
|
-
(value) => {
|
652
|
-
if (!value) {
|
653
|
-
return true;
|
654
|
-
}
|
655
|
-
if (Array.isArray(value) && value.length === 0) {
|
656
|
-
return true;
|
657
|
-
}
|
658
|
-
return value.length >= min;
|
659
|
-
}
|
660
|
-
);
|
661
|
-
}
|
662
|
-
}
|
663
|
-
if ("min" in schema && min) {
|
683
|
+
if (min) {
|
664
684
|
return schema.min(min, {
|
665
685
|
...translatedErrors.min,
|
666
686
|
values: {
|
@@ -778,19 +798,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
778
798
|
}, {});
|
779
799
|
return componentsByKey;
|
780
800
|
};
|
781
|
-
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);
|
782
900
|
const { toggleNotification } = useNotification();
|
783
901
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
902
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
784
903
|
const {
|
785
|
-
|
786
|
-
isLoading:
|
787
|
-
|
788
|
-
|
789
|
-
} =
|
790
|
-
|
791
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
792
|
-
});
|
793
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
904
|
+
data,
|
905
|
+
isLoading: isLoadingConfigs,
|
906
|
+
error,
|
907
|
+
isFetching: isFetchingConfigs
|
908
|
+
} = useGetContentTypeConfigurationQuery(model);
|
909
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
794
910
|
React.useEffect(() => {
|
795
911
|
if (error) {
|
796
912
|
toggleNotification({
|
@@ -798,39 +914,255 @@ const useDocument = (args, opts) => {
|
|
798
914
|
message: formatAPIError(error)
|
799
915
|
});
|
800
916
|
}
|
801
|
-
}, [
|
802
|
-
const
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
(document) => {
|
810
|
-
if (!validationSchema) {
|
811
|
-
throw new Error(
|
812
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
813
|
-
);
|
814
|
-
}
|
815
|
-
try {
|
816
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
817
|
-
return null;
|
818
|
-
} catch (error2) {
|
819
|
-
if (error2 instanceof ValidationError) {
|
820
|
-
return getYupValidationErrors(error2);
|
821
|
-
}
|
822
|
-
throw error2;
|
823
|
-
}
|
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
|
824
925
|
},
|
825
|
-
[
|
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]
|
826
942
|
);
|
827
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
828
943
|
return {
|
829
|
-
|
830
|
-
|
831
|
-
|
944
|
+
error,
|
945
|
+
isLoading,
|
946
|
+
edit,
|
947
|
+
list: listLayout
|
948
|
+
};
|
949
|
+
};
|
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,
|
832
1162
|
isLoading,
|
1163
|
+
hasError,
|
833
1164
|
schema,
|
1165
|
+
schemas,
|
834
1166
|
validate
|
835
1167
|
};
|
836
1168
|
};
|
@@ -844,22 +1176,60 @@ const useDoc = () => {
|
|
844
1176
|
if (!slug) {
|
845
1177
|
throw new Error("Could not find model in url params");
|
846
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;
|
847
1186
|
return {
|
848
1187
|
collectionType,
|
849
1188
|
model: slug,
|
850
|
-
id:
|
851
|
-
...
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
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
|
857
1230
|
};
|
858
1231
|
};
|
859
1232
|
const prefixPluginTranslations = (trad, pluginId) => {
|
860
|
-
if (!pluginId) {
|
861
|
-
throw new TypeError("pluginId can't be empty");
|
862
|
-
}
|
863
1233
|
return Object.keys(trad).reduce((acc, current) => {
|
864
1234
|
acc[`${pluginId}.${current}`] = trad[current];
|
865
1235
|
return acc;
|
@@ -875,6 +1245,8 @@ const useDocumentActions = () => {
|
|
875
1245
|
const { formatMessage } = useIntl();
|
876
1246
|
const { trackUsage } = useTracking();
|
877
1247
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1248
|
+
const navigate = useNavigate();
|
1249
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
878
1250
|
const [deleteDocument] = useDeleteDocumentMutation();
|
879
1251
|
const _delete = React.useCallback(
|
880
1252
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1189,6 +1561,7 @@ const useDocumentActions = () => {
|
|
1189
1561
|
defaultMessage: "Saved document"
|
1190
1562
|
})
|
1191
1563
|
});
|
1564
|
+
setCurrentStep("contentManager.success");
|
1192
1565
|
return res.data;
|
1193
1566
|
} catch (err) {
|
1194
1567
|
toggleNotification({
|
@@ -1210,7 +1583,6 @@ const useDocumentActions = () => {
|
|
1210
1583
|
sourceId
|
1211
1584
|
});
|
1212
1585
|
if ("error" in res) {
|
1213
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1214
1586
|
return { error: res.error };
|
1215
1587
|
}
|
1216
1588
|
toggleNotification({
|
@@ -1229,7 +1601,7 @@ const useDocumentActions = () => {
|
|
1229
1601
|
throw err;
|
1230
1602
|
}
|
1231
1603
|
},
|
1232
|
-
[autoCloneDocument,
|
1604
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1233
1605
|
);
|
1234
1606
|
const [cloneDocument] = useCloneDocumentMutation();
|
1235
1607
|
const clone = React.useCallback(
|
@@ -1255,6 +1627,7 @@ const useDocumentActions = () => {
|
|
1255
1627
|
defaultMessage: "Cloned document"
|
1256
1628
|
})
|
1257
1629
|
});
|
1630
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1258
1631
|
return res.data;
|
1259
1632
|
} catch (err) {
|
1260
1633
|
toggleNotification({
|
@@ -1265,7 +1638,7 @@ const useDocumentActions = () => {
|
|
1265
1638
|
throw err;
|
1266
1639
|
}
|
1267
1640
|
},
|
1268
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1641
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1269
1642
|
);
|
1270
1643
|
const [getDoc] = useLazyGetDocumentQuery();
|
1271
1644
|
const getDocument = React.useCallback(
|
@@ -1290,10 +1663,10 @@ const useDocumentActions = () => {
|
|
1290
1663
|
update
|
1291
1664
|
};
|
1292
1665
|
};
|
1293
|
-
const ProtectedHistoryPage = lazy(
|
1294
|
-
() => import("./History-
|
1666
|
+
const ProtectedHistoryPage = React.lazy(
|
1667
|
+
() => import("./History-CAERKpYl.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1295
1668
|
);
|
1296
|
-
const routes$
|
1669
|
+
const routes$2 = [
|
1297
1670
|
{
|
1298
1671
|
path: ":collectionType/:slug/:id/history",
|
1299
1672
|
Component: ProtectedHistoryPage
|
@@ -1303,32 +1676,45 @@ const routes$1 = [
|
|
1303
1676
|
Component: ProtectedHistoryPage
|
1304
1677
|
}
|
1305
1678
|
];
|
1679
|
+
const ProtectedPreviewPage = React.lazy(
|
1680
|
+
() => import("./Preview-C2WFq4S8.mjs").then((mod) => ({ default: mod.ProtectedPreviewPage }))
|
1681
|
+
);
|
1682
|
+
const routes$1 = [
|
1683
|
+
{
|
1684
|
+
path: ":collectionType/:slug/:id/preview",
|
1685
|
+
Component: ProtectedPreviewPage
|
1686
|
+
},
|
1687
|
+
{
|
1688
|
+
path: ":collectionType/:slug/preview",
|
1689
|
+
Component: ProtectedPreviewPage
|
1690
|
+
}
|
1691
|
+
];
|
1306
1692
|
const ProtectedEditViewPage = lazy(
|
1307
|
-
() => import("./EditViewPage-
|
1693
|
+
() => import("./EditViewPage-B_k7z288.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1308
1694
|
);
|
1309
1695
|
const ProtectedListViewPage = lazy(
|
1310
|
-
() => import("./ListViewPage-
|
1696
|
+
() => import("./ListViewPage-Q4g6kHDl.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1311
1697
|
);
|
1312
1698
|
const ProtectedListConfiguration = lazy(
|
1313
|
-
() => import("./ListConfigurationPage-
|
1699
|
+
() => import("./ListConfigurationPage-CVVT45M8.mjs").then((mod) => ({
|
1314
1700
|
default: mod.ProtectedListConfiguration
|
1315
1701
|
}))
|
1316
1702
|
);
|
1317
1703
|
const ProtectedEditConfigurationPage = lazy(
|
1318
|
-
() => import("./EditConfigurationPage-
|
1704
|
+
() => import("./EditConfigurationPage-DznPxn9p.mjs").then((mod) => ({
|
1319
1705
|
default: mod.ProtectedEditConfigurationPage
|
1320
1706
|
}))
|
1321
1707
|
);
|
1322
1708
|
const ProtectedComponentConfigurationPage = lazy(
|
1323
|
-
() => import("./ComponentConfigurationPage-
|
1709
|
+
() => import("./ComponentConfigurationPage-DT41asyM.mjs").then((mod) => ({
|
1324
1710
|
default: mod.ProtectedComponentConfigurationPage
|
1325
1711
|
}))
|
1326
1712
|
);
|
1327
1713
|
const NoPermissions = lazy(
|
1328
|
-
() => import("./NoPermissionsPage-
|
1714
|
+
() => import("./NoPermissionsPage-CyM16RKL.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1329
1715
|
);
|
1330
1716
|
const NoContentType = lazy(
|
1331
|
-
() => import("./NoContentTypePage-
|
1717
|
+
() => import("./NoContentTypePage-BY4YRGs0.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1332
1718
|
);
|
1333
1719
|
const CollectionTypePages = () => {
|
1334
1720
|
const { collectionType } = useParams();
|
@@ -1374,6 +1760,7 @@ const routes = [
|
|
1374
1760
|
path: "no-content-types",
|
1375
1761
|
Component: NoContentType
|
1376
1762
|
},
|
1763
|
+
...routes$2,
|
1377
1764
|
...routes$1
|
1378
1765
|
];
|
1379
1766
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1442,12 +1829,14 @@ const DocumentActionButton = (action) => {
|
|
1442
1829
|
/* @__PURE__ */ jsx(
|
1443
1830
|
Button,
|
1444
1831
|
{
|
1445
|
-
flex:
|
1832
|
+
flex: "auto",
|
1446
1833
|
startIcon: action.icon,
|
1447
1834
|
disabled: action.disabled,
|
1448
1835
|
onClick: handleClick(action),
|
1449
1836
|
justifyContent: "center",
|
1450
1837
|
variant: action.variant || "default",
|
1838
|
+
paddingTop: "7px",
|
1839
|
+
paddingBottom: "7px",
|
1451
1840
|
children: action.label
|
1452
1841
|
}
|
1453
1842
|
),
|
@@ -1455,7 +1844,7 @@ const DocumentActionButton = (action) => {
|
|
1455
1844
|
DocumentActionConfirmDialog,
|
1456
1845
|
{
|
1457
1846
|
...action.dialog,
|
1458
|
-
variant: action.variant,
|
1847
|
+
variant: action.dialog?.variant ?? action.variant,
|
1459
1848
|
isOpen: dialogId === action.id,
|
1460
1849
|
onClose: handleClose
|
1461
1850
|
}
|
@@ -1512,9 +1901,9 @@ const DocumentActionsMenu = ({
|
|
1512
1901
|
disabled: isDisabled,
|
1513
1902
|
size: "S",
|
1514
1903
|
endIcon: null,
|
1515
|
-
paddingTop: "
|
1516
|
-
paddingLeft: "
|
1517
|
-
paddingRight: "
|
1904
|
+
paddingTop: "4px",
|
1905
|
+
paddingLeft: "7px",
|
1906
|
+
paddingRight: "7px",
|
1518
1907
|
variant,
|
1519
1908
|
children: [
|
1520
1909
|
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
@@ -1525,7 +1914,7 @@ const DocumentActionsMenu = ({
|
|
1525
1914
|
]
|
1526
1915
|
}
|
1527
1916
|
),
|
1528
|
-
/* @__PURE__ */ jsxs(Menu.Content, {
|
1917
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1529
1918
|
actions2.map((action) => {
|
1530
1919
|
return /* @__PURE__ */ jsx(
|
1531
1920
|
Menu.Item,
|
@@ -1534,10 +1923,25 @@ const DocumentActionsMenu = ({
|
|
1534
1923
|
onSelect: handleClick(action),
|
1535
1924
|
display: "block",
|
1536
1925
|
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
|
1537
|
-
/* @__PURE__ */ jsxs(
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1926
|
+
/* @__PURE__ */ jsxs(
|
1927
|
+
Flex,
|
1928
|
+
{
|
1929
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1930
|
+
gap: 2,
|
1931
|
+
tag: "span",
|
1932
|
+
children: [
|
1933
|
+
/* @__PURE__ */ jsx(
|
1934
|
+
Flex,
|
1935
|
+
{
|
1936
|
+
tag: "span",
|
1937
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1938
|
+
children: action.icon
|
1939
|
+
}
|
1940
|
+
),
|
1941
|
+
action.label
|
1942
|
+
]
|
1943
|
+
}
|
1944
|
+
),
|
1541
1945
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
|
1542
1946
|
Flex,
|
1543
1947
|
{
|
@@ -1634,11 +2038,11 @@ const DocumentActionConfirmDialog = ({
|
|
1634
2038
|
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1635
2039
|
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1636
2040
|
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1637
|
-
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
2041
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1638
2042
|
id: "app.components.Button.cancel",
|
1639
2043
|
defaultMessage: "Cancel"
|
1640
2044
|
}) }) }),
|
1641
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2045
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1642
2046
|
id: "app.components.Button.confirm",
|
1643
2047
|
defaultMessage: "Confirm"
|
1644
2048
|
}) })
|
@@ -1661,10 +2065,22 @@ const DocumentActionModal = ({
|
|
1661
2065
|
};
|
1662
2066
|
return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
1663
2067
|
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
|
1664
|
-
|
1665
|
-
|
2068
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
|
2069
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1666
2070
|
] }) });
|
1667
2071
|
};
|
2072
|
+
const transformData = (data) => {
|
2073
|
+
if (Array.isArray(data)) {
|
2074
|
+
return data.map(transformData);
|
2075
|
+
}
|
2076
|
+
if (typeof data === "object" && data !== null) {
|
2077
|
+
if ("apiData" in data) {
|
2078
|
+
return data.apiData;
|
2079
|
+
}
|
2080
|
+
return mapValues(transformData)(data);
|
2081
|
+
}
|
2082
|
+
return data;
|
2083
|
+
};
|
1668
2084
|
const PublishAction$1 = ({
|
1669
2085
|
activeTab,
|
1670
2086
|
documentId,
|
@@ -1677,13 +2093,17 @@ const PublishAction$1 = ({
|
|
1677
2093
|
const navigate = useNavigate();
|
1678
2094
|
const { toggleNotification } = useNotification();
|
1679
2095
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2096
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
1680
2097
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
1681
2098
|
const { formatMessage } = useIntl();
|
1682
|
-
const { canPublish
|
1683
|
-
"PublishAction",
|
1684
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1685
|
-
);
|
2099
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1686
2100
|
const { publish } = useDocumentActions();
|
2101
|
+
const [
|
2102
|
+
countDraftRelations,
|
2103
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2104
|
+
] = useLazyGetDraftRelationCountQuery();
|
2105
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
2106
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1687
2107
|
const [{ query, rawQuery }] = useQueryParams();
|
1688
2108
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1689
2109
|
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1692,10 +2112,105 @@ const PublishAction$1 = ({
|
|
1692
2112
|
const validate = useForm("PublishAction", (state) => state.validate);
|
1693
2113
|
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1694
2114
|
const formValues = useForm("PublishAction", ({ values }) => values);
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
2115
|
+
React.useEffect(() => {
|
2116
|
+
if (isErrorDraftRelations) {
|
2117
|
+
toggleNotification({
|
2118
|
+
type: "danger",
|
2119
|
+
message: formatMessage({
|
2120
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2121
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2122
|
+
})
|
2123
|
+
});
|
2124
|
+
}
|
2125
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2126
|
+
React.useEffect(() => {
|
2127
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2128
|
+
const extractDraftRelations = (data) => {
|
2129
|
+
const relations = data.connect || [];
|
2130
|
+
relations.forEach((relation) => {
|
2131
|
+
if (relation.status === "draft") {
|
2132
|
+
localDraftRelations.add(relation.id);
|
2133
|
+
}
|
2134
|
+
});
|
2135
|
+
};
|
2136
|
+
const traverseAndExtract = (data) => {
|
2137
|
+
Object.entries(data).forEach(([key, value]) => {
|
2138
|
+
if (key === "connect" && Array.isArray(value)) {
|
2139
|
+
extractDraftRelations({ connect: value });
|
2140
|
+
} else if (typeof value === "object" && value !== null) {
|
2141
|
+
traverseAndExtract(value);
|
2142
|
+
}
|
2143
|
+
});
|
2144
|
+
};
|
2145
|
+
if (!documentId || modified) {
|
2146
|
+
traverseAndExtract(formValues);
|
2147
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2148
|
+
}
|
2149
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2150
|
+
React.useEffect(() => {
|
2151
|
+
if (!document || !document.documentId || isListView) {
|
2152
|
+
return;
|
2153
|
+
}
|
2154
|
+
const fetchDraftRelationsCount = async () => {
|
2155
|
+
const { data, error } = await countDraftRelations({
|
2156
|
+
collectionType,
|
2157
|
+
model,
|
2158
|
+
documentId,
|
2159
|
+
params
|
2160
|
+
});
|
2161
|
+
if (error) {
|
2162
|
+
throw error;
|
2163
|
+
}
|
2164
|
+
if (data) {
|
2165
|
+
setServerCountOfDraftRelations(data.data);
|
2166
|
+
}
|
2167
|
+
};
|
2168
|
+
fetchDraftRelationsCount();
|
2169
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2170
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
2171
|
+
if (!schema?.options?.draftAndPublish) {
|
2172
|
+
return null;
|
2173
|
+
}
|
2174
|
+
const performPublish = async () => {
|
2175
|
+
setSubmitting(true);
|
2176
|
+
try {
|
2177
|
+
const { errors } = await validate(true, {
|
2178
|
+
status: "published"
|
2179
|
+
});
|
2180
|
+
if (errors) {
|
2181
|
+
toggleNotification({
|
2182
|
+
type: "danger",
|
2183
|
+
message: formatMessage({
|
2184
|
+
id: "content-manager.validation.error",
|
2185
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2186
|
+
})
|
2187
|
+
});
|
2188
|
+
return;
|
2189
|
+
}
|
2190
|
+
const res = await publish(
|
2191
|
+
{
|
2192
|
+
collectionType,
|
2193
|
+
model,
|
2194
|
+
documentId,
|
2195
|
+
params
|
2196
|
+
},
|
2197
|
+
transformData(formValues)
|
2198
|
+
);
|
2199
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2200
|
+
navigate({
|
2201
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2202
|
+
search: rawQuery
|
2203
|
+
});
|
2204
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2205
|
+
setErrors(formatValidationErrors(res.error));
|
2206
|
+
}
|
2207
|
+
} finally {
|
2208
|
+
setSubmitting(false);
|
2209
|
+
}
|
2210
|
+
};
|
2211
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2212
|
+
const enableDraftRelationsCount = false;
|
2213
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1699
2214
|
return {
|
1700
2215
|
/**
|
1701
2216
|
* Disabled when:
|
@@ -1705,49 +2220,36 @@ const PublishAction$1 = ({
|
|
1705
2220
|
* - the document is already published & not modified
|
1706
2221
|
* - the document is being created & not modified
|
1707
2222
|
* - the user doesn't have the permission to publish
|
1708
|
-
* - the user doesn't have the permission to create a new document
|
1709
|
-
* - the user doesn't have the permission to update the document
|
1710
2223
|
*/
|
1711
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2224
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1712
2225
|
label: formatMessage({
|
1713
2226
|
id: "app.utils.publish",
|
1714
2227
|
defaultMessage: "Publish"
|
1715
2228
|
}),
|
1716
2229
|
onClick: async () => {
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
documentId,
|
1735
|
-
params
|
1736
|
-
},
|
1737
|
-
formValues
|
1738
|
-
);
|
1739
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1740
|
-
navigate({
|
1741
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1742
|
-
search: rawQuery
|
1743
|
-
});
|
1744
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1745
|
-
setErrors(formatValidationErrors(res.error));
|
2230
|
+
await performPublish();
|
2231
|
+
},
|
2232
|
+
dialog: hasDraftRelations ? {
|
2233
|
+
type: "dialog",
|
2234
|
+
variant: "danger",
|
2235
|
+
footer: null,
|
2236
|
+
title: formatMessage({
|
2237
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2238
|
+
defaultMessage: "Confirmation"
|
2239
|
+
}),
|
2240
|
+
content: formatMessage(
|
2241
|
+
{
|
2242
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2243
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2244
|
+
},
|
2245
|
+
{
|
2246
|
+
count: totalDraftRelations
|
1746
2247
|
}
|
1747
|
-
|
1748
|
-
|
2248
|
+
),
|
2249
|
+
onConfirm: async () => {
|
2250
|
+
await performPublish();
|
1749
2251
|
}
|
1750
|
-
}
|
2252
|
+
} : void 0
|
1751
2253
|
};
|
1752
2254
|
};
|
1753
2255
|
PublishAction$1.type = "publish";
|
@@ -1763,10 +2265,6 @@ const UpdateAction = ({
|
|
1763
2265
|
const cloneMatch = useMatch(CLONE_PATH);
|
1764
2266
|
const isCloning = cloneMatch !== null;
|
1765
2267
|
const { formatMessage } = useIntl();
|
1766
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1767
|
-
canCreate: canCreate2,
|
1768
|
-
canUpdate: canUpdate2
|
1769
|
-
}));
|
1770
2268
|
const { create, update, clone } = useDocumentActions();
|
1771
2269
|
const [{ query, rawQuery }] = useQueryParams();
|
1772
2270
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
@@ -1783,10 +2281,8 @@ const UpdateAction = ({
|
|
1783
2281
|
* - the form is submitting
|
1784
2282
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1785
2283
|
* - the active tab is the published tab
|
1786
|
-
* - the user doesn't have the permission to create a new document
|
1787
|
-
* - the user doesn't have the permission to update the document
|
1788
2284
|
*/
|
1789
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2285
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1790
2286
|
label: formatMessage({
|
1791
2287
|
id: "content-manager.containers.Edit.save",
|
1792
2288
|
defaultMessage: "Save"
|
@@ -1794,7 +2290,9 @@ const UpdateAction = ({
|
|
1794
2290
|
onClick: async () => {
|
1795
2291
|
setSubmitting(true);
|
1796
2292
|
try {
|
1797
|
-
const { errors } = await validate(
|
2293
|
+
const { errors } = await validate(true, {
|
2294
|
+
status: "draft"
|
2295
|
+
});
|
1798
2296
|
if (errors) {
|
1799
2297
|
toggleNotification({
|
1800
2298
|
type: "danger",
|
@@ -1812,13 +2310,16 @@ const UpdateAction = ({
|
|
1812
2310
|
documentId: cloneMatch.params.origin,
|
1813
2311
|
params
|
1814
2312
|
},
|
1815
|
-
document
|
2313
|
+
transformData(document)
|
1816
2314
|
);
|
1817
2315
|
if ("data" in res) {
|
1818
|
-
navigate(
|
1819
|
-
|
1820
|
-
|
1821
|
-
|
2316
|
+
navigate(
|
2317
|
+
{
|
2318
|
+
pathname: `../${res.data.documentId}`,
|
2319
|
+
search: rawQuery
|
2320
|
+
},
|
2321
|
+
{ relative: "path" }
|
2322
|
+
);
|
1822
2323
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1823
2324
|
setErrors(formatValidationErrors(res.error));
|
1824
2325
|
}
|
@@ -1830,7 +2331,7 @@ const UpdateAction = ({
|
|
1830
2331
|
documentId,
|
1831
2332
|
params
|
1832
2333
|
},
|
1833
|
-
document
|
2334
|
+
transformData(document)
|
1834
2335
|
);
|
1835
2336
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1836
2337
|
setErrors(formatValidationErrors(res.error));
|
@@ -1843,15 +2344,15 @@ const UpdateAction = ({
|
|
1843
2344
|
model,
|
1844
2345
|
params
|
1845
2346
|
},
|
1846
|
-
document
|
2347
|
+
transformData(document)
|
1847
2348
|
);
|
1848
2349
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1849
2350
|
navigate(
|
1850
2351
|
{
|
1851
|
-
pathname: `../${
|
2352
|
+
pathname: `../${res.data.documentId}`,
|
1852
2353
|
search: rawQuery
|
1853
2354
|
},
|
1854
|
-
{ replace: true }
|
2355
|
+
{ replace: true, relative: "path" }
|
1855
2356
|
);
|
1856
2357
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1857
2358
|
setErrors(formatValidationErrors(res.error));
|
@@ -1896,7 +2397,7 @@ const UnpublishAction$1 = ({
|
|
1896
2397
|
id: "app.utils.unpublish",
|
1897
2398
|
defaultMessage: "Unpublish"
|
1898
2399
|
}),
|
1899
|
-
icon: /* @__PURE__ */ jsx(
|
2400
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1900
2401
|
onClick: async () => {
|
1901
2402
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1902
2403
|
if (!documentId) {
|
@@ -2008,7 +2509,7 @@ const DiscardAction = ({
|
|
2008
2509
|
id: "content-manager.actions.discard.label",
|
2009
2510
|
defaultMessage: "Discard changes"
|
2010
2511
|
}),
|
2011
|
-
icon: /* @__PURE__ */ jsx(
|
2512
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2012
2513
|
position: ["panel", "table-row"],
|
2013
2514
|
variant: "danger",
|
2014
2515
|
dialog: {
|
@@ -2036,11 +2537,6 @@ const DiscardAction = ({
|
|
2036
2537
|
};
|
2037
2538
|
};
|
2038
2539
|
DiscardAction.type = "discard";
|
2039
|
-
const StyledCrossCircle = styled(CrossCircle)`
|
2040
|
-
path {
|
2041
|
-
fill: currentColor;
|
2042
|
-
}
|
2043
|
-
`;
|
2044
2540
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2045
2541
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2046
2542
|
const RelativeTime = React.forwardRef(
|
@@ -2088,8 +2584,12 @@ const getDisplayName = ({
|
|
2088
2584
|
};
|
2089
2585
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2090
2586
|
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2091
|
-
const statusVariant = status === "draft" ? "
|
2092
|
-
|
2587
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2588
|
+
const { formatMessage } = useIntl();
|
2589
|
+
return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2590
|
+
id: `content-manager.containers.List.${status}`,
|
2591
|
+
defaultMessage: capitalise(status)
|
2592
|
+
}) }) });
|
2093
2593
|
};
|
2094
2594
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2095
2595
|
const { formatMessage } = useIntl();
|
@@ -2098,23 +2598,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2098
2598
|
id: "content-manager.containers.edit.title.new",
|
2099
2599
|
defaultMessage: "Create an entry"
|
2100
2600
|
}) : documentTitle;
|
2101
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2601
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2102
2602
|
/* @__PURE__ */ jsx(BackButton, {}),
|
2103
|
-
/* @__PURE__ */ jsxs(
|
2104
|
-
|
2105
|
-
{
|
2106
|
-
|
2107
|
-
|
2108
|
-
paddingTop: 1,
|
2109
|
-
gap: "80px",
|
2110
|
-
alignItems: "flex-start",
|
2111
|
-
children: [
|
2112
|
-
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2113
|
-
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2114
|
-
]
|
2115
|
-
}
|
2116
|
-
),
|
2117
|
-
status ? /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2603
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2604
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2605
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2606
|
+
] }),
|
2607
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2118
2608
|
] });
|
2119
2609
|
};
|
2120
2610
|
const HeaderToolbar = () => {
|
@@ -2197,12 +2687,12 @@ const Information = ({ activeTab }) => {
|
|
2197
2687
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2198
2688
|
label: formatMessage({
|
2199
2689
|
id: "content-manager.containers.edit.information.last-published.label",
|
2200
|
-
defaultMessage: "
|
2690
|
+
defaultMessage: "Published"
|
2201
2691
|
}),
|
2202
2692
|
value: formatMessage(
|
2203
2693
|
{
|
2204
2694
|
id: "content-manager.containers.edit.information.last-published.value",
|
2205
|
-
defaultMessage: `
|
2695
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2206
2696
|
},
|
2207
2697
|
{
|
2208
2698
|
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2215,12 +2705,12 @@ const Information = ({ activeTab }) => {
|
|
2215
2705
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2216
2706
|
label: formatMessage({
|
2217
2707
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2218
|
-
defaultMessage: "
|
2708
|
+
defaultMessage: "Updated"
|
2219
2709
|
}),
|
2220
2710
|
value: formatMessage(
|
2221
2711
|
{
|
2222
2712
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2223
|
-
defaultMessage: `
|
2713
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2224
2714
|
},
|
2225
2715
|
{
|
2226
2716
|
time: /* @__PURE__ */ jsx(
|
@@ -2238,12 +2728,12 @@ const Information = ({ activeTab }) => {
|
|
2238
2728
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2239
2729
|
label: formatMessage({
|
2240
2730
|
id: "content-manager.containers.edit.information.document.label",
|
2241
|
-
defaultMessage: "
|
2731
|
+
defaultMessage: "Created"
|
2242
2732
|
}),
|
2243
2733
|
value: formatMessage(
|
2244
2734
|
{
|
2245
2735
|
id: "content-manager.containers.edit.information.document.value",
|
2246
|
-
defaultMessage: `
|
2736
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2247
2737
|
},
|
2248
2738
|
{
|
2249
2739
|
time: /* @__PURE__ */ jsx(
|
@@ -2281,25 +2771,77 @@ const Information = ({ activeTab }) => {
|
|
2281
2771
|
);
|
2282
2772
|
};
|
2283
2773
|
const HeaderActions = ({ actions: actions2 }) => {
|
2284
|
-
|
2285
|
-
|
2774
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2775
|
+
const handleClick = (action) => async (e) => {
|
2776
|
+
if (!("options" in action)) {
|
2777
|
+
const { onClick = () => false, dialog, id } = action;
|
2778
|
+
const muteDialog = await onClick(e);
|
2779
|
+
if (dialog && !muteDialog) {
|
2780
|
+
e.preventDefault();
|
2781
|
+
setDialogId(id);
|
2782
|
+
}
|
2783
|
+
}
|
2784
|
+
};
|
2785
|
+
const handleClose = () => {
|
2786
|
+
setDialogId(null);
|
2787
|
+
};
|
2788
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2789
|
+
if (action.options) {
|
2286
2790
|
return /* @__PURE__ */ jsx(
|
2287
2791
|
SingleSelect,
|
2288
2792
|
{
|
2289
2793
|
size: "S",
|
2290
|
-
disabled: action.disabled,
|
2291
|
-
"aria-label": action.label,
|
2292
2794
|
onChange: action.onSelect,
|
2293
|
-
|
2795
|
+
"aria-label": action.label,
|
2796
|
+
...action,
|
2294
2797
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2295
2798
|
},
|
2296
2799
|
action.id
|
2297
2800
|
);
|
2298
2801
|
} else {
|
2299
|
-
|
2802
|
+
if (action.type === "icon") {
|
2803
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2804
|
+
/* @__PURE__ */ jsx(
|
2805
|
+
IconButton,
|
2806
|
+
{
|
2807
|
+
disabled: action.disabled,
|
2808
|
+
label: action.label,
|
2809
|
+
size: "S",
|
2810
|
+
onClick: handleClick(action),
|
2811
|
+
children: action.icon
|
2812
|
+
}
|
2813
|
+
),
|
2814
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2815
|
+
HeaderActionDialog,
|
2816
|
+
{
|
2817
|
+
...action.dialog,
|
2818
|
+
isOpen: dialogId === action.id,
|
2819
|
+
onClose: handleClose
|
2820
|
+
}
|
2821
|
+
) : null
|
2822
|
+
] }, action.id);
|
2823
|
+
}
|
2300
2824
|
}
|
2301
2825
|
}) });
|
2302
2826
|
};
|
2827
|
+
const HeaderActionDialog = ({
|
2828
|
+
onClose,
|
2829
|
+
onCancel,
|
2830
|
+
title,
|
2831
|
+
content: Content,
|
2832
|
+
isOpen
|
2833
|
+
}) => {
|
2834
|
+
const handleClose = async () => {
|
2835
|
+
if (onCancel) {
|
2836
|
+
await onCancel();
|
2837
|
+
}
|
2838
|
+
onClose();
|
2839
|
+
};
|
2840
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2841
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2842
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2843
|
+
] }) });
|
2844
|
+
};
|
2303
2845
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2304
2846
|
const navigate = useNavigate();
|
2305
2847
|
const { formatMessage } = useIntl();
|
@@ -2340,12 +2882,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2340
2882
|
const { delete: deleteAction } = useDocumentActions();
|
2341
2883
|
const { toggleNotification } = useNotification();
|
2342
2884
|
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2885
|
+
const isLocalized = document?.locale != null;
|
2343
2886
|
return {
|
2344
2887
|
disabled: !canDelete || !document,
|
2345
|
-
label: formatMessage(
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2888
|
+
label: formatMessage(
|
2889
|
+
{
|
2890
|
+
id: "content-manager.actions.delete.label",
|
2891
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2892
|
+
},
|
2893
|
+
{ isLocalized }
|
2894
|
+
),
|
2349
2895
|
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2350
2896
|
dialog: {
|
2351
2897
|
type: "dialog",
|
@@ -2385,419 +2931,117 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2385
2931
|
params: {
|
2386
2932
|
locale: "*"
|
2387
2933
|
}
|
2388
|
-
});
|
2389
|
-
if (!("error" in res)) {
|
2390
|
-
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2391
|
-
}
|
2392
|
-
} finally {
|
2393
|
-
if (!listViewPathMatch) {
|
2394
|
-
setSubmitting(false);
|
2395
|
-
}
|
2396
|
-
}
|
2397
|
-
}
|
2398
|
-
},
|
2399
|
-
variant: "danger",
|
2400
|
-
position: ["header", "table-row"]
|
2401
|
-
};
|
2402
|
-
};
|
2403
|
-
DeleteAction$1.type = "delete";
|
2404
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2405
|
-
const Panels = () => {
|
2406
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2407
|
-
const [
|
2408
|
-
{
|
2409
|
-
query: { status }
|
2410
|
-
}
|
2411
|
-
] = useQueryParams({
|
2412
|
-
status: "draft"
|
2413
|
-
});
|
2414
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2415
|
-
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2416
|
-
const props = {
|
2417
|
-
activeTab: status,
|
2418
|
-
model,
|
2419
|
-
documentId: id,
|
2420
|
-
document: isCloning ? void 0 : document,
|
2421
|
-
meta: isCloning ? void 0 : meta,
|
2422
|
-
collectionType
|
2423
|
-
};
|
2424
|
-
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2425
|
-
DescriptionComponentRenderer,
|
2426
|
-
{
|
2427
|
-
props,
|
2428
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2429
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2430
|
-
}
|
2431
|
-
) });
|
2432
|
-
};
|
2433
|
-
const ActionsPanel = () => {
|
2434
|
-
const { formatMessage } = useIntl();
|
2435
|
-
return {
|
2436
|
-
title: formatMessage({
|
2437
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2438
|
-
defaultMessage: "Document"
|
2439
|
-
}),
|
2440
|
-
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2441
|
-
};
|
2442
|
-
};
|
2443
|
-
ActionsPanel.type = "actions";
|
2444
|
-
const ActionsPanelContent = () => {
|
2445
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2446
|
-
const [
|
2447
|
-
{
|
2448
|
-
query: { status = "draft" }
|
2449
|
-
}
|
2450
|
-
] = useQueryParams();
|
2451
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2452
|
-
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2453
|
-
const props = {
|
2454
|
-
activeTab: status,
|
2455
|
-
model,
|
2456
|
-
documentId: id,
|
2457
|
-
document: isCloning ? void 0 : document,
|
2458
|
-
meta: isCloning ? void 0 : meta,
|
2459
|
-
collectionType
|
2460
|
-
};
|
2461
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2462
|
-
/* @__PURE__ */ jsx(
|
2463
|
-
DescriptionComponentRenderer,
|
2464
|
-
{
|
2465
|
-
props,
|
2466
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2467
|
-
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2468
|
-
}
|
2469
|
-
),
|
2470
|
-
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2471
|
-
] });
|
2472
|
-
};
|
2473
|
-
const Panel = React.forwardRef(({ children, title }, ref) => {
|
2474
|
-
return /* @__PURE__ */ jsxs(
|
2475
|
-
Flex,
|
2476
|
-
{
|
2477
|
-
ref,
|
2478
|
-
tag: "aside",
|
2479
|
-
"aria-labelledby": "additional-information",
|
2480
|
-
background: "neutral0",
|
2481
|
-
borderColor: "neutral150",
|
2482
|
-
hasRadius: true,
|
2483
|
-
paddingBottom: 4,
|
2484
|
-
paddingLeft: 4,
|
2485
|
-
paddingRight: 4,
|
2486
|
-
paddingTop: 4,
|
2487
|
-
shadow: "tableShadow",
|
2488
|
-
gap: 3,
|
2489
|
-
direction: "column",
|
2490
|
-
justifyContent: "stretch",
|
2491
|
-
alignItems: "flex-start",
|
2492
|
-
children: [
|
2493
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2494
|
-
children
|
2495
|
-
]
|
2496
|
-
}
|
2497
|
-
);
|
2498
|
-
});
|
2499
|
-
const HOOKS = {
|
2500
|
-
/**
|
2501
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2502
|
-
* @constant
|
2503
|
-
* @type {string}
|
2504
|
-
*/
|
2505
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2506
|
-
/**
|
2507
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2508
|
-
* @constant
|
2509
|
-
* @type {string}
|
2510
|
-
*/
|
2511
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2512
|
-
/**
|
2513
|
-
* Hook that allows to mutate the CM's edit view layout
|
2514
|
-
* @constant
|
2515
|
-
* @type {string}
|
2516
|
-
*/
|
2517
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2518
|
-
/**
|
2519
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2520
|
-
* @constant
|
2521
|
-
* @type {string}
|
2522
|
-
*/
|
2523
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2524
|
-
};
|
2525
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2526
|
-
endpoints: (builder) => ({
|
2527
|
-
getContentTypeConfiguration: builder.query({
|
2528
|
-
query: (uid) => ({
|
2529
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2530
|
-
method: "GET"
|
2531
|
-
}),
|
2532
|
-
transformResponse: (response) => response.data,
|
2533
|
-
providesTags: (_result, _error, uid) => [
|
2534
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2535
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2536
|
-
]
|
2537
|
-
}),
|
2538
|
-
getAllContentTypeSettings: builder.query({
|
2539
|
-
query: () => "/content-manager/content-types-settings",
|
2540
|
-
transformResponse: (response) => response.data,
|
2541
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2542
|
-
}),
|
2543
|
-
updateContentTypeConfiguration: builder.mutation({
|
2544
|
-
query: ({ uid, ...body }) => ({
|
2545
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2546
|
-
method: "PUT",
|
2547
|
-
data: body
|
2548
|
-
}),
|
2549
|
-
transformResponse: (response) => response.data,
|
2550
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2551
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2552
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2553
|
-
// Is this necessary?
|
2554
|
-
{ type: "InitialData" }
|
2555
|
-
]
|
2556
|
-
})
|
2557
|
-
})
|
2558
|
-
});
|
2559
|
-
const {
|
2560
|
-
useGetContentTypeConfigurationQuery,
|
2561
|
-
useGetAllContentTypeSettingsQuery,
|
2562
|
-
useUpdateContentTypeConfigurationMutation
|
2563
|
-
} = contentTypesApi;
|
2564
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2565
|
-
const { type } = attribute;
|
2566
|
-
if (type === "relation") {
|
2567
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2568
|
-
}
|
2569
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2570
|
-
};
|
2571
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2572
|
-
if (!mainFieldName) {
|
2573
|
-
return void 0;
|
2574
|
-
}
|
2575
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2576
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2577
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2578
|
-
);
|
2579
|
-
return {
|
2580
|
-
name: mainFieldName,
|
2581
|
-
type: mainFieldType ?? "string"
|
2582
|
-
};
|
2583
|
-
};
|
2584
|
-
const DEFAULT_SETTINGS = {
|
2585
|
-
bulkable: false,
|
2586
|
-
filterable: false,
|
2587
|
-
searchable: false,
|
2588
|
-
pagination: false,
|
2589
|
-
defaultSortBy: "",
|
2590
|
-
defaultSortOrder: "asc",
|
2591
|
-
mainField: "id",
|
2592
|
-
pageSize: 10
|
2593
|
-
};
|
2594
|
-
const useDocumentLayout = (model) => {
|
2595
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2596
|
-
const [{ query }] = useQueryParams();
|
2597
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2598
|
-
const { toggleNotification } = useNotification();
|
2599
|
-
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2600
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2601
|
-
const {
|
2602
|
-
data,
|
2603
|
-
isLoading: isLoadingConfigs,
|
2604
|
-
error,
|
2605
|
-
isFetching: isFetchingConfigs
|
2606
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2607
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2608
|
-
React.useEffect(() => {
|
2609
|
-
if (error) {
|
2610
|
-
toggleNotification({
|
2611
|
-
type: "danger",
|
2612
|
-
message: formatAPIError(error)
|
2613
|
-
});
|
2614
|
-
}
|
2615
|
-
}, [error, formatAPIError, toggleNotification]);
|
2616
|
-
const editLayout = React.useMemo(
|
2617
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2618
|
-
layout: [],
|
2619
|
-
components: {},
|
2620
|
-
metadatas: {},
|
2621
|
-
options: {},
|
2622
|
-
settings: DEFAULT_SETTINGS
|
2623
|
-
},
|
2624
|
-
[data, isLoading, schemas, schema, components]
|
2625
|
-
);
|
2626
|
-
const listLayout = React.useMemo(() => {
|
2627
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2628
|
-
layout: [],
|
2629
|
-
metadatas: {},
|
2630
|
-
options: {},
|
2631
|
-
settings: DEFAULT_SETTINGS
|
2632
|
-
};
|
2633
|
-
}, [data, isLoading, schemas, schema, components]);
|
2634
|
-
const { layout: edit } = React.useMemo(
|
2635
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2636
|
-
layout: editLayout,
|
2637
|
-
query
|
2638
|
-
}),
|
2639
|
-
[editLayout, query, runHookWaterfall]
|
2640
|
-
);
|
2641
|
-
return {
|
2642
|
-
error,
|
2643
|
-
isLoading,
|
2644
|
-
edit,
|
2645
|
-
list: listLayout
|
2646
|
-
};
|
2647
|
-
};
|
2648
|
-
const useDocLayout = () => {
|
2649
|
-
const { model } = useDoc();
|
2650
|
-
return useDocumentLayout(model);
|
2651
|
-
};
|
2652
|
-
const formatEditLayout = (data, {
|
2653
|
-
schemas,
|
2654
|
-
schema,
|
2655
|
-
components
|
2656
|
-
}) => {
|
2657
|
-
let currentPanelIndex = 0;
|
2658
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2659
|
-
data.contentType.layouts.edit,
|
2660
|
-
schema?.attributes,
|
2661
|
-
data.contentType.metadatas,
|
2662
|
-
{ configurations: data.components, schemas: components },
|
2663
|
-
schemas
|
2664
|
-
).reduce((panels, row) => {
|
2665
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2666
|
-
panels.push([row]);
|
2667
|
-
currentPanelIndex += 2;
|
2668
|
-
} else {
|
2669
|
-
if (!panels[currentPanelIndex]) {
|
2670
|
-
panels.push([]);
|
2671
|
-
}
|
2672
|
-
panels[currentPanelIndex].push(row);
|
2673
|
-
}
|
2674
|
-
return panels;
|
2675
|
-
}, []);
|
2676
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2677
|
-
(acc, [uid, configuration]) => {
|
2678
|
-
acc[uid] = {
|
2679
|
-
layout: convertEditLayoutToFieldLayouts(
|
2680
|
-
configuration.layouts.edit,
|
2681
|
-
components[uid].attributes,
|
2682
|
-
configuration.metadatas
|
2683
|
-
),
|
2684
|
-
settings: {
|
2685
|
-
...configuration.settings,
|
2686
|
-
icon: components[uid].info.icon,
|
2687
|
-
displayName: components[uid].info.displayName
|
2688
|
-
}
|
2689
|
-
};
|
2690
|
-
return acc;
|
2691
|
-
},
|
2692
|
-
{}
|
2693
|
-
);
|
2694
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2695
|
-
(acc, [attribute, metadata]) => {
|
2696
|
-
return {
|
2697
|
-
...acc,
|
2698
|
-
[attribute]: metadata.edit
|
2699
|
-
};
|
2700
|
-
},
|
2701
|
-
{}
|
2702
|
-
);
|
2703
|
-
return {
|
2704
|
-
layout: panelledEditAttributes,
|
2705
|
-
components: componentEditAttributes,
|
2706
|
-
metadatas: editMetadatas,
|
2707
|
-
settings: {
|
2708
|
-
...data.contentType.settings,
|
2709
|
-
displayName: schema?.info.displayName
|
2934
|
+
});
|
2935
|
+
if (!("error" in res)) {
|
2936
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2937
|
+
}
|
2938
|
+
} finally {
|
2939
|
+
if (!listViewPathMatch) {
|
2940
|
+
setSubmitting(false);
|
2941
|
+
}
|
2942
|
+
}
|
2943
|
+
}
|
2710
2944
|
},
|
2711
|
-
|
2712
|
-
|
2713
|
-
...schema?.pluginOptions,
|
2714
|
-
...data.contentType.options
|
2715
|
-
}
|
2945
|
+
variant: "danger",
|
2946
|
+
position: ["header", "table-row"]
|
2716
2947
|
};
|
2717
2948
|
};
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
|
2724
|
-
}
|
2725
|
-
|
2726
|
-
|
2727
|
-
|
2728
|
-
|
2729
|
-
|
2730
|
-
|
2731
|
-
|
2732
|
-
|
2733
|
-
|
2734
|
-
|
2735
|
-
|
2736
|
-
|
2737
|
-
|
2738
|
-
|
2739
|
-
|
2740
|
-
|
2741
|
-
|
2742
|
-
|
2743
|
-
|
2744
|
-
}
|
2745
|
-
}
|
2746
|
-
);
|
2949
|
+
DeleteAction$1.type = "delete";
|
2950
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2951
|
+
const Panels = () => {
|
2952
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2953
|
+
const [
|
2954
|
+
{
|
2955
|
+
query: { status }
|
2956
|
+
}
|
2957
|
+
] = useQueryParams({
|
2958
|
+
status: "draft"
|
2959
|
+
});
|
2960
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2961
|
+
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2962
|
+
const props = {
|
2963
|
+
activeTab: status,
|
2964
|
+
model,
|
2965
|
+
documentId: id,
|
2966
|
+
document: isCloning ? void 0 : document,
|
2967
|
+
meta: isCloning ? void 0 : meta,
|
2968
|
+
collectionType
|
2969
|
+
};
|
2970
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2971
|
+
DescriptionComponentRenderer,
|
2972
|
+
{
|
2973
|
+
props,
|
2974
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2975
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2976
|
+
}
|
2977
|
+
) });
|
2747
2978
|
};
|
2748
|
-
const
|
2749
|
-
|
2750
|
-
schema,
|
2751
|
-
components
|
2752
|
-
}) => {
|
2753
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2754
|
-
(acc, [attribute, metadata]) => {
|
2755
|
-
return {
|
2756
|
-
...acc,
|
2757
|
-
[attribute]: metadata.list
|
2758
|
-
};
|
2759
|
-
},
|
2760
|
-
{}
|
2761
|
-
);
|
2762
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2763
|
-
data.contentType.layouts.list,
|
2764
|
-
schema?.attributes,
|
2765
|
-
listMetadatas,
|
2766
|
-
{ configurations: data.components, schemas: components },
|
2767
|
-
schemas
|
2768
|
-
);
|
2979
|
+
const ActionsPanel = () => {
|
2980
|
+
const { formatMessage } = useIntl();
|
2769
2981
|
return {
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
|
2775
|
-
...schema?.pluginOptions,
|
2776
|
-
...data.contentType.options
|
2777
|
-
}
|
2982
|
+
title: formatMessage({
|
2983
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2984
|
+
defaultMessage: "Entry"
|
2985
|
+
}),
|
2986
|
+
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2778
2987
|
};
|
2779
2988
|
};
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2989
|
+
ActionsPanel.type = "actions";
|
2990
|
+
const ActionsPanelContent = () => {
|
2991
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2992
|
+
const [
|
2993
|
+
{
|
2994
|
+
query: { status = "draft" }
|
2785
2995
|
}
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
|
2996
|
+
] = useQueryParams();
|
2997
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2998
|
+
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2999
|
+
const props = {
|
3000
|
+
activeTab: status,
|
3001
|
+
model,
|
3002
|
+
documentId: id,
|
3003
|
+
document: isCloning ? void 0 : document,
|
3004
|
+
meta: isCloning ? void 0 : meta,
|
3005
|
+
collectionType
|
3006
|
+
};
|
3007
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3008
|
+
/* @__PURE__ */ jsx(
|
3009
|
+
DescriptionComponentRenderer,
|
3010
|
+
{
|
3011
|
+
props,
|
3012
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3013
|
+
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
3014
|
+
}
|
3015
|
+
),
|
3016
|
+
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3017
|
+
] });
|
2800
3018
|
};
|
3019
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
3020
|
+
return /* @__PURE__ */ jsxs(
|
3021
|
+
Flex,
|
3022
|
+
{
|
3023
|
+
ref,
|
3024
|
+
tag: "aside",
|
3025
|
+
"aria-labelledby": "additional-information",
|
3026
|
+
background: "neutral0",
|
3027
|
+
borderColor: "neutral150",
|
3028
|
+
hasRadius: true,
|
3029
|
+
paddingBottom: 4,
|
3030
|
+
paddingLeft: 4,
|
3031
|
+
paddingRight: 4,
|
3032
|
+
paddingTop: 4,
|
3033
|
+
shadow: "tableShadow",
|
3034
|
+
gap: 3,
|
3035
|
+
direction: "column",
|
3036
|
+
justifyContent: "stretch",
|
3037
|
+
alignItems: "flex-start",
|
3038
|
+
children: [
|
3039
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3040
|
+
children
|
3041
|
+
]
|
3042
|
+
}
|
3043
|
+
);
|
3044
|
+
});
|
2801
3045
|
const ConfirmBulkActionDialog = ({
|
2802
3046
|
onToggleDialog,
|
2803
3047
|
isOpen = false,
|
@@ -2805,7 +3049,7 @@ const ConfirmBulkActionDialog = ({
|
|
2805
3049
|
endAction
|
2806
3050
|
}) => {
|
2807
3051
|
const { formatMessage } = useIntl();
|
2808
|
-
return /* @__PURE__ */ jsx(Dialog.Root, {
|
3052
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2809
3053
|
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
|
2810
3054
|
id: "app.components.ConfirmDialog.title",
|
2811
3055
|
defaultMessage: "Confirmation"
|
@@ -2836,6 +3080,7 @@ const ConfirmDialogPublishAll = ({
|
|
2836
3080
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2837
3081
|
const { model, schema } = useDoc();
|
2838
3082
|
const [{ query }] = useQueryParams();
|
3083
|
+
const enableDraftRelationsCount = false;
|
2839
3084
|
const {
|
2840
3085
|
data: countDraftRelations = 0,
|
2841
3086
|
isLoading,
|
@@ -2847,7 +3092,7 @@ const ConfirmDialogPublishAll = ({
|
|
2847
3092
|
locale: query?.plugins?.i18n?.locale
|
2848
3093
|
},
|
2849
3094
|
{
|
2850
|
-
skip:
|
3095
|
+
skip: !enableDraftRelationsCount
|
2851
3096
|
}
|
2852
3097
|
);
|
2853
3098
|
React.useEffect(() => {
|
@@ -3032,7 +3277,7 @@ const SelectedEntriesTableContent = ({
|
|
3032
3277
|
status: row.status
|
3033
3278
|
}
|
3034
3279
|
) }),
|
3035
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3280
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3036
3281
|
IconButton,
|
3037
3282
|
{
|
3038
3283
|
tag: Link,
|
@@ -3055,9 +3300,10 @@ const SelectedEntriesTableContent = ({
|
|
3055
3300
|
),
|
3056
3301
|
target: "_blank",
|
3057
3302
|
marginLeft: "auto",
|
3058
|
-
|
3303
|
+
variant: "ghost",
|
3304
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3059
3305
|
}
|
3060
|
-
) })
|
3306
|
+
) }) })
|
3061
3307
|
] }, row.id)) })
|
3062
3308
|
] });
|
3063
3309
|
};
|
@@ -3094,7 +3340,13 @@ const SelectedEntriesModalContent = ({
|
|
3094
3340
|
);
|
3095
3341
|
const { rows, validationErrors } = React.useMemo(() => {
|
3096
3342
|
if (data.length > 0 && schema) {
|
3097
|
-
const validate = createYupSchema(
|
3343
|
+
const validate = createYupSchema(
|
3344
|
+
schema.attributes,
|
3345
|
+
components,
|
3346
|
+
// Since this is the "Publish" action, the validation
|
3347
|
+
// schema must enforce the rules for published entities
|
3348
|
+
{ status: "published" }
|
3349
|
+
);
|
3098
3350
|
const validationErrors2 = {};
|
3099
3351
|
const rows2 = data.map((entry) => {
|
3100
3352
|
try {
|
@@ -3444,7 +3696,7 @@ const TableActions = ({ document }) => {
|
|
3444
3696
|
DescriptionComponentRenderer,
|
3445
3697
|
{
|
3446
3698
|
props,
|
3447
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3699
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3448
3700
|
children: (actions2) => {
|
3449
3701
|
const tableRowActions = actions2.filter((action) => {
|
3450
3702
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3555,7 +3807,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3555
3807
|
}),
|
3556
3808
|
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3557
3809
|
footer: ({ onClose }) => {
|
3558
|
-
return /* @__PURE__ */ jsxs(
|
3810
|
+
return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3559
3811
|
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3560
3812
|
id: "cancel",
|
3561
3813
|
defaultMessage: "Cancel"
|
@@ -3596,8 +3848,7 @@ class ContentManagerPlugin {
|
|
3596
3848
|
documentActions = [
|
3597
3849
|
...DEFAULT_ACTIONS,
|
3598
3850
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3599
|
-
...DEFAULT_HEADER_ACTIONS
|
3600
|
-
HistoryAction
|
3851
|
+
...DEFAULT_HEADER_ACTIONS
|
3601
3852
|
];
|
3602
3853
|
editViewSidePanels = [ActionsPanel];
|
3603
3854
|
headerActions = [];
|
@@ -3686,6 +3937,52 @@ const getPrintableType = (value) => {
|
|
3686
3937
|
}
|
3687
3938
|
return nativeType;
|
3688
3939
|
};
|
3940
|
+
const HistoryAction = ({ model, document }) => {
|
3941
|
+
const { formatMessage } = useIntl();
|
3942
|
+
const [{ query }] = useQueryParams();
|
3943
|
+
const navigate = useNavigate();
|
3944
|
+
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3945
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3946
|
+
return null;
|
3947
|
+
}
|
3948
|
+
return {
|
3949
|
+
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3950
|
+
label: formatMessage({
|
3951
|
+
id: "content-manager.history.document-action",
|
3952
|
+
defaultMessage: "Content History"
|
3953
|
+
}),
|
3954
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3955
|
+
disabled: (
|
3956
|
+
/**
|
3957
|
+
* The user is creating a new document.
|
3958
|
+
* It hasn't been saved yet, so there's no history to go to
|
3959
|
+
*/
|
3960
|
+
!document || /**
|
3961
|
+
* The document has been created but the current dimension has never been saved.
|
3962
|
+
* For example, the user is creating a new locale in an existing document,
|
3963
|
+
* so there's no history for the document in that locale
|
3964
|
+
*/
|
3965
|
+
!document.id || /**
|
3966
|
+
* History is only available for content types created by the user.
|
3967
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3968
|
+
* which start with `admin::` or `plugin::`
|
3969
|
+
*/
|
3970
|
+
!model.startsWith("api::")
|
3971
|
+
),
|
3972
|
+
position: "header"
|
3973
|
+
};
|
3974
|
+
};
|
3975
|
+
HistoryAction.type = "history";
|
3976
|
+
const historyAdmin = {
|
3977
|
+
bootstrap(app) {
|
3978
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3979
|
+
addDocumentAction((actions2) => {
|
3980
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3981
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3982
|
+
return actions2;
|
3983
|
+
});
|
3984
|
+
}
|
3985
|
+
};
|
3689
3986
|
const initialState = {
|
3690
3987
|
collectionTypeLinks: [],
|
3691
3988
|
components: [],
|
@@ -3722,6 +4019,70 @@ const { setInitialData } = actions;
|
|
3722
4019
|
const reducer = combineReducers({
|
3723
4020
|
app: reducer$1
|
3724
4021
|
});
|
4022
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4023
|
+
endpoints: (builder) => ({
|
4024
|
+
getPreviewUrl: builder.query({
|
4025
|
+
query({ query, params }) {
|
4026
|
+
return {
|
4027
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4028
|
+
method: "GET",
|
4029
|
+
config: {
|
4030
|
+
params: query
|
4031
|
+
}
|
4032
|
+
};
|
4033
|
+
}
|
4034
|
+
})
|
4035
|
+
})
|
4036
|
+
});
|
4037
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4038
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4039
|
+
const { formatMessage } = useIntl();
|
4040
|
+
const { trackUsage } = useTracking();
|
4041
|
+
const [{ query }] = useQueryParams();
|
4042
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4043
|
+
params: {
|
4044
|
+
contentType: model
|
4045
|
+
},
|
4046
|
+
query: {
|
4047
|
+
documentId,
|
4048
|
+
locale: document?.locale,
|
4049
|
+
status: document?.status
|
4050
|
+
}
|
4051
|
+
});
|
4052
|
+
if (!data?.data?.url || error) {
|
4053
|
+
return null;
|
4054
|
+
}
|
4055
|
+
const handleClick = () => {
|
4056
|
+
trackUsage("willOpenPreview");
|
4057
|
+
};
|
4058
|
+
return {
|
4059
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4060
|
+
content: /* @__PURE__ */ jsx(Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsx(
|
4061
|
+
Button,
|
4062
|
+
{
|
4063
|
+
variant: "tertiary",
|
4064
|
+
tag: Link,
|
4065
|
+
to: { pathname: "preview", search: stringify(query, { encode: false }) },
|
4066
|
+
onClick: handleClick,
|
4067
|
+
flex: "auto",
|
4068
|
+
children: formatMessage({
|
4069
|
+
id: "content-manager.preview.panel.button",
|
4070
|
+
defaultMessage: "Open preview"
|
4071
|
+
})
|
4072
|
+
}
|
4073
|
+
) })
|
4074
|
+
};
|
4075
|
+
};
|
4076
|
+
const FEATURE_ID = "preview";
|
4077
|
+
const previewAdmin = {
|
4078
|
+
bootstrap(app) {
|
4079
|
+
if (!window.strapi.future.isEnabled(FEATURE_ID)) {
|
4080
|
+
return;
|
4081
|
+
}
|
4082
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4083
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4084
|
+
}
|
4085
|
+
};
|
3725
4086
|
const index = {
|
3726
4087
|
register(app) {
|
3727
4088
|
const cm = new ContentManagerPlugin();
|
@@ -3741,7 +4102,7 @@ const index = {
|
|
3741
4102
|
app.router.addRoute({
|
3742
4103
|
path: "content-manager/*",
|
3743
4104
|
lazy: async () => {
|
3744
|
-
const { Layout } = await import("./layout-
|
4105
|
+
const { Layout } = await import("./layout-Btu_cMRF.mjs");
|
3745
4106
|
return {
|
3746
4107
|
Component: Layout
|
3747
4108
|
};
|
@@ -3750,10 +4111,18 @@ const index = {
|
|
3750
4111
|
});
|
3751
4112
|
app.registerPlugin(cm.config);
|
3752
4113
|
},
|
4114
|
+
bootstrap(app) {
|
4115
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4116
|
+
historyAdmin.bootstrap(app);
|
4117
|
+
}
|
4118
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4119
|
+
previewAdmin.bootstrap(app);
|
4120
|
+
}
|
4121
|
+
},
|
3753
4122
|
async registerTrads({ locales }) {
|
3754
4123
|
const importedTrads = await Promise.all(
|
3755
4124
|
locales.map((locale) => {
|
3756
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-
|
4125
|
+
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-D_BMf0hT.mjs"), "./translations/es.json": () => import("./es-D34tqjMw.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr--pg5jUbt.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-BHqhDq4V.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
|
3757
4126
|
return {
|
3758
4127
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3759
4128
|
locale
|
@@ -3774,13 +4143,16 @@ export {
|
|
3774
4143
|
BulkActionsRenderer as B,
|
3775
4144
|
COLLECTION_TYPES as C,
|
3776
4145
|
DocumentStatus as D,
|
3777
|
-
|
3778
|
-
|
3779
|
-
|
4146
|
+
extractContentTypeComponents as E,
|
4147
|
+
DEFAULT_SETTINGS as F,
|
4148
|
+
convertEditLayoutToFieldLayouts as G,
|
3780
4149
|
HOOKS as H,
|
3781
4150
|
InjectionZone as I,
|
3782
|
-
|
3783
|
-
|
4151
|
+
useDocument as J,
|
4152
|
+
useGetPreviewUrlQuery as K,
|
4153
|
+
index as L,
|
4154
|
+
useContentManagerContext as M,
|
4155
|
+
useDocumentActions as N,
|
3784
4156
|
Panels as P,
|
3785
4157
|
RelativeTime as R,
|
3786
4158
|
SINGLE_TYPES as S,
|
@@ -3798,18 +4170,18 @@ export {
|
|
3798
4170
|
PERMISSIONS as k,
|
3799
4171
|
DocumentRBAC as l,
|
3800
4172
|
DOCUMENT_META_FIELDS as m,
|
3801
|
-
|
3802
|
-
|
3803
|
-
|
3804
|
-
|
3805
|
-
|
4173
|
+
CLONE_PATH as n,
|
4174
|
+
useDocLayout as o,
|
4175
|
+
useGetContentTypeConfigurationQuery as p,
|
4176
|
+
CREATOR_FIELDS as q,
|
4177
|
+
getMainField as r,
|
3806
4178
|
setInitialData as s,
|
3807
|
-
|
4179
|
+
getDisplayName as t,
|
3808
4180
|
useContentTypeSchema as u,
|
3809
|
-
|
3810
|
-
|
3811
|
-
|
3812
|
-
|
3813
|
-
|
4181
|
+
checkIfAttributeIsDisplayable as v,
|
4182
|
+
useGetAllDocumentsQuery as w,
|
4183
|
+
convertListLayoutToFieldLayouts as x,
|
4184
|
+
capitalise as y,
|
4185
|
+
useUpdateContentTypeConfigurationMutation as z
|
3814
4186
|
};
|
3815
|
-
//# sourceMappingURL=index-
|
4187
|
+
//# sourceMappingURL=index-CbytGVdz.mjs.map
|