@strapi/content-manager 0.0.0-experimental.f31889311d753b5f7d95198ae84d8fce1d156cd6 → 0.0.0-experimental.f49f46a1c17445a39e8af3f63124bcccf73842e6
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-BNxtMIfV.js → ComponentConfigurationPage-ClKl_TA2.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BNxtMIfV.js.map → ComponentConfigurationPage-ClKl_TA2.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BWOQWCv2.mjs → ComponentConfigurationPage-D3ZWDAHG.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BWOQWCv2.mjs.map → ComponentConfigurationPage-D3ZWDAHG.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-GTp-Ucnw.mjs → EditConfigurationPage-BYCBSJxP.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-GTp-Ucnw.mjs.map → EditConfigurationPage-BYCBSJxP.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-D340bYlT.js → EditConfigurationPage-OWez0Kxp.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-D340bYlT.js.map → EditConfigurationPage-OWez0Kxp.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-BVMS5hT-.mjs → EditViewPage-5pdbvsO_.mjs} +63 -12
- package/dist/_chunks/EditViewPage-5pdbvsO_.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-CXkmnAvI.js → EditViewPage-BEs5iGDi.js} +62 -11
- package/dist/_chunks/EditViewPage-BEs5iGDi.js.map +1 -0
- package/dist/_chunks/{Field-Ibi32diw.js → Field-DNHm4wHx.js} +210 -119
- package/dist/_chunks/Field-DNHm4wHx.js.map +1 -0
- package/dist/_chunks/{Field-nNgv5bpd.mjs → Field-DcKuFHYK.mjs} +208 -117
- package/dist/_chunks/Field-DcKuFHYK.mjs.map +1 -0
- package/dist/_chunks/{Form-DodJsI2A.mjs → Form-CGwM_-5c.mjs} +36 -17
- package/dist/_chunks/Form-CGwM_-5c.mjs.map +1 -0
- package/dist/_chunks/{Form-Dhnh34ym.js → Form-CoRxWJOz.js} +36 -17
- package/dist/_chunks/Form-CoRxWJOz.js.map +1 -0
- package/dist/_chunks/{History-C9auUkDi.js → History-BcUTQrfG.js} +40 -97
- package/dist/_chunks/History-BcUTQrfG.js.map +1 -0
- package/dist/_chunks/{History-CKCSQXz_.mjs → History-DEvr3Q_V.mjs} +42 -99
- package/dist/_chunks/History-DEvr3Q_V.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Bg4rWUjX.js → ListConfigurationPage-BE_Ho7tV.js} +17 -6
- package/dist/_chunks/ListConfigurationPage-BE_Ho7tV.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-CKEC4ttG.mjs → ListConfigurationPage-BM4zZZcM.mjs} +18 -7
- package/dist/_chunks/ListConfigurationPage-BM4zZZcM.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-B7_WJUjG.mjs → ListViewPage-BK2mkrql.mjs} +65 -39
- package/dist/_chunks/ListViewPage-BK2mkrql.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-C2gIeYHG.js → ListViewPage-BkT8Eao0.js} +68 -42
- package/dist/_chunks/ListViewPage-BkT8Eao0.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-Ckem6Ll6.mjs → NoContentTypePage-BvcAutu9.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-Ckem6Ll6.mjs.map → NoContentTypePage-BvcAutu9.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-DqgdUfyn.js → NoContentTypePage-C8mtyc4H.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-DqgdUfyn.js.map → NoContentTypePage-C8mtyc4H.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-CF29Q-sW.js → NoPermissionsPage-B5Y9Y78B.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-CF29Q-sW.js.map → NoPermissionsPage-B5Y9Y78B.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BO-GEjA4.mjs → NoPermissionsPage-BmbRz7PR.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BO-GEjA4.mjs.map → NoPermissionsPage-BmbRz7PR.mjs.map} +1 -1
- package/dist/_chunks/Preview-BF8ZDYqS.js +286 -0
- package/dist/_chunks/Preview-BF8ZDYqS.js.map +1 -0
- package/dist/_chunks/Preview-DcexhKJE.mjs +267 -0
- package/dist/_chunks/Preview-DcexhKJE.mjs.map +1 -0
- package/dist/_chunks/{Relations-C0uC9J4f.js → Relations-BKnoK1R0.js} +72 -36
- package/dist/_chunks/Relations-BKnoK1R0.js.map +1 -0
- package/dist/_chunks/{Relations-DItV5eow.mjs → Relations-BjIzc4EK.mjs} +73 -37
- package/dist/_chunks/Relations-BjIzc4EK.mjs.map +1 -0
- package/dist/_chunks/{en-BrCTWlZv.mjs → en-CfIXaZf9.mjs} +26 -14
- package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-CfIXaZf9.mjs.map} +1 -1
- package/dist/_chunks/{en-uOUIxfcQ.js → en-DTWPCdTS.js} +26 -14
- package/dist/_chunks/{en-uOUIxfcQ.js.map → en-DTWPCdTS.js.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/{index-DrNe6ctw.mjs → index-BW-rXkjn.mjs} +1027 -761
- package/dist/_chunks/index-BW-rXkjn.mjs.map +1 -0
- package/dist/_chunks/{index-Dd0nXyJF.js → index-DOzAG2cq.js} +1008 -741
- package/dist/_chunks/index-DOzAG2cq.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-B3ez7kvr.mjs → layout-DFVbgjp2.mjs} +8 -7
- package/dist/_chunks/layout-DFVbgjp2.mjs.map +1 -0
- package/dist/_chunks/{layout-CLLtt_5O.js → layout-RC3W2obV.js} +8 -7
- package/dist/_chunks/layout-RC3W2obV.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-B0hlsUU_.mjs → relations-Dogh8HWI.mjs} +6 -7
- package/dist/_chunks/relations-Dogh8HWI.mjs.map +1 -0
- package/dist/_chunks/{relations-bRxcNv1q.js → relations-zam7-5H7.js} +6 -7
- package/dist/_chunks/relations-zam7-5H7.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/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/constants.d.ts +1 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/router.d.ts +1 -1
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +19 -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 +421 -183
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +421 -183
- 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/utils/metadata.d.ts +15 -1
- package/dist/server/src/controllers/utils/metadata.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 +3 -3
- 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/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/preview.d.ts +27 -0
- package/dist/shared/contracts/preview.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +4 -0
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +14 -14
- package/dist/_chunks/EditViewPage-BVMS5hT-.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-CXkmnAvI.js.map +0 -1
- package/dist/_chunks/Field-Ibi32diw.js.map +0 -1
- package/dist/_chunks/Field-nNgv5bpd.mjs.map +0 -1
- package/dist/_chunks/Form-Dhnh34ym.js.map +0 -1
- package/dist/_chunks/Form-DodJsI2A.mjs.map +0 -1
- package/dist/_chunks/History-C9auUkDi.js.map +0 -1
- package/dist/_chunks/History-CKCSQXz_.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Bg4rWUjX.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-CKEC4ttG.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-B7_WJUjG.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-C2gIeYHG.js.map +0 -1
- package/dist/_chunks/Relations-C0uC9J4f.js.map +0 -1
- package/dist/_chunks/Relations-DItV5eow.mjs.map +0 -1
- package/dist/_chunks/index-Dd0nXyJF.js.map +0 -1
- package/dist/_chunks/index-DrNe6ctw.mjs.map +0 -1
- package/dist/_chunks/layout-B3ez7kvr.mjs.map +0 -1
- package/dist/_chunks/layout-CLLtt_5O.js.map +0 -1
- package/dist/_chunks/relations-B0hlsUU_.mjs.map +0 -1
- package/dist/_chunks/relations-bRxcNv1q.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,11 +1,12 @@
|
|
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, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors,
|
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";
|
4
4
|
import * as React from "react";
|
5
5
|
import { lazy } from "react";
|
6
|
-
import {
|
6
|
+
import { Menu, Button, VisuallyHidden, Flex, Dialog, Modal, Typography, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
|
7
|
+
import mapValues from "lodash/fp/mapValues";
|
7
8
|
import { useIntl } from "react-intl";
|
8
|
-
import { useParams,
|
9
|
+
import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
|
9
10
|
import { styled } from "styled-components";
|
10
11
|
import * as yup from "yup";
|
11
12
|
import { ValidationError } from "yup";
|
@@ -100,6 +101,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
100
101
|
if (!slug) {
|
101
102
|
throw new Error("Cannot find the slug param in the URL");
|
102
103
|
}
|
104
|
+
const [{ rawQuery }] = useQueryParams();
|
103
105
|
const userPermissions = useAuth("DocumentRBAC", (state) => state.permissions);
|
104
106
|
const contentTypePermissions = React.useMemo(() => {
|
105
107
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -110,7 +112,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
110
112
|
return { ...acc, [action]: [permission] };
|
111
113
|
}, {});
|
112
114
|
}, [slug, userPermissions]);
|
113
|
-
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
|
+
);
|
114
123
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
115
124
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
116
125
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -158,7 +167,8 @@ const contentManagerApi = adminApi.enhanceEndpoints({
|
|
158
167
|
"Document",
|
159
168
|
"InitialData",
|
160
169
|
"HistoryVersion",
|
161
|
-
"Relations"
|
170
|
+
"Relations",
|
171
|
+
"UidAvailability"
|
162
172
|
]
|
163
173
|
});
|
164
174
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -188,7 +198,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
188
198
|
params
|
189
199
|
}
|
190
200
|
}),
|
191
|
-
invalidatesTags: (_result, _error, { model }) => [
|
201
|
+
invalidatesTags: (_result, _error, { model }) => [
|
202
|
+
{ type: "Document", id: `${model}_LIST` },
|
203
|
+
{ type: "UidAvailability", id: model }
|
204
|
+
]
|
192
205
|
}),
|
193
206
|
/**
|
194
207
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -205,7 +218,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
205
218
|
}),
|
206
219
|
invalidatesTags: (result, _error, { model }) => [
|
207
220
|
{ type: "Document", id: `${model}_LIST` },
|
208
|
-
"Relations"
|
221
|
+
"Relations",
|
222
|
+
{ type: "UidAvailability", id: model }
|
209
223
|
]
|
210
224
|
}),
|
211
225
|
deleteDocument: builder.mutation({
|
@@ -246,7 +260,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
246
260
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
247
261
|
},
|
248
262
|
{ type: "Document", id: `${model}_LIST` },
|
249
|
-
"Relations"
|
263
|
+
"Relations",
|
264
|
+
{ type: "UidAvailability", id: model }
|
250
265
|
];
|
251
266
|
}
|
252
267
|
}),
|
@@ -303,6 +318,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
303
318
|
{
|
304
319
|
type: "Document",
|
305
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`
|
306
326
|
}
|
307
327
|
];
|
308
328
|
}
|
@@ -366,7 +386,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
366
386
|
type: "Document",
|
367
387
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
368
388
|
},
|
369
|
-
"Relations"
|
389
|
+
"Relations",
|
390
|
+
{ type: "UidAvailability", id: model }
|
370
391
|
];
|
371
392
|
},
|
372
393
|
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
@@ -449,20 +470,39 @@ const buildValidParams = (query) => {
|
|
449
470
|
const isBaseQueryError = (error) => {
|
450
471
|
return error.name !== void 0;
|
451
472
|
};
|
452
|
-
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 }) => {
|
453
492
|
const createModelSchema = (attributes2) => yup.object().shape(
|
454
493
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
455
494
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
456
495
|
return acc;
|
457
496
|
}
|
458
497
|
const validations = [
|
498
|
+
addNullableValidation,
|
459
499
|
addRequiredValidation,
|
460
500
|
addMinLengthValidation,
|
461
501
|
addMaxLengthValidation,
|
462
502
|
addMinValidation,
|
463
503
|
addMaxValidation,
|
464
504
|
addRegexValidation
|
465
|
-
].map((fn) => fn(attribute));
|
505
|
+
].map((fn) => fn(attribute, options));
|
466
506
|
const transformSchema = pipe(...validations);
|
467
507
|
switch (attribute.type) {
|
468
508
|
case "component": {
|
@@ -472,12 +512,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
472
512
|
...acc,
|
473
513
|
[name]: transformSchema(
|
474
514
|
yup.array().of(createModelSchema(attributes3).nullable(false))
|
475
|
-
)
|
515
|
+
).test(arrayValidator(attribute, options))
|
476
516
|
};
|
477
517
|
} else {
|
478
518
|
return {
|
479
519
|
...acc,
|
480
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
520
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
481
521
|
};
|
482
522
|
}
|
483
523
|
}
|
@@ -499,7 +539,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
499
539
|
}
|
500
540
|
)
|
501
541
|
)
|
502
|
-
)
|
542
|
+
).test(arrayValidator(attribute, options))
|
503
543
|
};
|
504
544
|
case "relation":
|
505
545
|
return {
|
@@ -511,7 +551,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
511
551
|
} else if (Array.isArray(value)) {
|
512
552
|
return yup.array().of(
|
513
553
|
yup.object().shape({
|
514
|
-
id: yup.
|
554
|
+
id: yup.number().required()
|
515
555
|
})
|
516
556
|
);
|
517
557
|
} else if (typeof value === "object") {
|
@@ -563,6 +603,14 @@ const createAttributeSchema = (attribute) => {
|
|
563
603
|
if (!value || typeof value === "string" && value.length === 0) {
|
564
604
|
return true;
|
565
605
|
}
|
606
|
+
if (typeof value === "object") {
|
607
|
+
try {
|
608
|
+
JSON.stringify(value);
|
609
|
+
return true;
|
610
|
+
} catch (err) {
|
611
|
+
return false;
|
612
|
+
}
|
613
|
+
}
|
566
614
|
try {
|
567
615
|
JSON.parse(value);
|
568
616
|
return true;
|
@@ -581,13 +629,7 @@ const createAttributeSchema = (attribute) => {
|
|
581
629
|
return yup.mixed();
|
582
630
|
}
|
583
631
|
};
|
584
|
-
const
|
585
|
-
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
586
|
-
return schema.min(1, translatedErrors.required);
|
587
|
-
}
|
588
|
-
if (attribute.required && attribute.type !== "relation") {
|
589
|
-
return schema.required(translatedErrors.required);
|
590
|
-
}
|
632
|
+
const nullableSchema = (schema) => {
|
591
633
|
return schema?.nullable ? schema.nullable() : (
|
592
634
|
// In some cases '.nullable' will not be available on the schema.
|
593
635
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -595,7 +637,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
595
637
|
schema
|
596
638
|
);
|
597
639
|
};
|
598
|
-
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
|
+
}
|
599
656
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
600
657
|
return schema.min(attribute.minLength, {
|
601
658
|
...translatedErrors.minLength,
|
@@ -617,32 +674,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
617
674
|
}
|
618
675
|
return schema;
|
619
676
|
};
|
620
|
-
const addMinValidation = (attribute) => (schema) => {
|
621
|
-
if ("
|
677
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
678
|
+
if (options.status === "draft") {
|
679
|
+
return schema;
|
680
|
+
}
|
681
|
+
if ("min" in attribute && "min" in schema) {
|
622
682
|
const min = toInteger(attribute.min);
|
623
|
-
if (
|
624
|
-
if (!attribute.required && "test" in schema && min) {
|
625
|
-
return schema.test(
|
626
|
-
"custom-min",
|
627
|
-
{
|
628
|
-
...translatedErrors.min,
|
629
|
-
values: {
|
630
|
-
min: attribute.min
|
631
|
-
}
|
632
|
-
},
|
633
|
-
(value) => {
|
634
|
-
if (!value) {
|
635
|
-
return true;
|
636
|
-
}
|
637
|
-
if (Array.isArray(value) && value.length === 0) {
|
638
|
-
return true;
|
639
|
-
}
|
640
|
-
return value.length >= min;
|
641
|
-
}
|
642
|
-
);
|
643
|
-
}
|
644
|
-
}
|
645
|
-
if ("min" in schema && min) {
|
683
|
+
if (min) {
|
646
684
|
return schema.min(min, {
|
647
685
|
...translatedErrors.min,
|
648
686
|
values: {
|
@@ -760,19 +798,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
760
798
|
}, {});
|
761
799
|
return componentsByKey;
|
762
800
|
};
|
763
|
-
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);
|
764
900
|
const { toggleNotification } = useNotification();
|
765
901
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
902
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
766
903
|
const {
|
767
|
-
|
768
|
-
isLoading:
|
769
|
-
|
770
|
-
|
771
|
-
} =
|
772
|
-
|
773
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
774
|
-
});
|
775
|
-
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;
|
776
910
|
React.useEffect(() => {
|
777
911
|
if (error) {
|
778
912
|
toggleNotification({
|
@@ -780,90 +914,346 @@ const useDocument = (args, opts) => {
|
|
780
914
|
message: formatAPIError(error)
|
781
915
|
});
|
782
916
|
}
|
783
|
-
}, [
|
784
|
-
const
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
(document) => {
|
792
|
-
if (!validationSchema) {
|
793
|
-
throw new Error(
|
794
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
795
|
-
);
|
796
|
-
}
|
797
|
-
try {
|
798
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
799
|
-
return null;
|
800
|
-
} catch (error2) {
|
801
|
-
if (error2 instanceof ValidationError) {
|
802
|
-
return getYupValidationErrors(error2);
|
803
|
-
}
|
804
|
-
throw error2;
|
805
|
-
}
|
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
|
806
925
|
},
|
807
|
-
[
|
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]
|
808
942
|
);
|
809
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
810
943
|
return {
|
811
|
-
|
812
|
-
document: data?.data,
|
813
|
-
meta: data?.meta,
|
944
|
+
error,
|
814
945
|
isLoading,
|
815
|
-
|
816
|
-
|
817
|
-
};
|
818
|
-
};
|
819
|
-
const useDoc = () => {
|
820
|
-
const { id, slug, collectionType, origin } = useParams();
|
821
|
-
const [{ query }] = useQueryParams();
|
822
|
-
const params = React.useMemo(() => buildValidParams(query), [query]);
|
823
|
-
if (!collectionType) {
|
824
|
-
throw new Error("Could not find collectionType in url params");
|
825
|
-
}
|
826
|
-
if (!slug) {
|
827
|
-
throw new Error("Could not find model in url params");
|
828
|
-
}
|
829
|
-
return {
|
830
|
-
collectionType,
|
831
|
-
model: slug,
|
832
|
-
id: origin || id === "create" ? void 0 : id,
|
833
|
-
...useDocument(
|
834
|
-
{ documentId: origin || id, model: slug, collectionType, params },
|
835
|
-
{
|
836
|
-
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
837
|
-
}
|
838
|
-
)
|
946
|
+
edit,
|
947
|
+
list: listLayout
|
839
948
|
};
|
840
949
|
};
|
841
|
-
const
|
842
|
-
|
843
|
-
|
844
|
-
}
|
845
|
-
return Object.keys(trad).reduce((acc, current) => {
|
846
|
-
acc[`${pluginId}.${current}`] = trad[current];
|
847
|
-
return acc;
|
848
|
-
}, {});
|
849
|
-
};
|
850
|
-
const getTranslation = (id) => `content-manager.${id}`;
|
851
|
-
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
852
|
-
id: "notification.error",
|
853
|
-
defaultMessage: "An error occurred, please try again"
|
950
|
+
const useDocLayout = () => {
|
951
|
+
const { model } = useDoc();
|
952
|
+
return useDocumentLayout(model);
|
854
953
|
};
|
855
|
-
const
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
const
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
954
|
+
const formatEditLayout = (data, {
|
955
|
+
schemas,
|
956
|
+
schema,
|
957
|
+
components
|
958
|
+
}) => {
|
959
|
+
let currentPanelIndex = 0;
|
960
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
961
|
+
data.contentType.layouts.edit,
|
962
|
+
schema?.attributes,
|
963
|
+
data.contentType.metadatas,
|
964
|
+
{ configurations: data.components, schemas: components },
|
965
|
+
schemas
|
966
|
+
).reduce((panels, row) => {
|
967
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
968
|
+
panels.push([row]);
|
969
|
+
currentPanelIndex += 2;
|
970
|
+
} else {
|
971
|
+
if (!panels[currentPanelIndex]) {
|
972
|
+
panels.push([row]);
|
973
|
+
} else {
|
974
|
+
panels[currentPanelIndex].push(row);
|
975
|
+
}
|
976
|
+
}
|
977
|
+
return panels;
|
978
|
+
}, []);
|
979
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
980
|
+
(acc, [uid, configuration]) => {
|
981
|
+
acc[uid] = {
|
982
|
+
layout: convertEditLayoutToFieldLayouts(
|
983
|
+
configuration.layouts.edit,
|
984
|
+
components[uid].attributes,
|
985
|
+
configuration.metadatas,
|
986
|
+
{ configurations: data.components, schemas: components }
|
987
|
+
),
|
988
|
+
settings: {
|
989
|
+
...configuration.settings,
|
990
|
+
icon: components[uid].info.icon,
|
991
|
+
displayName: components[uid].info.displayName
|
992
|
+
}
|
993
|
+
};
|
994
|
+
return acc;
|
995
|
+
},
|
996
|
+
{}
|
997
|
+
);
|
998
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
999
|
+
(acc, [attribute, metadata]) => {
|
1000
|
+
return {
|
1001
|
+
...acc,
|
1002
|
+
[attribute]: metadata.edit
|
1003
|
+
};
|
1004
|
+
},
|
1005
|
+
{}
|
1006
|
+
);
|
1007
|
+
return {
|
1008
|
+
layout: panelledEditAttributes,
|
1009
|
+
components: componentEditAttributes,
|
1010
|
+
metadatas: editMetadatas,
|
1011
|
+
settings: {
|
1012
|
+
...data.contentType.settings,
|
1013
|
+
displayName: schema?.info.displayName
|
1014
|
+
},
|
1015
|
+
options: {
|
1016
|
+
...schema?.options,
|
1017
|
+
...schema?.pluginOptions,
|
1018
|
+
...data.contentType.options
|
1019
|
+
}
|
1020
|
+
};
|
1021
|
+
};
|
1022
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1023
|
+
return rows.map(
|
1024
|
+
(row) => row.map((field) => {
|
1025
|
+
const attribute = attributes[field.name];
|
1026
|
+
if (!attribute) {
|
1027
|
+
return null;
|
1028
|
+
}
|
1029
|
+
const { edit: metadata } = metadatas[field.name];
|
1030
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1031
|
+
return {
|
1032
|
+
attribute,
|
1033
|
+
disabled: !metadata.editable,
|
1034
|
+
hint: metadata.description,
|
1035
|
+
label: metadata.label ?? "",
|
1036
|
+
name: field.name,
|
1037
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1038
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1039
|
+
schemas,
|
1040
|
+
components: components?.schemas ?? {}
|
1041
|
+
}),
|
1042
|
+
placeholder: metadata.placeholder ?? "",
|
1043
|
+
required: attribute.required ?? false,
|
1044
|
+
size: field.size,
|
1045
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1046
|
+
visible: metadata.visible ?? true,
|
1047
|
+
type: attribute.type
|
1048
|
+
};
|
1049
|
+
}).filter((field) => field !== null)
|
1050
|
+
);
|
1051
|
+
};
|
1052
|
+
const formatListLayout = (data, {
|
1053
|
+
schemas,
|
1054
|
+
schema,
|
1055
|
+
components
|
1056
|
+
}) => {
|
1057
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1058
|
+
(acc, [attribute, metadata]) => {
|
1059
|
+
return {
|
1060
|
+
...acc,
|
1061
|
+
[attribute]: metadata.list
|
1062
|
+
};
|
1063
|
+
},
|
1064
|
+
{}
|
1065
|
+
);
|
1066
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1067
|
+
data.contentType.layouts.list,
|
1068
|
+
schema?.attributes,
|
1069
|
+
listMetadatas,
|
1070
|
+
{ configurations: data.components, schemas: components },
|
1071
|
+
schemas
|
1072
|
+
);
|
1073
|
+
return {
|
1074
|
+
layout: listAttributes,
|
1075
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1076
|
+
metadatas: listMetadatas,
|
1077
|
+
options: {
|
1078
|
+
...schema?.options,
|
1079
|
+
...schema?.pluginOptions,
|
1080
|
+
...data.contentType.options
|
1081
|
+
}
|
1082
|
+
};
|
1083
|
+
};
|
1084
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1085
|
+
return columns.map((name) => {
|
1086
|
+
const attribute = attributes[name];
|
1087
|
+
if (!attribute) {
|
1088
|
+
return null;
|
1089
|
+
}
|
1090
|
+
const metadata = metadatas[name];
|
1091
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1092
|
+
return {
|
1093
|
+
attribute,
|
1094
|
+
label: metadata.label ?? "",
|
1095
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1096
|
+
schemas,
|
1097
|
+
components: components?.schemas ?? {}
|
1098
|
+
}),
|
1099
|
+
name,
|
1100
|
+
searchable: metadata.searchable ?? true,
|
1101
|
+
sortable: metadata.sortable ?? true
|
1102
|
+
};
|
1103
|
+
}).filter((field) => field !== null);
|
1104
|
+
};
|
1105
|
+
const useDocument = (args, opts) => {
|
1106
|
+
const { toggleNotification } = useNotification();
|
1107
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1108
|
+
const {
|
1109
|
+
currentData: data,
|
1110
|
+
isLoading: isLoadingDocument,
|
1111
|
+
isFetching: isFetchingDocument,
|
1112
|
+
error
|
1113
|
+
} = useGetDocumentQuery(args, {
|
1114
|
+
...opts,
|
1115
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1116
|
+
});
|
1117
|
+
const {
|
1118
|
+
components,
|
1119
|
+
schema,
|
1120
|
+
schemas,
|
1121
|
+
isLoading: isLoadingSchema
|
1122
|
+
} = useContentTypeSchema(args.model);
|
1123
|
+
React.useEffect(() => {
|
1124
|
+
if (error) {
|
1125
|
+
toggleNotification({
|
1126
|
+
type: "danger",
|
1127
|
+
message: formatAPIError(error)
|
1128
|
+
});
|
1129
|
+
}
|
1130
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1131
|
+
const validationSchema = React.useMemo(() => {
|
1132
|
+
if (!schema) {
|
1133
|
+
return null;
|
1134
|
+
}
|
1135
|
+
return createYupSchema(schema.attributes, components);
|
1136
|
+
}, [schema, components]);
|
1137
|
+
const validate = React.useCallback(
|
1138
|
+
(document) => {
|
1139
|
+
if (!validationSchema) {
|
1140
|
+
throw new Error(
|
1141
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1142
|
+
);
|
1143
|
+
}
|
1144
|
+
try {
|
1145
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1146
|
+
return null;
|
1147
|
+
} catch (error2) {
|
1148
|
+
if (error2 instanceof ValidationError) {
|
1149
|
+
return getYupValidationErrors(error2);
|
1150
|
+
}
|
1151
|
+
throw error2;
|
1152
|
+
}
|
1153
|
+
},
|
1154
|
+
[validationSchema]
|
1155
|
+
);
|
1156
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1157
|
+
const hasError = !!error;
|
1158
|
+
return {
|
1159
|
+
components,
|
1160
|
+
document: data?.data,
|
1161
|
+
meta: data?.meta,
|
1162
|
+
isLoading,
|
1163
|
+
hasError,
|
1164
|
+
schema,
|
1165
|
+
schemas,
|
1166
|
+
validate
|
1167
|
+
};
|
1168
|
+
};
|
1169
|
+
const useDoc = () => {
|
1170
|
+
const { id, slug, collectionType, origin } = useParams();
|
1171
|
+
const [{ query }] = useQueryParams();
|
1172
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1173
|
+
if (!collectionType) {
|
1174
|
+
throw new Error("Could not find collectionType in url params");
|
1175
|
+
}
|
1176
|
+
if (!slug) {
|
1177
|
+
throw new Error("Could not find model in url params");
|
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;
|
1186
|
+
return {
|
1187
|
+
collectionType,
|
1188
|
+
model: slug,
|
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
|
1230
|
+
};
|
1231
|
+
};
|
1232
|
+
const prefixPluginTranslations = (trad, pluginId) => {
|
1233
|
+
return Object.keys(trad).reduce((acc, current) => {
|
1234
|
+
acc[`${pluginId}.${current}`] = trad[current];
|
1235
|
+
return acc;
|
1236
|
+
}, {});
|
1237
|
+
};
|
1238
|
+
const getTranslation = (id) => `content-manager.${id}`;
|
1239
|
+
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
1240
|
+
id: "notification.error",
|
1241
|
+
defaultMessage: "An error occurred, please try again"
|
1242
|
+
};
|
1243
|
+
const useDocumentActions = () => {
|
1244
|
+
const { toggleNotification } = useNotification();
|
1245
|
+
const { formatMessage } = useIntl();
|
1246
|
+
const { trackUsage } = useTracking();
|
1247
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1248
|
+
const navigate = useNavigate();
|
1249
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
1250
|
+
const [deleteDocument] = useDeleteDocumentMutation();
|
1251
|
+
const _delete = React.useCallback(
|
1252
|
+
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
1253
|
+
try {
|
1254
|
+
trackUsage("willDeleteEntry", trackerProperty);
|
1255
|
+
const res = await deleteDocument({
|
1256
|
+
collectionType,
|
867
1257
|
model,
|
868
1258
|
documentId,
|
869
1259
|
params
|
@@ -1171,6 +1561,7 @@ const useDocumentActions = () => {
|
|
1171
1561
|
defaultMessage: "Saved document"
|
1172
1562
|
})
|
1173
1563
|
});
|
1564
|
+
setCurrentStep("contentManager.success");
|
1174
1565
|
return res.data;
|
1175
1566
|
} catch (err) {
|
1176
1567
|
toggleNotification({
|
@@ -1210,7 +1601,7 @@ const useDocumentActions = () => {
|
|
1210
1601
|
throw err;
|
1211
1602
|
}
|
1212
1603
|
},
|
1213
|
-
[autoCloneDocument,
|
1604
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1214
1605
|
);
|
1215
1606
|
const [cloneDocument] = useCloneDocumentMutation();
|
1216
1607
|
const clone = React.useCallback(
|
@@ -1236,6 +1627,7 @@ const useDocumentActions = () => {
|
|
1236
1627
|
defaultMessage: "Cloned document"
|
1237
1628
|
})
|
1238
1629
|
});
|
1630
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1239
1631
|
return res.data;
|
1240
1632
|
} catch (err) {
|
1241
1633
|
toggleNotification({
|
@@ -1246,7 +1638,7 @@ const useDocumentActions = () => {
|
|
1246
1638
|
throw err;
|
1247
1639
|
}
|
1248
1640
|
},
|
1249
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1641
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1250
1642
|
);
|
1251
1643
|
const [getDoc] = useLazyGetDocumentQuery();
|
1252
1644
|
const getDocument = React.useCallback(
|
@@ -1271,10 +1663,10 @@ const useDocumentActions = () => {
|
|
1271
1663
|
update
|
1272
1664
|
};
|
1273
1665
|
};
|
1274
|
-
const ProtectedHistoryPage = lazy(
|
1275
|
-
() => import("./History-
|
1666
|
+
const ProtectedHistoryPage = React.lazy(
|
1667
|
+
() => import("./History-DEvr3Q_V.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1276
1668
|
);
|
1277
|
-
const routes$
|
1669
|
+
const routes$2 = [
|
1278
1670
|
{
|
1279
1671
|
path: ":collectionType/:slug/:id/history",
|
1280
1672
|
Component: ProtectedHistoryPage
|
@@ -1284,32 +1676,45 @@ const routes$1 = [
|
|
1284
1676
|
Component: ProtectedHistoryPage
|
1285
1677
|
}
|
1286
1678
|
];
|
1679
|
+
const ProtectedPreviewPage = React.lazy(
|
1680
|
+
() => import("./Preview-DcexhKJE.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
|
+
];
|
1287
1692
|
const ProtectedEditViewPage = lazy(
|
1288
|
-
() => import("./EditViewPage-
|
1693
|
+
() => import("./EditViewPage-5pdbvsO_.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1289
1694
|
);
|
1290
1695
|
const ProtectedListViewPage = lazy(
|
1291
|
-
() => import("./ListViewPage-
|
1696
|
+
() => import("./ListViewPage-BK2mkrql.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1292
1697
|
);
|
1293
1698
|
const ProtectedListConfiguration = lazy(
|
1294
|
-
() => import("./ListConfigurationPage-
|
1699
|
+
() => import("./ListConfigurationPage-BM4zZZcM.mjs").then((mod) => ({
|
1295
1700
|
default: mod.ProtectedListConfiguration
|
1296
1701
|
}))
|
1297
1702
|
);
|
1298
1703
|
const ProtectedEditConfigurationPage = lazy(
|
1299
|
-
() => import("./EditConfigurationPage-
|
1704
|
+
() => import("./EditConfigurationPage-BYCBSJxP.mjs").then((mod) => ({
|
1300
1705
|
default: mod.ProtectedEditConfigurationPage
|
1301
1706
|
}))
|
1302
1707
|
);
|
1303
1708
|
const ProtectedComponentConfigurationPage = lazy(
|
1304
|
-
() => import("./ComponentConfigurationPage-
|
1709
|
+
() => import("./ComponentConfigurationPage-D3ZWDAHG.mjs").then((mod) => ({
|
1305
1710
|
default: mod.ProtectedComponentConfigurationPage
|
1306
1711
|
}))
|
1307
1712
|
);
|
1308
1713
|
const NoPermissions = lazy(
|
1309
|
-
() => import("./NoPermissionsPage-
|
1714
|
+
() => import("./NoPermissionsPage-BmbRz7PR.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1310
1715
|
);
|
1311
1716
|
const NoContentType = lazy(
|
1312
|
-
() => import("./NoContentTypePage-
|
1717
|
+
() => import("./NoContentTypePage-BvcAutu9.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1313
1718
|
);
|
1314
1719
|
const CollectionTypePages = () => {
|
1315
1720
|
const { collectionType } = useParams();
|
@@ -1321,7 +1726,7 @@ const CollectionTypePages = () => {
|
|
1321
1726
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1322
1727
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1323
1728
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1324
|
-
const LIST_PATH = `/content-manager
|
1729
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1325
1730
|
const routes = [
|
1326
1731
|
{
|
1327
1732
|
path: LIST_RELATIVE_PATH,
|
@@ -1355,6 +1760,7 @@ const routes = [
|
|
1355
1760
|
path: "no-content-types",
|
1356
1761
|
Component: NoContentType
|
1357
1762
|
},
|
1763
|
+
...routes$2,
|
1358
1764
|
...routes$1
|
1359
1765
|
];
|
1360
1766
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1423,12 +1829,14 @@ const DocumentActionButton = (action) => {
|
|
1423
1829
|
/* @__PURE__ */ jsx(
|
1424
1830
|
Button,
|
1425
1831
|
{
|
1426
|
-
flex:
|
1832
|
+
flex: "auto",
|
1427
1833
|
startIcon: action.icon,
|
1428
1834
|
disabled: action.disabled,
|
1429
1835
|
onClick: handleClick(action),
|
1430
1836
|
justifyContent: "center",
|
1431
1837
|
variant: action.variant || "default",
|
1838
|
+
paddingTop: "7px",
|
1839
|
+
paddingBottom: "7px",
|
1432
1840
|
children: action.label
|
1433
1841
|
}
|
1434
1842
|
),
|
@@ -1451,6 +1859,11 @@ const DocumentActionButton = (action) => {
|
|
1451
1859
|
) : null
|
1452
1860
|
] });
|
1453
1861
|
};
|
1862
|
+
const MenuItem = styled(Menu.Item)`
|
1863
|
+
&:hover {
|
1864
|
+
background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
|
1865
|
+
}
|
1866
|
+
`;
|
1454
1867
|
const DocumentActionsMenu = ({
|
1455
1868
|
actions: actions2,
|
1456
1869
|
children,
|
@@ -1506,44 +1919,35 @@ const DocumentActionsMenu = ({
|
|
1506
1919
|
]
|
1507
1920
|
}
|
1508
1921
|
),
|
1509
|
-
/* @__PURE__ */ jsxs(Menu.Content, {
|
1922
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1510
1923
|
actions2.map((action) => {
|
1511
1924
|
return /* @__PURE__ */ jsx(
|
1512
|
-
|
1925
|
+
MenuItem,
|
1513
1926
|
{
|
1514
1927
|
disabled: action.disabled,
|
1515
1928
|
onSelect: handleClick(action),
|
1516
1929
|
display: "block",
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
height: 5,
|
1539
|
-
paddingLeft: 2,
|
1540
|
-
paddingRight: 2,
|
1541
|
-
hasRadius: true,
|
1542
|
-
color: "alternative600",
|
1543
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1544
|
-
}
|
1545
|
-
)
|
1546
|
-
] })
|
1930
|
+
isVariantDanger: action.variant === "danger",
|
1931
|
+
isDisabled: action.disabled,
|
1932
|
+
children: /* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxs(
|
1933
|
+
Flex,
|
1934
|
+
{
|
1935
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1936
|
+
gap: 2,
|
1937
|
+
tag: "span",
|
1938
|
+
children: [
|
1939
|
+
/* @__PURE__ */ jsx(
|
1940
|
+
Flex,
|
1941
|
+
{
|
1942
|
+
tag: "span",
|
1943
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1944
|
+
children: action.icon
|
1945
|
+
}
|
1946
|
+
),
|
1947
|
+
action.label
|
1948
|
+
]
|
1949
|
+
}
|
1950
|
+
) })
|
1547
1951
|
},
|
1548
1952
|
action.id
|
1549
1953
|
);
|
@@ -1585,6 +1989,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
|
|
1585
1989
|
return "primary600";
|
1586
1990
|
}
|
1587
1991
|
};
|
1992
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1993
|
+
switch (variant) {
|
1994
|
+
case "danger":
|
1995
|
+
return "danger600";
|
1996
|
+
case "secondary":
|
1997
|
+
return "neutral500";
|
1998
|
+
case "success":
|
1999
|
+
return "success600";
|
2000
|
+
default:
|
2001
|
+
return "primary600";
|
2002
|
+
}
|
2003
|
+
};
|
1588
2004
|
const DocumentActionConfirmDialog = ({
|
1589
2005
|
onClose,
|
1590
2006
|
onCancel,
|
@@ -1611,11 +2027,11 @@ const DocumentActionConfirmDialog = ({
|
|
1611
2027
|
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1612
2028
|
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1613
2029
|
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1614
|
-
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
2030
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1615
2031
|
id: "app.components.Button.cancel",
|
1616
2032
|
defaultMessage: "Cancel"
|
1617
2033
|
}) }) }),
|
1618
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2034
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1619
2035
|
id: "app.components.Button.confirm",
|
1620
2036
|
defaultMessage: "Confirm"
|
1621
2037
|
}) })
|
@@ -1642,6 +2058,18 @@ const DocumentActionModal = ({
|
|
1642
2058
|
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1643
2059
|
] }) });
|
1644
2060
|
};
|
2061
|
+
const transformData = (data) => {
|
2062
|
+
if (Array.isArray(data)) {
|
2063
|
+
return data.map(transformData);
|
2064
|
+
}
|
2065
|
+
if (typeof data === "object" && data !== null) {
|
2066
|
+
if ("apiData" in data) {
|
2067
|
+
return data.apiData;
|
2068
|
+
}
|
2069
|
+
return mapValues(transformData)(data);
|
2070
|
+
}
|
2071
|
+
return data;
|
2072
|
+
};
|
1645
2073
|
const PublishAction$1 = ({
|
1646
2074
|
activeTab,
|
1647
2075
|
documentId,
|
@@ -1654,12 +2082,10 @@ const PublishAction$1 = ({
|
|
1654
2082
|
const navigate = useNavigate();
|
1655
2083
|
const { toggleNotification } = useNotification();
|
1656
2084
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2085
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
1657
2086
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
1658
2087
|
const { formatMessage } = useIntl();
|
1659
|
-
const { canPublish
|
1660
|
-
"PublishAction",
|
1661
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1662
|
-
);
|
2088
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1663
2089
|
const { publish } = useDocumentActions();
|
1664
2090
|
const [
|
1665
2091
|
countDraftRelations,
|
@@ -1711,24 +2137,25 @@ const PublishAction$1 = ({
|
|
1711
2137
|
}
|
1712
2138
|
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1713
2139
|
React.useEffect(() => {
|
1714
|
-
if (documentId) {
|
1715
|
-
|
1716
|
-
const { data, error } = await countDraftRelations({
|
1717
|
-
collectionType,
|
1718
|
-
model,
|
1719
|
-
documentId,
|
1720
|
-
params
|
1721
|
-
});
|
1722
|
-
if (error) {
|
1723
|
-
throw error;
|
1724
|
-
}
|
1725
|
-
if (data) {
|
1726
|
-
setServerCountOfDraftRelations(data.data);
|
1727
|
-
}
|
1728
|
-
};
|
1729
|
-
fetchDraftRelationsCount();
|
2140
|
+
if (!document || !document.documentId || isListView) {
|
2141
|
+
return;
|
1730
2142
|
}
|
1731
|
-
|
2143
|
+
const fetchDraftRelationsCount = async () => {
|
2144
|
+
const { data, error } = await countDraftRelations({
|
2145
|
+
collectionType,
|
2146
|
+
model,
|
2147
|
+
documentId,
|
2148
|
+
params
|
2149
|
+
});
|
2150
|
+
if (error) {
|
2151
|
+
throw error;
|
2152
|
+
}
|
2153
|
+
if (data) {
|
2154
|
+
setServerCountOfDraftRelations(data.data);
|
2155
|
+
}
|
2156
|
+
};
|
2157
|
+
fetchDraftRelationsCount();
|
2158
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
1732
2159
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1733
2160
|
if (!schema?.options?.draftAndPublish) {
|
1734
2161
|
return null;
|
@@ -1736,7 +2163,9 @@ const PublishAction$1 = ({
|
|
1736
2163
|
const performPublish = async () => {
|
1737
2164
|
setSubmitting(true);
|
1738
2165
|
try {
|
1739
|
-
const { errors } = await validate(
|
2166
|
+
const { errors } = await validate(true, {
|
2167
|
+
status: "published"
|
2168
|
+
});
|
1740
2169
|
if (errors) {
|
1741
2170
|
toggleNotification({
|
1742
2171
|
type: "danger",
|
@@ -1754,7 +2183,7 @@ const PublishAction$1 = ({
|
|
1754
2183
|
documentId,
|
1755
2184
|
params
|
1756
2185
|
},
|
1757
|
-
formValues
|
2186
|
+
transformData(formValues)
|
1758
2187
|
);
|
1759
2188
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1760
2189
|
navigate({
|
@@ -1769,7 +2198,8 @@ const PublishAction$1 = ({
|
|
1769
2198
|
}
|
1770
2199
|
};
|
1771
2200
|
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1772
|
-
const
|
2201
|
+
const enableDraftRelationsCount = false;
|
2202
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1773
2203
|
return {
|
1774
2204
|
/**
|
1775
2205
|
* Disabled when:
|
@@ -1786,9 +2216,6 @@ const PublishAction$1 = ({
|
|
1786
2216
|
defaultMessage: "Publish"
|
1787
2217
|
}),
|
1788
2218
|
onClick: async () => {
|
1789
|
-
if (hasDraftRelations) {
|
1790
|
-
return;
|
1791
|
-
}
|
1792
2219
|
await performPublish();
|
1793
2220
|
},
|
1794
2221
|
dialog: hasDraftRelations ? {
|
@@ -1827,10 +2254,6 @@ const UpdateAction = ({
|
|
1827
2254
|
const cloneMatch = useMatch(CLONE_PATH);
|
1828
2255
|
const isCloning = cloneMatch !== null;
|
1829
2256
|
const { formatMessage } = useIntl();
|
1830
|
-
useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1831
|
-
canCreate: canCreate2,
|
1832
|
-
canUpdate: canUpdate2
|
1833
|
-
}));
|
1834
2257
|
const { create, update, clone } = useDocumentActions();
|
1835
2258
|
const [{ query, rawQuery }] = useQueryParams();
|
1836
2259
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
@@ -1850,13 +2273,15 @@ const UpdateAction = ({
|
|
1850
2273
|
*/
|
1851
2274
|
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1852
2275
|
label: formatMessage({
|
1853
|
-
id: "
|
2276
|
+
id: "global.save",
|
1854
2277
|
defaultMessage: "Save"
|
1855
2278
|
}),
|
1856
2279
|
onClick: async () => {
|
1857
2280
|
setSubmitting(true);
|
1858
2281
|
try {
|
1859
|
-
const { errors } = await validate(
|
2282
|
+
const { errors } = await validate(true, {
|
2283
|
+
status: "draft"
|
2284
|
+
});
|
1860
2285
|
if (errors) {
|
1861
2286
|
toggleNotification({
|
1862
2287
|
type: "danger",
|
@@ -1874,7 +2299,7 @@ const UpdateAction = ({
|
|
1874
2299
|
documentId: cloneMatch.params.origin,
|
1875
2300
|
params
|
1876
2301
|
},
|
1877
|
-
document
|
2302
|
+
transformData(document)
|
1878
2303
|
);
|
1879
2304
|
if ("data" in res) {
|
1880
2305
|
navigate(
|
@@ -1895,7 +2320,7 @@ const UpdateAction = ({
|
|
1895
2320
|
documentId,
|
1896
2321
|
params
|
1897
2322
|
},
|
1898
|
-
document
|
2323
|
+
transformData(document)
|
1899
2324
|
);
|
1900
2325
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1901
2326
|
setErrors(formatValidationErrors(res.error));
|
@@ -1908,7 +2333,7 @@ const UpdateAction = ({
|
|
1908
2333
|
model,
|
1909
2334
|
params
|
1910
2335
|
},
|
1911
|
-
document
|
2336
|
+
transformData(document)
|
1912
2337
|
);
|
1913
2338
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1914
2339
|
navigate(
|
@@ -1961,7 +2386,7 @@ const UnpublishAction$1 = ({
|
|
1961
2386
|
id: "app.utils.unpublish",
|
1962
2387
|
defaultMessage: "Unpublish"
|
1963
2388
|
}),
|
1964
|
-
icon: /* @__PURE__ */ jsx(
|
2389
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1965
2390
|
onClick: async () => {
|
1966
2391
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1967
2392
|
if (!documentId) {
|
@@ -2073,7 +2498,7 @@ const DiscardAction = ({
|
|
2073
2498
|
id: "content-manager.actions.discard.label",
|
2074
2499
|
defaultMessage: "Discard changes"
|
2075
2500
|
}),
|
2076
|
-
icon: /* @__PURE__ */ jsx(
|
2501
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2077
2502
|
position: ["panel", "table-row"],
|
2078
2503
|
variant: "danger",
|
2079
2504
|
dialog: {
|
@@ -2101,11 +2526,6 @@ const DiscardAction = ({
|
|
2101
2526
|
};
|
2102
2527
|
};
|
2103
2528
|
DiscardAction.type = "discard";
|
2104
|
-
const StyledCrossCircle = styled(CrossCircle)`
|
2105
|
-
path {
|
2106
|
-
fill: currentColor;
|
2107
|
-
}
|
2108
|
-
`;
|
2109
2529
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2110
2530
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2111
2531
|
const RelativeTime = React.forwardRef(
|
@@ -2118,7 +2538,7 @@ const RelativeTime = React.forwardRef(
|
|
2118
2538
|
});
|
2119
2539
|
const unit = intervals.find((intervalUnit) => {
|
2120
2540
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2121
|
-
});
|
2541
|
+
}) ?? "seconds";
|
2122
2542
|
const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
|
2123
2543
|
const customInterval = customIntervals.find(
|
2124
2544
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2152,19 +2572,29 @@ const getDisplayName = ({
|
|
2152
2572
|
return email ?? "";
|
2153
2573
|
};
|
2154
2574
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2155
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2156
|
-
const statusVariant = status === "draft" ? "
|
2157
|
-
|
2575
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2576
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2577
|
+
const { formatMessage } = useIntl();
|
2578
|
+
return /* @__PURE__ */ jsx(Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2579
|
+
id: `content-manager.containers.List.${status}`,
|
2580
|
+
defaultMessage: capitalise(status)
|
2581
|
+
}) }) });
|
2158
2582
|
};
|
2159
2583
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2160
2584
|
const { formatMessage } = useIntl();
|
2161
2585
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2586
|
+
const params = useParams();
|
2162
2587
|
const title = isCreating ? formatMessage({
|
2163
2588
|
id: "content-manager.containers.edit.title.new",
|
2164
2589
|
defaultMessage: "Create an entry"
|
2165
2590
|
}) : documentTitle;
|
2166
2591
|
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2167
|
-
/* @__PURE__ */ jsx(
|
2592
|
+
/* @__PURE__ */ jsx(
|
2593
|
+
BackButton,
|
2594
|
+
{
|
2595
|
+
fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
|
2596
|
+
}
|
2597
|
+
),
|
2168
2598
|
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2169
2599
|
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2170
2600
|
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
@@ -2252,12 +2682,12 @@ const Information = ({ activeTab }) => {
|
|
2252
2682
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2253
2683
|
label: formatMessage({
|
2254
2684
|
id: "content-manager.containers.edit.information.last-published.label",
|
2255
|
-
defaultMessage: "
|
2685
|
+
defaultMessage: "Published"
|
2256
2686
|
}),
|
2257
2687
|
value: formatMessage(
|
2258
2688
|
{
|
2259
2689
|
id: "content-manager.containers.edit.information.last-published.value",
|
2260
|
-
defaultMessage: `
|
2690
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2261
2691
|
},
|
2262
2692
|
{
|
2263
2693
|
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2270,12 +2700,12 @@ const Information = ({ activeTab }) => {
|
|
2270
2700
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2271
2701
|
label: formatMessage({
|
2272
2702
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2273
|
-
defaultMessage: "
|
2703
|
+
defaultMessage: "Updated"
|
2274
2704
|
}),
|
2275
2705
|
value: formatMessage(
|
2276
2706
|
{
|
2277
2707
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2278
|
-
defaultMessage: `
|
2708
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2279
2709
|
},
|
2280
2710
|
{
|
2281
2711
|
time: /* @__PURE__ */ jsx(
|
@@ -2293,12 +2723,12 @@ const Information = ({ activeTab }) => {
|
|
2293
2723
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2294
2724
|
label: formatMessage({
|
2295
2725
|
id: "content-manager.containers.edit.information.document.label",
|
2296
|
-
defaultMessage: "
|
2726
|
+
defaultMessage: "Created"
|
2297
2727
|
}),
|
2298
2728
|
value: formatMessage(
|
2299
2729
|
{
|
2300
2730
|
id: "content-manager.containers.edit.information.document.value",
|
2301
|
-
defaultMessage: `
|
2731
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2302
2732
|
},
|
2303
2733
|
{
|
2304
2734
|
time: /* @__PURE__ */ jsx(
|
@@ -2336,523 +2766,277 @@ const Information = ({ activeTab }) => {
|
|
2336
2766
|
);
|
2337
2767
|
};
|
2338
2768
|
const HeaderActions = ({ actions: actions2 }) => {
|
2339
|
-
|
2340
|
-
|
2769
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2770
|
+
const handleClick = (action) => async (e) => {
|
2771
|
+
if (!("options" in action)) {
|
2772
|
+
const { onClick = () => false, dialog, id } = action;
|
2773
|
+
const muteDialog = await onClick(e);
|
2774
|
+
if (dialog && !muteDialog) {
|
2775
|
+
e.preventDefault();
|
2776
|
+
setDialogId(id);
|
2777
|
+
}
|
2778
|
+
}
|
2779
|
+
};
|
2780
|
+
const handleClose = () => {
|
2781
|
+
setDialogId(null);
|
2782
|
+
};
|
2783
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2784
|
+
if (action.options) {
|
2341
2785
|
return /* @__PURE__ */ jsx(
|
2342
2786
|
SingleSelect,
|
2343
2787
|
{
|
2344
2788
|
size: "S",
|
2345
|
-
disabled: action.disabled,
|
2346
|
-
"aria-label": action.label,
|
2347
2789
|
onChange: action.onSelect,
|
2348
|
-
|
2790
|
+
"aria-label": action.label,
|
2791
|
+
...action,
|
2349
2792
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2350
2793
|
},
|
2351
2794
|
action.id
|
2352
2795
|
);
|
2353
2796
|
} else {
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2363
|
-
|
2364
|
-
defaultMessage: "Configure the view"
|
2365
|
-
}),
|
2366
|
-
icon: /* @__PURE__ */ jsx(ListPlus, {}),
|
2367
|
-
onClick: () => {
|
2368
|
-
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2369
|
-
},
|
2370
|
-
position: "header"
|
2371
|
-
};
|
2372
|
-
};
|
2373
|
-
ConfigureTheViewAction.type = "configure-the-view";
|
2374
|
-
const EditTheModelAction = ({ model }) => {
|
2375
|
-
const navigate = useNavigate();
|
2376
|
-
const { formatMessage } = useIntl();
|
2377
|
-
return {
|
2378
|
-
label: formatMessage({
|
2379
|
-
id: "content-manager.link-to-ctb",
|
2380
|
-
defaultMessage: "Edit the model"
|
2381
|
-
}),
|
2382
|
-
icon: /* @__PURE__ */ jsx(Pencil, {}),
|
2383
|
-
onClick: () => {
|
2384
|
-
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2385
|
-
},
|
2386
|
-
position: "header"
|
2387
|
-
};
|
2388
|
-
};
|
2389
|
-
EditTheModelAction.type = "edit-the-model";
|
2390
|
-
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2391
|
-
const navigate = useNavigate();
|
2392
|
-
const { formatMessage } = useIntl();
|
2393
|
-
const listViewPathMatch = useMatch(LIST_PATH);
|
2394
|
-
const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
|
2395
|
-
const { delete: deleteAction } = useDocumentActions();
|
2396
|
-
const { toggleNotification } = useNotification();
|
2397
|
-
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2398
|
-
return {
|
2399
|
-
disabled: !canDelete || !document,
|
2400
|
-
label: formatMessage({
|
2401
|
-
id: "content-manager.actions.delete.label",
|
2402
|
-
defaultMessage: "Delete document"
|
2403
|
-
}),
|
2404
|
-
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2405
|
-
dialog: {
|
2406
|
-
type: "dialog",
|
2407
|
-
title: formatMessage({
|
2408
|
-
id: "app.components.ConfirmDialog.title",
|
2409
|
-
defaultMessage: "Confirmation"
|
2410
|
-
}),
|
2411
|
-
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
2412
|
-
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2413
|
-
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2414
|
-
id: "content-manager.actions.delete.dialog.body",
|
2415
|
-
defaultMessage: "Are you sure?"
|
2416
|
-
}) })
|
2417
|
-
] }),
|
2418
|
-
onConfirm: async () => {
|
2419
|
-
if (!listViewPathMatch) {
|
2420
|
-
setSubmitting(true);
|
2421
|
-
}
|
2422
|
-
try {
|
2423
|
-
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2424
|
-
console.error(
|
2425
|
-
"You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2426
|
-
);
|
2427
|
-
toggleNotification({
|
2428
|
-
message: formatMessage({
|
2429
|
-
id: "content-manager.actions.delete.error",
|
2430
|
-
defaultMessage: "An error occurred while trying to delete the document."
|
2431
|
-
}),
|
2432
|
-
type: "danger"
|
2433
|
-
});
|
2434
|
-
return;
|
2435
|
-
}
|
2436
|
-
const res = await deleteAction({
|
2437
|
-
documentId,
|
2438
|
-
model,
|
2439
|
-
collectionType,
|
2440
|
-
params: {
|
2441
|
-
locale: "*"
|
2797
|
+
if (action.type === "icon") {
|
2798
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2799
|
+
/* @__PURE__ */ jsx(
|
2800
|
+
IconButton,
|
2801
|
+
{
|
2802
|
+
disabled: action.disabled,
|
2803
|
+
label: action.label,
|
2804
|
+
size: "S",
|
2805
|
+
onClick: handleClick(action),
|
2806
|
+
children: action.icon
|
2442
2807
|
}
|
2443
|
-
|
2444
|
-
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
2808
|
+
),
|
2809
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2810
|
+
HeaderActionDialog,
|
2811
|
+
{
|
2812
|
+
...action.dialog,
|
2813
|
+
isOpen: dialogId === action.id,
|
2814
|
+
onClose: handleClose
|
2815
|
+
}
|
2816
|
+
) : null
|
2817
|
+
] }, action.id);
|
2452
2818
|
}
|
2453
|
-
},
|
2454
|
-
variant: "danger",
|
2455
|
-
position: ["header", "table-row"]
|
2456
|
-
};
|
2457
|
-
};
|
2458
|
-
DeleteAction$1.type = "delete";
|
2459
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2460
|
-
const Panels = () => {
|
2461
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2462
|
-
const [
|
2463
|
-
{
|
2464
|
-
query: { status }
|
2465
|
-
}
|
2466
|
-
] = useQueryParams({
|
2467
|
-
status: "draft"
|
2468
|
-
});
|
2469
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2470
|
-
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2471
|
-
const props = {
|
2472
|
-
activeTab: status,
|
2473
|
-
model,
|
2474
|
-
documentId: id,
|
2475
|
-
document: isCloning ? void 0 : document,
|
2476
|
-
meta: isCloning ? void 0 : meta,
|
2477
|
-
collectionType
|
2478
|
-
};
|
2479
|
-
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2480
|
-
DescriptionComponentRenderer,
|
2481
|
-
{
|
2482
|
-
props,
|
2483
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2484
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2485
|
-
}
|
2486
|
-
) });
|
2487
|
-
};
|
2488
|
-
const ActionsPanel = () => {
|
2489
|
-
const { formatMessage } = useIntl();
|
2490
|
-
return {
|
2491
|
-
title: formatMessage({
|
2492
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2493
|
-
defaultMessage: "Document"
|
2494
|
-
}),
|
2495
|
-
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2496
|
-
};
|
2497
|
-
};
|
2498
|
-
ActionsPanel.type = "actions";
|
2499
|
-
const ActionsPanelContent = () => {
|
2500
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2501
|
-
const [
|
2502
|
-
{
|
2503
|
-
query: { status = "draft" }
|
2504
2819
|
}
|
2505
|
-
|
2506
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2507
|
-
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2508
|
-
const props = {
|
2509
|
-
activeTab: status,
|
2510
|
-
model,
|
2511
|
-
documentId: id,
|
2512
|
-
document: isCloning ? void 0 : document,
|
2513
|
-
meta: isCloning ? void 0 : meta,
|
2514
|
-
collectionType
|
2515
|
-
};
|
2516
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2517
|
-
/* @__PURE__ */ jsx(
|
2518
|
-
DescriptionComponentRenderer,
|
2519
|
-
{
|
2520
|
-
props,
|
2521
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2522
|
-
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2523
|
-
}
|
2524
|
-
),
|
2525
|
-
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2526
|
-
] });
|
2820
|
+
}) });
|
2527
2821
|
};
|
2528
|
-
const
|
2529
|
-
|
2530
|
-
|
2531
|
-
|
2532
|
-
|
2533
|
-
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2537
|
-
|
2538
|
-
paddingBottom: 4,
|
2539
|
-
paddingLeft: 4,
|
2540
|
-
paddingRight: 4,
|
2541
|
-
paddingTop: 4,
|
2542
|
-
shadow: "tableShadow",
|
2543
|
-
gap: 3,
|
2544
|
-
direction: "column",
|
2545
|
-
justifyContent: "stretch",
|
2546
|
-
alignItems: "flex-start",
|
2547
|
-
children: [
|
2548
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2549
|
-
children
|
2550
|
-
]
|
2822
|
+
const HeaderActionDialog = ({
|
2823
|
+
onClose,
|
2824
|
+
onCancel,
|
2825
|
+
title,
|
2826
|
+
content: Content,
|
2827
|
+
isOpen
|
2828
|
+
}) => {
|
2829
|
+
const handleClose = async () => {
|
2830
|
+
if (onCancel) {
|
2831
|
+
await onCancel();
|
2551
2832
|
}
|
2552
|
-
|
2553
|
-
}
|
2554
|
-
|
2555
|
-
|
2556
|
-
|
2557
|
-
|
2558
|
-
* @type {string}
|
2559
|
-
*/
|
2560
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2561
|
-
/**
|
2562
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2563
|
-
* @constant
|
2564
|
-
* @type {string}
|
2565
|
-
*/
|
2566
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2567
|
-
/**
|
2568
|
-
* Hook that allows to mutate the CM's edit view layout
|
2569
|
-
* @constant
|
2570
|
-
* @type {string}
|
2571
|
-
*/
|
2572
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2573
|
-
/**
|
2574
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2575
|
-
* @constant
|
2576
|
-
* @type {string}
|
2577
|
-
*/
|
2578
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2833
|
+
onClose();
|
2834
|
+
};
|
2835
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2836
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2837
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2838
|
+
] }) });
|
2579
2839
|
};
|
2580
|
-
const
|
2581
|
-
|
2582
|
-
|
2583
|
-
|
2584
|
-
|
2585
|
-
|
2586
|
-
|
2587
|
-
transformResponse: (response) => response.data,
|
2588
|
-
providesTags: (_result, _error, uid) => [
|
2589
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2590
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2591
|
-
]
|
2592
|
-
}),
|
2593
|
-
getAllContentTypeSettings: builder.query({
|
2594
|
-
query: () => "/content-manager/content-types-settings",
|
2595
|
-
transformResponse: (response) => response.data,
|
2596
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2840
|
+
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2841
|
+
const navigate = useNavigate();
|
2842
|
+
const { formatMessage } = useIntl();
|
2843
|
+
return {
|
2844
|
+
label: formatMessage({
|
2845
|
+
id: "app.links.configure-view",
|
2846
|
+
defaultMessage: "Configure the view"
|
2597
2847
|
}),
|
2598
|
-
|
2599
|
-
|
2600
|
-
|
2601
|
-
|
2602
|
-
|
2603
|
-
|
2604
|
-
transformResponse: (response) => response.data,
|
2605
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2606
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2607
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2608
|
-
// Is this necessary?
|
2609
|
-
{ type: "InitialData" }
|
2610
|
-
]
|
2611
|
-
})
|
2612
|
-
})
|
2613
|
-
});
|
2614
|
-
const {
|
2615
|
-
useGetContentTypeConfigurationQuery,
|
2616
|
-
useGetAllContentTypeSettingsQuery,
|
2617
|
-
useUpdateContentTypeConfigurationMutation
|
2618
|
-
} = contentTypesApi;
|
2619
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2620
|
-
const { type } = attribute;
|
2621
|
-
if (type === "relation") {
|
2622
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2623
|
-
}
|
2624
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2848
|
+
icon: /* @__PURE__ */ jsx(ListPlus, {}),
|
2849
|
+
onClick: () => {
|
2850
|
+
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2851
|
+
},
|
2852
|
+
position: "header"
|
2853
|
+
};
|
2625
2854
|
};
|
2626
|
-
|
2627
|
-
|
2628
|
-
|
2629
|
-
}
|
2630
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2631
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2632
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2633
|
-
);
|
2855
|
+
ConfigureTheViewAction.type = "configure-the-view";
|
2856
|
+
const EditTheModelAction = ({ model }) => {
|
2857
|
+
const navigate = useNavigate();
|
2858
|
+
const { formatMessage } = useIntl();
|
2634
2859
|
return {
|
2635
|
-
|
2636
|
-
|
2860
|
+
label: formatMessage({
|
2861
|
+
id: "content-manager.link-to-ctb",
|
2862
|
+
defaultMessage: "Edit the model"
|
2863
|
+
}),
|
2864
|
+
icon: /* @__PURE__ */ jsx(Pencil, {}),
|
2865
|
+
onClick: () => {
|
2866
|
+
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2867
|
+
},
|
2868
|
+
position: "header"
|
2637
2869
|
};
|
2638
2870
|
};
|
2639
|
-
|
2640
|
-
|
2641
|
-
|
2642
|
-
|
2643
|
-
|
2644
|
-
|
2645
|
-
|
2646
|
-
mainField: "id",
|
2647
|
-
pageSize: 10
|
2648
|
-
};
|
2649
|
-
const useDocumentLayout = (model) => {
|
2650
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2651
|
-
const [{ query }] = useQueryParams();
|
2652
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2871
|
+
EditTheModelAction.type = "edit-the-model";
|
2872
|
+
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2873
|
+
const navigate = useNavigate();
|
2874
|
+
const { formatMessage } = useIntl();
|
2875
|
+
const listViewPathMatch = useMatch(LIST_PATH);
|
2876
|
+
const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
|
2877
|
+
const { delete: deleteAction } = useDocumentActions();
|
2653
2878
|
const { toggleNotification } = useNotification();
|
2654
|
-
const
|
2655
|
-
const
|
2656
|
-
const {
|
2657
|
-
data,
|
2658
|
-
isLoading: isLoadingConfigs,
|
2659
|
-
error,
|
2660
|
-
isFetching: isFetchingConfigs
|
2661
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2662
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2663
|
-
React.useEffect(() => {
|
2664
|
-
if (error) {
|
2665
|
-
toggleNotification({
|
2666
|
-
type: "danger",
|
2667
|
-
message: formatAPIError(error)
|
2668
|
-
});
|
2669
|
-
}
|
2670
|
-
}, [error, formatAPIError, toggleNotification]);
|
2671
|
-
const editLayout = React.useMemo(
|
2672
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2673
|
-
layout: [],
|
2674
|
-
components: {},
|
2675
|
-
metadatas: {},
|
2676
|
-
options: {},
|
2677
|
-
settings: DEFAULT_SETTINGS
|
2678
|
-
},
|
2679
|
-
[data, isLoading, schemas, schema, components]
|
2680
|
-
);
|
2681
|
-
const listLayout = React.useMemo(() => {
|
2682
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2683
|
-
layout: [],
|
2684
|
-
metadatas: {},
|
2685
|
-
options: {},
|
2686
|
-
settings: DEFAULT_SETTINGS
|
2687
|
-
};
|
2688
|
-
}, [data, isLoading, schemas, schema, components]);
|
2689
|
-
const { layout: edit } = React.useMemo(
|
2690
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2691
|
-
layout: editLayout,
|
2692
|
-
query
|
2693
|
-
}),
|
2694
|
-
[editLayout, query, runHookWaterfall]
|
2695
|
-
);
|
2879
|
+
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2880
|
+
const isLocalized = document?.locale != null;
|
2696
2881
|
return {
|
2697
|
-
|
2698
|
-
|
2699
|
-
|
2700
|
-
|
2701
|
-
|
2702
|
-
}
|
2703
|
-
|
2704
|
-
|
2705
|
-
|
2706
|
-
|
2707
|
-
|
2708
|
-
|
2709
|
-
|
2710
|
-
|
2711
|
-
})
|
2712
|
-
|
2713
|
-
|
2714
|
-
|
2715
|
-
|
2716
|
-
|
2717
|
-
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
|
2724
|
-
|
2725
|
-
|
2726
|
-
|
2727
|
-
|
2728
|
-
|
2729
|
-
|
2730
|
-
|
2731
|
-
|
2732
|
-
|
2733
|
-
|
2734
|
-
|
2735
|
-
|
2736
|
-
|
2737
|
-
|
2738
|
-
|
2739
|
-
|
2740
|
-
|
2741
|
-
|
2742
|
-
|
2882
|
+
disabled: !canDelete || !document,
|
2883
|
+
label: formatMessage(
|
2884
|
+
{
|
2885
|
+
id: "content-manager.actions.delete.label",
|
2886
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2887
|
+
},
|
2888
|
+
{ isLocalized }
|
2889
|
+
),
|
2890
|
+
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2891
|
+
dialog: {
|
2892
|
+
type: "dialog",
|
2893
|
+
title: formatMessage({
|
2894
|
+
id: "app.components.ConfirmDialog.title",
|
2895
|
+
defaultMessage: "Confirmation"
|
2896
|
+
}),
|
2897
|
+
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
2898
|
+
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2899
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2900
|
+
id: "content-manager.actions.delete.dialog.body",
|
2901
|
+
defaultMessage: "Are you sure?"
|
2902
|
+
}) })
|
2903
|
+
] }),
|
2904
|
+
onConfirm: async () => {
|
2905
|
+
if (!listViewPathMatch) {
|
2906
|
+
setSubmitting(true);
|
2907
|
+
}
|
2908
|
+
try {
|
2909
|
+
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2910
|
+
console.error(
|
2911
|
+
"You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2912
|
+
);
|
2913
|
+
toggleNotification({
|
2914
|
+
message: formatMessage({
|
2915
|
+
id: "content-manager.actions.delete.error",
|
2916
|
+
defaultMessage: "An error occurred while trying to delete the document."
|
2917
|
+
}),
|
2918
|
+
type: "danger"
|
2919
|
+
});
|
2920
|
+
return;
|
2921
|
+
}
|
2922
|
+
const res = await deleteAction({
|
2923
|
+
documentId,
|
2924
|
+
model,
|
2925
|
+
collectionType,
|
2926
|
+
params: {
|
2927
|
+
locale: "*"
|
2928
|
+
}
|
2929
|
+
});
|
2930
|
+
if (!("error" in res)) {
|
2931
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2932
|
+
}
|
2933
|
+
} finally {
|
2934
|
+
if (!listViewPathMatch) {
|
2935
|
+
setSubmitting(false);
|
2936
|
+
}
|
2743
2937
|
}
|
2744
|
-
}
|
2745
|
-
return acc;
|
2746
|
-
},
|
2747
|
-
{}
|
2748
|
-
);
|
2749
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2750
|
-
(acc, [attribute, metadata]) => {
|
2751
|
-
return {
|
2752
|
-
...acc,
|
2753
|
-
[attribute]: metadata.edit
|
2754
|
-
};
|
2755
|
-
},
|
2756
|
-
{}
|
2757
|
-
);
|
2758
|
-
return {
|
2759
|
-
layout: panelledEditAttributes,
|
2760
|
-
components: componentEditAttributes,
|
2761
|
-
metadatas: editMetadatas,
|
2762
|
-
settings: {
|
2763
|
-
...data.contentType.settings,
|
2764
|
-
displayName: schema?.info.displayName
|
2938
|
+
}
|
2765
2939
|
},
|
2766
|
-
|
2767
|
-
|
2768
|
-
...schema?.pluginOptions,
|
2769
|
-
...data.contentType.options
|
2770
|
-
}
|
2940
|
+
variant: "danger",
|
2941
|
+
position: ["header", "table-row"]
|
2771
2942
|
};
|
2772
2943
|
};
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
}
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
}
|
2800
|
-
}
|
2801
|
-
);
|
2944
|
+
DeleteAction$1.type = "delete";
|
2945
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2946
|
+
const Panels = () => {
|
2947
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2948
|
+
const [
|
2949
|
+
{
|
2950
|
+
query: { status }
|
2951
|
+
}
|
2952
|
+
] = useQueryParams({
|
2953
|
+
status: "draft"
|
2954
|
+
});
|
2955
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2956
|
+
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2957
|
+
const props = {
|
2958
|
+
activeTab: status,
|
2959
|
+
model,
|
2960
|
+
documentId: id,
|
2961
|
+
document: isCloning ? void 0 : document,
|
2962
|
+
meta: isCloning ? void 0 : meta,
|
2963
|
+
collectionType
|
2964
|
+
};
|
2965
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2966
|
+
DescriptionComponentRenderer,
|
2967
|
+
{
|
2968
|
+
props,
|
2969
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2970
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2971
|
+
}
|
2972
|
+
) });
|
2802
2973
|
};
|
2803
|
-
const
|
2804
|
-
|
2805
|
-
schema,
|
2806
|
-
components
|
2807
|
-
}) => {
|
2808
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2809
|
-
(acc, [attribute, metadata]) => {
|
2810
|
-
return {
|
2811
|
-
...acc,
|
2812
|
-
[attribute]: metadata.list
|
2813
|
-
};
|
2814
|
-
},
|
2815
|
-
{}
|
2816
|
-
);
|
2817
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2818
|
-
data.contentType.layouts.list,
|
2819
|
-
schema?.attributes,
|
2820
|
-
listMetadatas,
|
2821
|
-
{ configurations: data.components, schemas: components },
|
2822
|
-
schemas
|
2823
|
-
);
|
2974
|
+
const ActionsPanel = () => {
|
2975
|
+
const { formatMessage } = useIntl();
|
2824
2976
|
return {
|
2825
|
-
|
2826
|
-
|
2827
|
-
|
2828
|
-
|
2829
|
-
|
2830
|
-
...schema?.pluginOptions,
|
2831
|
-
...data.contentType.options
|
2832
|
-
}
|
2977
|
+
title: formatMessage({
|
2978
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2979
|
+
defaultMessage: "Entry"
|
2980
|
+
}),
|
2981
|
+
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2833
2982
|
};
|
2834
2983
|
};
|
2835
|
-
|
2836
|
-
|
2837
|
-
|
2838
|
-
|
2839
|
-
|
2984
|
+
ActionsPanel.type = "actions";
|
2985
|
+
const ActionsPanelContent = () => {
|
2986
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2987
|
+
const [
|
2988
|
+
{
|
2989
|
+
query: { status = "draft" }
|
2840
2990
|
}
|
2841
|
-
|
2842
|
-
|
2843
|
-
|
2844
|
-
|
2845
|
-
|
2846
|
-
|
2847
|
-
|
2848
|
-
|
2849
|
-
|
2850
|
-
|
2851
|
-
|
2852
|
-
|
2853
|
-
|
2854
|
-
|
2991
|
+
] = useQueryParams();
|
2992
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2993
|
+
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2994
|
+
const props = {
|
2995
|
+
activeTab: status,
|
2996
|
+
model,
|
2997
|
+
documentId: id,
|
2998
|
+
document: isCloning ? void 0 : document,
|
2999
|
+
meta: isCloning ? void 0 : meta,
|
3000
|
+
collectionType
|
3001
|
+
};
|
3002
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3003
|
+
/* @__PURE__ */ jsx(
|
3004
|
+
DescriptionComponentRenderer,
|
3005
|
+
{
|
3006
|
+
props,
|
3007
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3008
|
+
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
3009
|
+
}
|
3010
|
+
),
|
3011
|
+
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3012
|
+
] });
|
2855
3013
|
};
|
3014
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
3015
|
+
return /* @__PURE__ */ jsxs(
|
3016
|
+
Flex,
|
3017
|
+
{
|
3018
|
+
ref,
|
3019
|
+
tag: "aside",
|
3020
|
+
"aria-labelledby": "additional-information",
|
3021
|
+
background: "neutral0",
|
3022
|
+
borderColor: "neutral150",
|
3023
|
+
hasRadius: true,
|
3024
|
+
paddingBottom: 4,
|
3025
|
+
paddingLeft: 4,
|
3026
|
+
paddingRight: 4,
|
3027
|
+
paddingTop: 4,
|
3028
|
+
shadow: "tableShadow",
|
3029
|
+
gap: 3,
|
3030
|
+
direction: "column",
|
3031
|
+
justifyContent: "stretch",
|
3032
|
+
alignItems: "flex-start",
|
3033
|
+
children: [
|
3034
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3035
|
+
children
|
3036
|
+
]
|
3037
|
+
}
|
3038
|
+
);
|
3039
|
+
});
|
2856
3040
|
const ConfirmBulkActionDialog = ({
|
2857
3041
|
onToggleDialog,
|
2858
3042
|
isOpen = false,
|
@@ -2891,6 +3075,7 @@ const ConfirmDialogPublishAll = ({
|
|
2891
3075
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2892
3076
|
const { model, schema } = useDoc();
|
2893
3077
|
const [{ query }] = useQueryParams();
|
3078
|
+
const enableDraftRelationsCount = false;
|
2894
3079
|
const {
|
2895
3080
|
data: countDraftRelations = 0,
|
2896
3081
|
isLoading,
|
@@ -2902,7 +3087,7 @@ const ConfirmDialogPublishAll = ({
|
|
2902
3087
|
locale: query?.plugins?.i18n?.locale
|
2903
3088
|
},
|
2904
3089
|
{
|
2905
|
-
skip:
|
3090
|
+
skip: !enableDraftRelationsCount
|
2906
3091
|
}
|
2907
3092
|
);
|
2908
3093
|
React.useEffect(() => {
|
@@ -3087,7 +3272,7 @@ const SelectedEntriesTableContent = ({
|
|
3087
3272
|
status: row.status
|
3088
3273
|
}
|
3089
3274
|
) }),
|
3090
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3275
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3091
3276
|
IconButton,
|
3092
3277
|
{
|
3093
3278
|
tag: Link,
|
@@ -3096,23 +3281,16 @@ const SelectedEntriesTableContent = ({
|
|
3096
3281
|
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3097
3282
|
},
|
3098
3283
|
state: { from: pathname },
|
3099
|
-
label: formatMessage(
|
3100
|
-
|
3101
|
-
|
3102
|
-
|
3103
|
-
{
|
3104
|
-
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3105
|
-
defaultMessage: "item line {number}"
|
3106
|
-
},
|
3107
|
-
{ number: index2 + 1 }
|
3108
|
-
)
|
3109
|
-
}
|
3110
|
-
),
|
3284
|
+
label: formatMessage({
|
3285
|
+
id: "content-manager.bulk-publish.edit",
|
3286
|
+
defaultMessage: "Edit"
|
3287
|
+
}),
|
3111
3288
|
target: "_blank",
|
3112
3289
|
marginLeft: "auto",
|
3113
|
-
|
3290
|
+
variant: "ghost",
|
3291
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3114
3292
|
}
|
3115
|
-
) })
|
3293
|
+
) }) })
|
3116
3294
|
] }, row.id)) })
|
3117
3295
|
] });
|
3118
3296
|
};
|
@@ -3149,7 +3327,13 @@ const SelectedEntriesModalContent = ({
|
|
3149
3327
|
);
|
3150
3328
|
const { rows, validationErrors } = React.useMemo(() => {
|
3151
3329
|
if (data.length > 0 && schema) {
|
3152
|
-
const validate = createYupSchema(
|
3330
|
+
const validate = createYupSchema(
|
3331
|
+
schema.attributes,
|
3332
|
+
components,
|
3333
|
+
// Since this is the "Publish" action, the validation
|
3334
|
+
// schema must enforce the rules for published entities
|
3335
|
+
{ status: "published" }
|
3336
|
+
);
|
3153
3337
|
const validationErrors2 = {};
|
3154
3338
|
const rows2 = data.map((entry) => {
|
3155
3339
|
try {
|
@@ -3499,7 +3683,7 @@ const TableActions = ({ document }) => {
|
|
3499
3683
|
DescriptionComponentRenderer,
|
3500
3684
|
{
|
3501
3685
|
props,
|
3502
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3686
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3503
3687
|
children: (actions2) => {
|
3504
3688
|
const tableRowActions = actions2.filter((action) => {
|
3505
3689
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3610,7 +3794,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3610
3794
|
}),
|
3611
3795
|
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3612
3796
|
footer: ({ onClose }) => {
|
3613
|
-
return /* @__PURE__ */ jsxs(
|
3797
|
+
return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3614
3798
|
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3615
3799
|
id: "cancel",
|
3616
3800
|
defaultMessage: "Cancel"
|
@@ -3744,17 +3928,27 @@ const HistoryAction = ({ model, document }) => {
|
|
3744
3928
|
const { formatMessage } = useIntl();
|
3745
3929
|
const [{ query }] = useQueryParams();
|
3746
3930
|
const navigate = useNavigate();
|
3931
|
+
const { trackUsage } = useTracking();
|
3932
|
+
const { pathname } = useLocation();
|
3747
3933
|
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3748
3934
|
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3749
3935
|
return null;
|
3750
3936
|
}
|
3937
|
+
const handleOnClick = () => {
|
3938
|
+
const destination = { pathname: "history", search: pluginsQueryParams };
|
3939
|
+
trackUsage("willNavigate", {
|
3940
|
+
from: pathname,
|
3941
|
+
to: `${pathname}/${destination.pathname}`
|
3942
|
+
});
|
3943
|
+
navigate(destination);
|
3944
|
+
};
|
3751
3945
|
return {
|
3752
3946
|
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3753
3947
|
label: formatMessage({
|
3754
3948
|
id: "content-manager.history.document-action",
|
3755
3949
|
defaultMessage: "Content History"
|
3756
3950
|
}),
|
3757
|
-
onClick:
|
3951
|
+
onClick: handleOnClick,
|
3758
3952
|
disabled: (
|
3759
3953
|
/**
|
3760
3954
|
* The user is creating a new document.
|
@@ -3822,6 +4016,72 @@ const { setInitialData } = actions;
|
|
3822
4016
|
const reducer = combineReducers({
|
3823
4017
|
app: reducer$1
|
3824
4018
|
});
|
4019
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4020
|
+
endpoints: (builder) => ({
|
4021
|
+
getPreviewUrl: builder.query({
|
4022
|
+
query({ query, params }) {
|
4023
|
+
return {
|
4024
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4025
|
+
method: "GET",
|
4026
|
+
config: {
|
4027
|
+
params: query
|
4028
|
+
}
|
4029
|
+
};
|
4030
|
+
}
|
4031
|
+
})
|
4032
|
+
})
|
4033
|
+
});
|
4034
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4035
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4036
|
+
const { formatMessage } = useIntl();
|
4037
|
+
const { trackUsage } = useTracking();
|
4038
|
+
const { pathname } = useLocation();
|
4039
|
+
const [{ query }] = useQueryParams();
|
4040
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4041
|
+
params: {
|
4042
|
+
contentType: model
|
4043
|
+
},
|
4044
|
+
query: {
|
4045
|
+
documentId,
|
4046
|
+
locale: document?.locale,
|
4047
|
+
status: document?.status
|
4048
|
+
}
|
4049
|
+
});
|
4050
|
+
if (!data?.data?.url || error) {
|
4051
|
+
return null;
|
4052
|
+
}
|
4053
|
+
const trackNavigation = () => {
|
4054
|
+
const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
|
4055
|
+
trackUsage("willNavigate", { from: pathname, to: destinationPathname });
|
4056
|
+
};
|
4057
|
+
return {
|
4058
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4059
|
+
content: /* @__PURE__ */ jsx(Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsx(
|
4060
|
+
Button,
|
4061
|
+
{
|
4062
|
+
variant: "tertiary",
|
4063
|
+
tag: Link,
|
4064
|
+
to: { pathname: "preview", search: stringify(query, { encode: false }) },
|
4065
|
+
onClick: trackNavigation,
|
4066
|
+
flex: "auto",
|
4067
|
+
children: formatMessage({
|
4068
|
+
id: "content-manager.preview.panel.button",
|
4069
|
+
defaultMessage: "Open preview"
|
4070
|
+
})
|
4071
|
+
}
|
4072
|
+
) })
|
4073
|
+
};
|
4074
|
+
};
|
4075
|
+
const FEATURE_ID = "preview";
|
4076
|
+
const previewAdmin = {
|
4077
|
+
bootstrap(app) {
|
4078
|
+
if (!window.strapi.future.isEnabled(FEATURE_ID)) {
|
4079
|
+
return;
|
4080
|
+
}
|
4081
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4082
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4083
|
+
}
|
4084
|
+
};
|
3825
4085
|
const index = {
|
3826
4086
|
register(app) {
|
3827
4087
|
const cm = new ContentManagerPlugin();
|
@@ -3841,7 +4101,7 @@ const index = {
|
|
3841
4101
|
app.router.addRoute({
|
3842
4102
|
path: "content-manager/*",
|
3843
4103
|
lazy: async () => {
|
3844
|
-
const { Layout } = await import("./layout-
|
4104
|
+
const { Layout } = await import("./layout-DFVbgjp2.mjs");
|
3845
4105
|
return {
|
3846
4106
|
Component: Layout
|
3847
4107
|
};
|
@@ -3854,11 +4114,14 @@ const index = {
|
|
3854
4114
|
if (typeof historyAdmin.bootstrap === "function") {
|
3855
4115
|
historyAdmin.bootstrap(app);
|
3856
4116
|
}
|
4117
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4118
|
+
previewAdmin.bootstrap(app);
|
4119
|
+
}
|
3857
4120
|
},
|
3858
4121
|
async registerTrads({ locales }) {
|
3859
4122
|
const importedTrads = await Promise.all(
|
3860
4123
|
locales.map((locale) => {
|
3861
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-
|
4124
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-CfIXaZf9.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 }) => {
|
3862
4125
|
return {
|
3863
4126
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3864
4127
|
locale
|
@@ -3879,13 +4142,16 @@ export {
|
|
3879
4142
|
BulkActionsRenderer as B,
|
3880
4143
|
COLLECTION_TYPES as C,
|
3881
4144
|
DocumentStatus as D,
|
3882
|
-
|
3883
|
-
|
3884
|
-
|
4145
|
+
extractContentTypeComponents as E,
|
4146
|
+
DEFAULT_SETTINGS as F,
|
4147
|
+
convertEditLayoutToFieldLayouts as G,
|
3885
4148
|
HOOKS as H,
|
3886
4149
|
InjectionZone as I,
|
3887
|
-
|
3888
|
-
|
4150
|
+
useDocument as J,
|
4151
|
+
useGetPreviewUrlQuery as K,
|
4152
|
+
index as L,
|
4153
|
+
useContentManagerContext as M,
|
4154
|
+
useDocumentActions as N,
|
3889
4155
|
Panels as P,
|
3890
4156
|
RelativeTime as R,
|
3891
4157
|
SINGLE_TYPES as S,
|
@@ -3903,18 +4169,18 @@ export {
|
|
3903
4169
|
PERMISSIONS as k,
|
3904
4170
|
DocumentRBAC as l,
|
3905
4171
|
DOCUMENT_META_FIELDS as m,
|
3906
|
-
|
3907
|
-
|
3908
|
-
|
3909
|
-
|
3910
|
-
|
4172
|
+
CLONE_PATH as n,
|
4173
|
+
useDocLayout as o,
|
4174
|
+
useGetContentTypeConfigurationQuery as p,
|
4175
|
+
CREATOR_FIELDS as q,
|
4176
|
+
getMainField as r,
|
3911
4177
|
setInitialData as s,
|
3912
|
-
|
4178
|
+
getDisplayName as t,
|
3913
4179
|
useContentTypeSchema as u,
|
3914
|
-
|
3915
|
-
|
3916
|
-
|
3917
|
-
|
3918
|
-
|
4180
|
+
checkIfAttributeIsDisplayable as v,
|
4181
|
+
useGetAllDocumentsQuery as w,
|
4182
|
+
convertListLayoutToFieldLayouts as x,
|
4183
|
+
capitalise as y,
|
4184
|
+
useUpdateContentTypeConfigurationMutation as z
|
3919
4185
|
};
|
3920
|
-
//# sourceMappingURL=index-
|
4186
|
+
//# sourceMappingURL=index-BW-rXkjn.mjs.map
|