@strapi/content-manager 0.0.0-experimental.e14656d3b8681880212c13260b9a2b340c182f2d → 0.0.0-experimental.e350eaa6073e65190102b4b798c32c287053cc02
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/CardDragPreview-C0QyJgRA.js.map +1 -1
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-D_M8iBw5.js → ComponentConfigurationPage-BTR_hQow.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-D_M8iBw5.js.map → ComponentConfigurationPage-BTR_hQow.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-qemkOlnj.mjs → ComponentConfigurationPage-bLQr82ce.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-qemkOlnj.mjs.map → ComponentConfigurationPage-bLQr82ce.mjs.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
- package/dist/_chunks/{EditConfigurationPage-CjUrEewK.mjs → EditConfigurationPage-BhRSnUsL.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-CjUrEewK.mjs.map → EditConfigurationPage-BhRSnUsL.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-BePwPuHy.js → EditConfigurationPage-z39Wv3E6.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-BePwPuHy.js.map → EditConfigurationPage-z39Wv3E6.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-De8GyU8P.mjs → EditViewPage-BCjNxNlY.mjs} +50 -10
- package/dist/_chunks/EditViewPage-BCjNxNlY.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-B-RJeiJD.js → EditViewPage-wujOq90c.js} +50 -11
- package/dist/_chunks/EditViewPage-wujOq90c.js.map +1 -0
- package/dist/_chunks/{Field-dq8Tg1M_.js → Field-B5QXnctJ.js} +238 -153
- package/dist/_chunks/Field-B5QXnctJ.js.map +1 -0
- package/dist/_chunks/{Field-pb2o8uBe.mjs → Field-Byr3mPTl.mjs} +232 -147
- package/dist/_chunks/Field-Byr3mPTl.mjs.map +1 -0
- package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
- package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
- package/dist/_chunks/{Form-DJn0Dxha.mjs → Form-BZgvE8C8.mjs} +17 -9
- package/dist/_chunks/Form-BZgvE8C8.mjs.map +1 -0
- package/dist/_chunks/{Form-DGIf4jQU.js → Form-D7mexvm3.js} +19 -12
- package/dist/_chunks/Form-D7mexvm3.js.map +1 -0
- package/dist/_chunks/{History-BowL3JKP.mjs → History-CqNgxkqK.mjs} +43 -100
- package/dist/_chunks/History-CqNgxkqK.mjs.map +1 -0
- package/dist/_chunks/{History-Dh2NEHnR.js → History-DYl2A8Z_.js} +42 -100
- package/dist/_chunks/History-DYl2A8Z_.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-BxYCWz9e.js → ListConfigurationPage-BXnu_OoY.js} +7 -7
- package/dist/_chunks/ListConfigurationPage-BXnu_OoY.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-BpVOB-hn.mjs → ListConfigurationPage-BbQjzKkQ.mjs} +7 -6
- package/dist/_chunks/ListConfigurationPage-BbQjzKkQ.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-4XsciqHZ.js → ListViewPage-BtSi8C1l.js} +103 -77
- package/dist/_chunks/ListViewPage-BtSi8C1l.js.map +1 -0
- package/dist/_chunks/{ListViewPage-CXFUjZQC.mjs → ListViewPage-D4ofkbjR.mjs} +99 -72
- package/dist/_chunks/ListViewPage-D4ofkbjR.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-C8OpoHeU.js → NoContentTypePage-CitJeOq4.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-C8OpoHeU.js.map → NoContentTypePage-CitJeOq4.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-DuhOTp3x.mjs → NoContentTypePage-DyUx5mXh.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-DuhOTp3x.mjs.map → NoContentTypePage-DyUx5mXh.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DVz3mzDz.mjs → NoPermissionsPage-DhIiyWkk.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DVz3mzDz.mjs.map → NoPermissionsPage-DhIiyWkk.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-y_r7DVA2.js → NoPermissionsPage-DzgWz0M-.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-y_r7DVA2.js.map → NoPermissionsPage-DzgWz0M-.js.map} +1 -1
- package/dist/_chunks/Preview-BaYGJ0nb.mjs +293 -0
- package/dist/_chunks/Preview-BaYGJ0nb.mjs.map +1 -0
- package/dist/_chunks/Preview-DfNx8Ke-.js +311 -0
- package/dist/_chunks/Preview-DfNx8Ke-.js.map +1 -0
- package/dist/_chunks/{Relations-CVNLrn1Y.mjs → Relations-DM2yUTST.mjs} +75 -41
- package/dist/_chunks/Relations-DM2yUTST.mjs.map +1 -0
- package/dist/_chunks/{Relations-DPFCAa7b.js → Relations-DuKCaXrv.js} +75 -42
- package/dist/_chunks/Relations-DuKCaXrv.js.map +1 -0
- package/dist/_chunks/{en-uOUIxfcQ.js → en-BK8Xyl5I.js} +28 -15
- package/dist/_chunks/{en-uOUIxfcQ.js.map → en-BK8Xyl5I.js.map} +1 -1
- package/dist/_chunks/{en-BrCTWlZv.mjs → en-Dtk_ot79.mjs} +28 -15
- package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-Dtk_ot79.mjs.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
- package/dist/_chunks/{index-C3fJE-1-.js → index-BUWEmX8m.js} +1273 -996
- package/dist/_chunks/index-BUWEmX8m.js.map +1 -0
- package/dist/_chunks/{index-DiMrfcfy.mjs → index-DVAIIsOs.mjs} +1276 -999
- package/dist/_chunks/index-DVAIIsOs.mjs.map +1 -0
- package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
- package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
- package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
- package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
- package/dist/_chunks/{layout-ls3gxfpH.mjs → layout-Bxsv5mP7.mjs} +6 -5
- package/dist/_chunks/{layout-ls3gxfpH.mjs.map → layout-Bxsv5mP7.mjs.map} +1 -1
- package/dist/_chunks/{layout-C788OmNr.js → layout-C3fN7Ejz.js} +7 -7
- package/dist/_chunks/{layout-C788OmNr.js.map → layout-C3fN7Ejz.js.map} +1 -1
- 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-DYeotliT.js → relations-BPZKAoEY.js} +6 -7
- package/dist/_chunks/relations-BPZKAoEY.js.map +1 -0
- package/dist/_chunks/{relations-CLcOmGO0.mjs → relations-o3pPhzY4.mjs} +6 -7
- package/dist/_chunks/relations-o3pPhzY4.mjs.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +4 -3
- package/dist/admin/src/content-manager.d.ts +3 -2
- package/dist/admin/src/exports.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/DocumentActions.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +0 -32
- 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/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/documents.d.ts +3 -4
- package/dist/server/index.js +453 -201
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +453 -200
- 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/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +13 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +16 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +32 -0
- package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview.d.ts +12 -0
- package/dist/server/src/preview/services/preview.d.ts.map +1 -0
- package/dist/server/src/preview/utils.d.ts +19 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +8 -8
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -4
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/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 +17 -15
- package/dist/_chunks/EditViewPage-B-RJeiJD.js.map +0 -1
- package/dist/_chunks/EditViewPage-De8GyU8P.mjs.map +0 -1
- package/dist/_chunks/Field-dq8Tg1M_.js.map +0 -1
- package/dist/_chunks/Field-pb2o8uBe.mjs.map +0 -1
- package/dist/_chunks/Form-DGIf4jQU.js.map +0 -1
- package/dist/_chunks/Form-DJn0Dxha.mjs.map +0 -1
- package/dist/_chunks/History-BowL3JKP.mjs.map +0 -1
- package/dist/_chunks/History-Dh2NEHnR.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-BpVOB-hn.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-BxYCWz9e.js.map +0 -1
- package/dist/_chunks/ListViewPage-4XsciqHZ.js.map +0 -1
- package/dist/_chunks/ListViewPage-CXFUjZQC.mjs.map +0 -1
- package/dist/_chunks/Relations-CVNLrn1Y.mjs.map +0 -1
- package/dist/_chunks/Relations-DPFCAa7b.js.map +0 -1
- package/dist/_chunks/index-C3fJE-1-.js.map +0 -1
- package/dist/_chunks/index-DiMrfcfy.mjs.map +0 -1
- package/dist/_chunks/relations-CLcOmGO0.mjs.map +0 -1
- package/dist/_chunks/relations-DYeotliT.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
@@ -4,18 +4,18 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const strapiAdmin = require("@strapi/admin/strapi-admin");
|
5
5
|
const React = require("react");
|
6
6
|
const designSystem = require("@strapi/design-system");
|
7
|
+
const mapValues = require("lodash/fp/mapValues");
|
7
8
|
const reactIntl = require("react-intl");
|
8
9
|
const reactRouterDom = require("react-router-dom");
|
9
10
|
const styledComponents = require("styled-components");
|
10
11
|
const yup = require("yup");
|
12
|
+
const qs = require("qs");
|
11
13
|
const pipe = require("lodash/fp/pipe");
|
12
14
|
const dateFns = require("date-fns");
|
13
|
-
const qs = require("qs");
|
14
15
|
const toolkit = require("@reduxjs/toolkit");
|
15
16
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
16
17
|
function _interopNamespace(e) {
|
17
|
-
if (e && e.__esModule)
|
18
|
-
return e;
|
18
|
+
if (e && e.__esModule) return e;
|
19
19
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
20
20
|
if (e) {
|
21
21
|
for (const k in e) {
|
@@ -32,15 +32,23 @@ function _interopNamespace(e) {
|
|
32
32
|
return Object.freeze(n);
|
33
33
|
}
|
34
34
|
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
35
|
+
const mapValues__default = /* @__PURE__ */ _interopDefault(mapValues);
|
35
36
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
36
37
|
const pipe__default = /* @__PURE__ */ _interopDefault(pipe);
|
37
|
-
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
38
|
+
const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
|
38
39
|
const v = glob[path];
|
39
40
|
if (v) {
|
40
41
|
return typeof v === "function" ? v() : Promise.resolve(v);
|
41
42
|
}
|
42
43
|
return new Promise((_, reject) => {
|
43
|
-
(typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
|
44
|
+
(typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
|
45
|
+
reject.bind(
|
46
|
+
null,
|
47
|
+
new Error(
|
48
|
+
"Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
|
49
|
+
)
|
50
|
+
)
|
51
|
+
);
|
44
52
|
});
|
45
53
|
};
|
46
54
|
const PLUGIN_ID = "content-manager";
|
@@ -121,6 +129,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
121
129
|
if (!slug) {
|
122
130
|
throw new Error("Cannot find the slug param in the URL");
|
123
131
|
}
|
132
|
+
const [{ rawQuery }] = strapiAdmin.useQueryParams();
|
124
133
|
const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
|
125
134
|
const contentTypePermissions = React__namespace.useMemo(() => {
|
126
135
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -131,7 +140,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
131
140
|
return { ...acc, [action]: [permission] };
|
132
141
|
}, {});
|
133
142
|
}, [slug, userPermissions]);
|
134
|
-
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
143
|
+
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
144
|
+
contentTypePermissions,
|
145
|
+
permissions ?? void 0,
|
146
|
+
// TODO: useRBAC context should be typed and built differently
|
147
|
+
// We are passing raw query as context to the hook so that it can
|
148
|
+
// rely on the locale provided from DocumentRBAC for its permission calculations.
|
149
|
+
rawQuery
|
150
|
+
);
|
135
151
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
136
152
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
137
153
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -286,7 +302,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
286
302
|
url: `/content-manager/collection-types/${model}`,
|
287
303
|
method: "GET",
|
288
304
|
config: {
|
289
|
-
params
|
305
|
+
params: qs.stringify(params, { encode: true })
|
290
306
|
}
|
291
307
|
}),
|
292
308
|
providesTags: (result, _error, arg) => {
|
@@ -465,8 +481,7 @@ const {
|
|
465
481
|
useUnpublishManyDocumentsMutation
|
466
482
|
} = documentApi;
|
467
483
|
const buildValidParams = (query) => {
|
468
|
-
if (!query)
|
469
|
-
return query;
|
484
|
+
if (!query) return query;
|
470
485
|
const { plugins: _, ...validQueryParams } = {
|
471
486
|
...query,
|
472
487
|
...Object.values(query?.plugins ?? {}).reduce(
|
@@ -474,14 +489,29 @@ const buildValidParams = (query) => {
|
|
474
489
|
{}
|
475
490
|
)
|
476
491
|
};
|
477
|
-
if ("_q" in validQueryParams) {
|
478
|
-
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
479
|
-
}
|
480
492
|
return validQueryParams;
|
481
493
|
};
|
482
494
|
const isBaseQueryError = (error) => {
|
483
495
|
return error.name !== void 0;
|
484
496
|
};
|
497
|
+
const arrayValidator = (attribute, options) => ({
|
498
|
+
message: strapiAdmin.translatedErrors.required,
|
499
|
+
test(value) {
|
500
|
+
if (options.status === "draft") {
|
501
|
+
return true;
|
502
|
+
}
|
503
|
+
if (!attribute.required) {
|
504
|
+
return true;
|
505
|
+
}
|
506
|
+
if (!value) {
|
507
|
+
return false;
|
508
|
+
}
|
509
|
+
if (Array.isArray(value) && value.length === 0) {
|
510
|
+
return false;
|
511
|
+
}
|
512
|
+
return true;
|
513
|
+
}
|
514
|
+
});
|
485
515
|
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
486
516
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
487
517
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
@@ -489,6 +519,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
489
519
|
return acc;
|
490
520
|
}
|
491
521
|
const validations = [
|
522
|
+
addNullableValidation,
|
492
523
|
addRequiredValidation,
|
493
524
|
addMinLengthValidation,
|
494
525
|
addMaxLengthValidation,
|
@@ -505,12 +536,12 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
505
536
|
...acc,
|
506
537
|
[name]: transformSchema(
|
507
538
|
yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
|
508
|
-
)
|
539
|
+
).test(arrayValidator(attribute, options))
|
509
540
|
};
|
510
541
|
} else {
|
511
542
|
return {
|
512
543
|
...acc,
|
513
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
544
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
514
545
|
};
|
515
546
|
}
|
516
547
|
}
|
@@ -532,7 +563,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
532
563
|
}
|
533
564
|
)
|
534
565
|
)
|
535
|
-
)
|
566
|
+
).test(arrayValidator(attribute, options))
|
536
567
|
};
|
537
568
|
case "relation":
|
538
569
|
return {
|
@@ -544,7 +575,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
544
575
|
} else if (Array.isArray(value)) {
|
545
576
|
return yup__namespace.array().of(
|
546
577
|
yup__namespace.object().shape({
|
547
|
-
id: yup__namespace.
|
578
|
+
id: yup__namespace.number().required()
|
548
579
|
})
|
549
580
|
);
|
550
581
|
} else if (typeof value === "object") {
|
@@ -630,17 +661,17 @@ const nullableSchema = (schema) => {
|
|
630
661
|
schema
|
631
662
|
);
|
632
663
|
};
|
664
|
+
const addNullableValidation = () => (schema) => {
|
665
|
+
return nullableSchema(schema);
|
666
|
+
};
|
633
667
|
const addRequiredValidation = (attribute, options) => (schema) => {
|
634
|
-
if (options.status === "draft") {
|
635
|
-
return
|
636
|
-
}
|
637
|
-
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
638
|
-
return schema.min(1, strapiAdmin.translatedErrors.required);
|
668
|
+
if (options.status === "draft" || !attribute.required) {
|
669
|
+
return schema;
|
639
670
|
}
|
640
|
-
if (attribute.required &&
|
671
|
+
if (attribute.required && "required" in schema) {
|
641
672
|
return schema.required(strapiAdmin.translatedErrors.required);
|
642
673
|
}
|
643
|
-
return
|
674
|
+
return schema;
|
644
675
|
};
|
645
676
|
const addMinLengthValidation = (attribute, options) => (schema) => {
|
646
677
|
if (options.status === "draft") {
|
@@ -668,31 +699,12 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
668
699
|
return schema;
|
669
700
|
};
|
670
701
|
const addMinValidation = (attribute, options) => (schema) => {
|
671
|
-
if ("
|
702
|
+
if (options.status === "draft") {
|
703
|
+
return schema;
|
704
|
+
}
|
705
|
+
if ("min" in attribute && "min" in schema) {
|
672
706
|
const min = toInteger(attribute.min);
|
673
|
-
if (
|
674
|
-
if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
|
675
|
-
return schema.test(
|
676
|
-
"custom-min",
|
677
|
-
{
|
678
|
-
...strapiAdmin.translatedErrors.min,
|
679
|
-
values: {
|
680
|
-
min: attribute.min
|
681
|
-
}
|
682
|
-
},
|
683
|
-
(value) => {
|
684
|
-
if (!value) {
|
685
|
-
return true;
|
686
|
-
}
|
687
|
-
if (Array.isArray(value) && value.length === 0) {
|
688
|
-
return true;
|
689
|
-
}
|
690
|
-
return value.length >= min;
|
691
|
-
}
|
692
|
-
);
|
693
|
-
}
|
694
|
-
}
|
695
|
-
if ("min" in schema && min) {
|
707
|
+
if (min) {
|
696
708
|
return schema.min(min, {
|
697
709
|
...strapiAdmin.translatedErrors.min,
|
698
710
|
values: {
|
@@ -810,19 +822,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
810
822
|
}, {});
|
811
823
|
return componentsByKey;
|
812
824
|
};
|
813
|
-
const
|
825
|
+
const HOOKS = {
|
826
|
+
/**
|
827
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
828
|
+
* @constant
|
829
|
+
* @type {string}
|
830
|
+
*/
|
831
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
832
|
+
/**
|
833
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
834
|
+
* @constant
|
835
|
+
* @type {string}
|
836
|
+
*/
|
837
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
838
|
+
/**
|
839
|
+
* Hook that allows to mutate the CM's edit view layout
|
840
|
+
* @constant
|
841
|
+
* @type {string}
|
842
|
+
*/
|
843
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
844
|
+
/**
|
845
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
846
|
+
* @constant
|
847
|
+
* @type {string}
|
848
|
+
*/
|
849
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
850
|
+
};
|
851
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
852
|
+
endpoints: (builder) => ({
|
853
|
+
getContentTypeConfiguration: builder.query({
|
854
|
+
query: (uid) => ({
|
855
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
856
|
+
method: "GET"
|
857
|
+
}),
|
858
|
+
transformResponse: (response) => response.data,
|
859
|
+
providesTags: (_result, _error, uid) => [
|
860
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
861
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
862
|
+
]
|
863
|
+
}),
|
864
|
+
getAllContentTypeSettings: builder.query({
|
865
|
+
query: () => "/content-manager/content-types-settings",
|
866
|
+
transformResponse: (response) => response.data,
|
867
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
868
|
+
}),
|
869
|
+
updateContentTypeConfiguration: builder.mutation({
|
870
|
+
query: ({ uid, ...body }) => ({
|
871
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
872
|
+
method: "PUT",
|
873
|
+
data: body
|
874
|
+
}),
|
875
|
+
transformResponse: (response) => response.data,
|
876
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
877
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
878
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
879
|
+
// Is this necessary?
|
880
|
+
{ type: "InitialData" }
|
881
|
+
]
|
882
|
+
})
|
883
|
+
})
|
884
|
+
});
|
885
|
+
const {
|
886
|
+
useGetContentTypeConfigurationQuery,
|
887
|
+
useGetAllContentTypeSettingsQuery,
|
888
|
+
useUpdateContentTypeConfigurationMutation
|
889
|
+
} = contentTypesApi;
|
890
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
891
|
+
const { type } = attribute;
|
892
|
+
if (type === "relation") {
|
893
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
894
|
+
}
|
895
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
896
|
+
};
|
897
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
898
|
+
if (!mainFieldName) {
|
899
|
+
return void 0;
|
900
|
+
}
|
901
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
902
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
903
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
904
|
+
);
|
905
|
+
return {
|
906
|
+
name: mainFieldName,
|
907
|
+
type: mainFieldType ?? "string"
|
908
|
+
};
|
909
|
+
};
|
910
|
+
const DEFAULT_SETTINGS = {
|
911
|
+
bulkable: false,
|
912
|
+
filterable: false,
|
913
|
+
searchable: false,
|
914
|
+
pagination: false,
|
915
|
+
defaultSortBy: "",
|
916
|
+
defaultSortOrder: "asc",
|
917
|
+
mainField: "id",
|
918
|
+
pageSize: 10
|
919
|
+
};
|
920
|
+
const useDocumentLayout = (model) => {
|
921
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
922
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
923
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
814
924
|
const { toggleNotification } = strapiAdmin.useNotification();
|
815
925
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
926
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
816
927
|
const {
|
817
|
-
|
818
|
-
isLoading:
|
819
|
-
|
820
|
-
|
821
|
-
} =
|
822
|
-
|
823
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
824
|
-
});
|
825
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
928
|
+
data,
|
929
|
+
isLoading: isLoadingConfigs,
|
930
|
+
error,
|
931
|
+
isFetching: isFetchingConfigs
|
932
|
+
} = useGetContentTypeConfigurationQuery(model);
|
933
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
826
934
|
React__namespace.useEffect(() => {
|
827
935
|
if (error) {
|
828
936
|
toggleNotification({
|
@@ -830,398 +938,654 @@ const useDocument = (args, opts) => {
|
|
830
938
|
message: formatAPIError(error)
|
831
939
|
});
|
832
940
|
}
|
833
|
-
}, [
|
834
|
-
const
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
(document) => {
|
842
|
-
if (!validationSchema) {
|
843
|
-
throw new Error(
|
844
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
845
|
-
);
|
846
|
-
}
|
847
|
-
try {
|
848
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
849
|
-
return null;
|
850
|
-
} catch (error2) {
|
851
|
-
if (error2 instanceof yup.ValidationError) {
|
852
|
-
return strapiAdmin.getYupValidationErrors(error2);
|
853
|
-
}
|
854
|
-
throw error2;
|
855
|
-
}
|
941
|
+
}, [error, formatAPIError, toggleNotification]);
|
942
|
+
const editLayout = React__namespace.useMemo(
|
943
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
944
|
+
layout: [],
|
945
|
+
components: {},
|
946
|
+
metadatas: {},
|
947
|
+
options: {},
|
948
|
+
settings: DEFAULT_SETTINGS
|
856
949
|
},
|
857
|
-
[
|
950
|
+
[data, isLoading, schemas, schema, components]
|
951
|
+
);
|
952
|
+
const listLayout = React__namespace.useMemo(() => {
|
953
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
954
|
+
layout: [],
|
955
|
+
metadatas: {},
|
956
|
+
options: {},
|
957
|
+
settings: DEFAULT_SETTINGS
|
958
|
+
};
|
959
|
+
}, [data, isLoading, schemas, schema, components]);
|
960
|
+
const { layout: edit } = React__namespace.useMemo(
|
961
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
962
|
+
layout: editLayout,
|
963
|
+
query
|
964
|
+
}),
|
965
|
+
[editLayout, query, runHookWaterfall]
|
858
966
|
);
|
859
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
860
967
|
return {
|
861
|
-
|
862
|
-
document: data?.data,
|
863
|
-
meta: data?.meta,
|
968
|
+
error,
|
864
969
|
isLoading,
|
865
|
-
|
866
|
-
|
867
|
-
};
|
868
|
-
};
|
869
|
-
const useDoc = () => {
|
870
|
-
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
871
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
872
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
873
|
-
if (!collectionType) {
|
874
|
-
throw new Error("Could not find collectionType in url params");
|
875
|
-
}
|
876
|
-
if (!slug) {
|
877
|
-
throw new Error("Could not find model in url params");
|
878
|
-
}
|
879
|
-
return {
|
880
|
-
collectionType,
|
881
|
-
model: slug,
|
882
|
-
id: origin || id === "create" ? void 0 : id,
|
883
|
-
...useDocument(
|
884
|
-
{ documentId: origin || id, model: slug, collectionType, params },
|
885
|
-
{
|
886
|
-
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
887
|
-
}
|
888
|
-
)
|
970
|
+
edit,
|
971
|
+
list: listLayout
|
889
972
|
};
|
890
973
|
};
|
891
|
-
const
|
892
|
-
|
893
|
-
|
894
|
-
}
|
895
|
-
return Object.keys(trad).reduce((acc, current) => {
|
896
|
-
acc[`${pluginId}.${current}`] = trad[current];
|
897
|
-
return acc;
|
898
|
-
}, {});
|
899
|
-
};
|
900
|
-
const getTranslation = (id) => `content-manager.${id}`;
|
901
|
-
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
902
|
-
id: "notification.error",
|
903
|
-
defaultMessage: "An error occurred, please try again"
|
974
|
+
const useDocLayout = () => {
|
975
|
+
const { model } = useDoc();
|
976
|
+
return useDocumentLayout(model);
|
904
977
|
};
|
905
|
-
const
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
const
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
});
|
927
|
-
return { error: res.error };
|
928
|
-
}
|
929
|
-
toggleNotification({
|
930
|
-
type: "success",
|
931
|
-
message: formatMessage({
|
932
|
-
id: getTranslation("success.record.delete"),
|
933
|
-
defaultMessage: "Deleted document"
|
934
|
-
})
|
935
|
-
});
|
936
|
-
trackUsage("didDeleteEntry", trackerProperty);
|
937
|
-
return res.data;
|
938
|
-
} catch (err) {
|
939
|
-
toggleNotification({
|
940
|
-
type: "danger",
|
941
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
942
|
-
});
|
943
|
-
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
944
|
-
throw err;
|
978
|
+
const formatEditLayout = (data, {
|
979
|
+
schemas,
|
980
|
+
schema,
|
981
|
+
components
|
982
|
+
}) => {
|
983
|
+
let currentPanelIndex = 0;
|
984
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
985
|
+
data.contentType.layouts.edit,
|
986
|
+
schema?.attributes,
|
987
|
+
data.contentType.metadatas,
|
988
|
+
{ configurations: data.components, schemas: components },
|
989
|
+
schemas
|
990
|
+
).reduce((panels, row) => {
|
991
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
992
|
+
panels.push([row]);
|
993
|
+
currentPanelIndex += 2;
|
994
|
+
} else {
|
995
|
+
if (!panels[currentPanelIndex]) {
|
996
|
+
panels.push([row]);
|
997
|
+
} else {
|
998
|
+
panels[currentPanelIndex].push(row);
|
945
999
|
}
|
946
|
-
}
|
947
|
-
|
948
|
-
);
|
949
|
-
const
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
message: formatAPIError(res.error)
|
963
|
-
});
|
964
|
-
return { error: res.error };
|
1000
|
+
}
|
1001
|
+
return panels;
|
1002
|
+
}, []);
|
1003
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
1004
|
+
(acc, [uid, configuration]) => {
|
1005
|
+
acc[uid] = {
|
1006
|
+
layout: convertEditLayoutToFieldLayouts(
|
1007
|
+
configuration.layouts.edit,
|
1008
|
+
components[uid].attributes,
|
1009
|
+
configuration.metadatas,
|
1010
|
+
{ configurations: data.components, schemas: components }
|
1011
|
+
),
|
1012
|
+
settings: {
|
1013
|
+
...configuration.settings,
|
1014
|
+
icon: components[uid].info.icon,
|
1015
|
+
displayName: components[uid].info.displayName
|
965
1016
|
}
|
966
|
-
|
967
|
-
|
968
|
-
title: formatMessage({
|
969
|
-
id: getTranslation("success.records.delete"),
|
970
|
-
defaultMessage: "Successfully deleted."
|
971
|
-
}),
|
972
|
-
message: ""
|
973
|
-
});
|
974
|
-
trackUsage("didBulkDeleteEntries");
|
975
|
-
return res.data;
|
976
|
-
} catch (err) {
|
977
|
-
toggleNotification({
|
978
|
-
type: "danger",
|
979
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
980
|
-
});
|
981
|
-
trackUsage("didNotBulkDeleteEntries");
|
982
|
-
throw err;
|
983
|
-
}
|
1017
|
+
};
|
1018
|
+
return acc;
|
984
1019
|
},
|
985
|
-
|
1020
|
+
{}
|
986
1021
|
);
|
987
|
-
const
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
model,
|
994
|
-
documentId,
|
995
|
-
params
|
996
|
-
});
|
997
|
-
if ("error" in res) {
|
998
|
-
toggleNotification({
|
999
|
-
type: "danger",
|
1000
|
-
message: formatAPIError(res.error)
|
1001
|
-
});
|
1002
|
-
return { error: res.error };
|
1003
|
-
}
|
1004
|
-
toggleNotification({
|
1005
|
-
type: "success",
|
1006
|
-
message: formatMessage({
|
1007
|
-
id: "content-manager.success.record.discard",
|
1008
|
-
defaultMessage: "Changes discarded"
|
1009
|
-
})
|
1010
|
-
});
|
1011
|
-
return res.data;
|
1012
|
-
} catch (err) {
|
1013
|
-
toggleNotification({
|
1014
|
-
type: "danger",
|
1015
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1016
|
-
});
|
1017
|
-
throw err;
|
1018
|
-
}
|
1022
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1023
|
+
(acc, [attribute, metadata]) => {
|
1024
|
+
return {
|
1025
|
+
...acc,
|
1026
|
+
[attribute]: metadata.edit
|
1027
|
+
};
|
1019
1028
|
},
|
1020
|
-
|
1029
|
+
{}
|
1021
1030
|
);
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
model,
|
1030
|
-
documentId,
|
1031
|
-
data,
|
1032
|
-
params
|
1033
|
-
});
|
1034
|
-
if ("error" in res) {
|
1035
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1036
|
-
return { error: res.error };
|
1037
|
-
}
|
1038
|
-
trackUsage("didPublishEntry");
|
1039
|
-
toggleNotification({
|
1040
|
-
type: "success",
|
1041
|
-
message: formatMessage({
|
1042
|
-
id: getTranslation("success.record.publish"),
|
1043
|
-
defaultMessage: "Published document"
|
1044
|
-
})
|
1045
|
-
});
|
1046
|
-
return res.data;
|
1047
|
-
} catch (err) {
|
1048
|
-
toggleNotification({
|
1049
|
-
type: "danger",
|
1050
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1051
|
-
});
|
1052
|
-
throw err;
|
1053
|
-
}
|
1031
|
+
return {
|
1032
|
+
layout: panelledEditAttributes,
|
1033
|
+
components: componentEditAttributes,
|
1034
|
+
metadatas: editMetadatas,
|
1035
|
+
settings: {
|
1036
|
+
...data.contentType.settings,
|
1037
|
+
displayName: schema?.info.displayName
|
1054
1038
|
},
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
return { error: res.error };
|
1069
|
-
}
|
1070
|
-
toggleNotification({
|
1071
|
-
type: "success",
|
1072
|
-
message: formatMessage({
|
1073
|
-
id: getTranslation("success.record.publish"),
|
1074
|
-
defaultMessage: "Published document"
|
1075
|
-
})
|
1076
|
-
});
|
1077
|
-
return res.data;
|
1078
|
-
} catch (err) {
|
1079
|
-
toggleNotification({
|
1080
|
-
type: "danger",
|
1081
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1082
|
-
});
|
1083
|
-
throw err;
|
1039
|
+
options: {
|
1040
|
+
...schema?.options,
|
1041
|
+
...schema?.pluginOptions,
|
1042
|
+
...data.contentType.options
|
1043
|
+
}
|
1044
|
+
};
|
1045
|
+
};
|
1046
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1047
|
+
return rows.map(
|
1048
|
+
(row) => row.map((field) => {
|
1049
|
+
const attribute = attributes[field.name];
|
1050
|
+
if (!attribute) {
|
1051
|
+
return null;
|
1084
1052
|
}
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1053
|
+
const { edit: metadata } = metadatas[field.name];
|
1054
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1055
|
+
return {
|
1056
|
+
attribute,
|
1057
|
+
disabled: !metadata.editable,
|
1058
|
+
hint: metadata.description,
|
1059
|
+
label: metadata.label ?? "",
|
1060
|
+
name: field.name,
|
1061
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1062
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1063
|
+
schemas,
|
1064
|
+
components: components?.schemas ?? {}
|
1065
|
+
}),
|
1066
|
+
placeholder: metadata.placeholder ?? "",
|
1067
|
+
required: attribute.required ?? false,
|
1068
|
+
size: field.size,
|
1069
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1070
|
+
visible: metadata.visible ?? true,
|
1071
|
+
type: attribute.type
|
1072
|
+
};
|
1073
|
+
}).filter((field) => field !== null)
|
1093
1074
|
);
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1075
|
+
};
|
1076
|
+
const formatListLayout = (data, {
|
1077
|
+
schemas,
|
1078
|
+
schema,
|
1079
|
+
components
|
1080
|
+
}) => {
|
1081
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1082
|
+
(acc, [attribute, metadata]) => {
|
1083
|
+
return {
|
1084
|
+
...acc,
|
1085
|
+
[attribute]: metadata.list
|
1086
|
+
};
|
1087
|
+
},
|
1088
|
+
{}
|
1089
|
+
);
|
1090
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1091
|
+
data.contentType.layouts.list,
|
1092
|
+
schema?.attributes,
|
1093
|
+
listMetadatas,
|
1094
|
+
{ configurations: data.components, schemas: components },
|
1095
|
+
schemas
|
1096
|
+
);
|
1097
|
+
return {
|
1098
|
+
layout: listAttributes,
|
1099
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1100
|
+
metadatas: listMetadatas,
|
1101
|
+
options: {
|
1102
|
+
...schema?.options,
|
1103
|
+
...schema?.pluginOptions,
|
1104
|
+
...data.contentType.options
|
1105
|
+
}
|
1106
|
+
};
|
1107
|
+
};
|
1108
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1109
|
+
return columns.map((name) => {
|
1110
|
+
const attribute = attributes[name];
|
1111
|
+
if (!attribute) {
|
1112
|
+
return null;
|
1113
|
+
}
|
1114
|
+
const metadata = metadatas[name];
|
1115
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1116
|
+
return {
|
1117
|
+
attribute,
|
1118
|
+
label: metadata.label ?? "",
|
1119
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1120
|
+
schemas,
|
1121
|
+
components: components?.schemas ?? {}
|
1122
|
+
}),
|
1123
|
+
name,
|
1124
|
+
searchable: metadata.searchable ?? true,
|
1125
|
+
sortable: metadata.sortable ?? true
|
1126
|
+
};
|
1127
|
+
}).filter((field) => field !== null);
|
1128
|
+
};
|
1129
|
+
const useDocument = (args, opts) => {
|
1130
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1131
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1132
|
+
const {
|
1133
|
+
currentData: data,
|
1134
|
+
isLoading: isLoadingDocument,
|
1135
|
+
isFetching: isFetchingDocument,
|
1136
|
+
error
|
1137
|
+
} = useGetDocumentQuery(args, {
|
1138
|
+
...opts,
|
1139
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1140
|
+
});
|
1141
|
+
const {
|
1142
|
+
components,
|
1143
|
+
schema,
|
1144
|
+
schemas,
|
1145
|
+
isLoading: isLoadingSchema
|
1146
|
+
} = useContentTypeSchema(args.model);
|
1147
|
+
React__namespace.useEffect(() => {
|
1148
|
+
if (error) {
|
1149
|
+
toggleNotification({
|
1150
|
+
type: "danger",
|
1151
|
+
message: formatAPIError(error)
|
1152
|
+
});
|
1153
|
+
}
|
1154
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1155
|
+
const validationSchema = React__namespace.useMemo(() => {
|
1156
|
+
if (!schema) {
|
1157
|
+
return null;
|
1158
|
+
}
|
1159
|
+
return createYupSchema(schema.attributes, components);
|
1160
|
+
}, [schema, components]);
|
1161
|
+
const validate = React__namespace.useCallback(
|
1162
|
+
(document) => {
|
1163
|
+
if (!validationSchema) {
|
1164
|
+
throw new Error(
|
1165
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1166
|
+
);
|
1167
|
+
}
|
1168
|
+
try {
|
1169
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1170
|
+
return null;
|
1171
|
+
} catch (error2) {
|
1172
|
+
if (error2 instanceof yup.ValidationError) {
|
1173
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
1110
1174
|
}
|
1111
|
-
|
1112
|
-
toggleNotification({
|
1113
|
-
type: "success",
|
1114
|
-
message: formatMessage({
|
1115
|
-
id: getTranslation("success.record.save"),
|
1116
|
-
defaultMessage: "Saved document"
|
1117
|
-
})
|
1118
|
-
});
|
1119
|
-
return res.data;
|
1120
|
-
} catch (err) {
|
1121
|
-
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1122
|
-
toggleNotification({
|
1123
|
-
type: "danger",
|
1124
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1125
|
-
});
|
1126
|
-
throw err;
|
1175
|
+
throw error2;
|
1127
1176
|
}
|
1128
1177
|
},
|
1129
|
-
[
|
1178
|
+
[validationSchema]
|
1130
1179
|
);
|
1131
|
-
const
|
1132
|
-
const
|
1133
|
-
|
1180
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1181
|
+
const hasError = !!error;
|
1182
|
+
return {
|
1183
|
+
components,
|
1184
|
+
document: data?.data,
|
1185
|
+
meta: data?.meta,
|
1186
|
+
isLoading,
|
1187
|
+
hasError,
|
1188
|
+
schema,
|
1189
|
+
schemas,
|
1190
|
+
validate
|
1191
|
+
};
|
1192
|
+
};
|
1193
|
+
const useDoc = () => {
|
1194
|
+
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
1195
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
1196
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1197
|
+
if (!collectionType) {
|
1198
|
+
throw new Error("Could not find collectionType in url params");
|
1199
|
+
}
|
1200
|
+
if (!slug) {
|
1201
|
+
throw new Error("Could not find model in url params");
|
1202
|
+
}
|
1203
|
+
const document = useDocument(
|
1204
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1205
|
+
{
|
1206
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1207
|
+
}
|
1208
|
+
);
|
1209
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
1210
|
+
return {
|
1211
|
+
collectionType,
|
1212
|
+
model: slug,
|
1213
|
+
id: returnId,
|
1214
|
+
...document
|
1215
|
+
};
|
1216
|
+
};
|
1217
|
+
const useContentManagerContext = () => {
|
1218
|
+
const {
|
1219
|
+
collectionType,
|
1220
|
+
model,
|
1221
|
+
id,
|
1222
|
+
components,
|
1223
|
+
isLoading: isLoadingDoc,
|
1224
|
+
schema,
|
1225
|
+
schemas
|
1226
|
+
} = useDoc();
|
1227
|
+
const layout = useDocumentLayout(model);
|
1228
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1229
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1230
|
+
const slug = model;
|
1231
|
+
const isCreatingEntry = id === "create";
|
1232
|
+
useContentTypeSchema();
|
1233
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1234
|
+
const error = layout.error;
|
1235
|
+
return {
|
1236
|
+
error,
|
1237
|
+
isLoading,
|
1238
|
+
// Base metadata
|
1239
|
+
model,
|
1240
|
+
collectionType,
|
1241
|
+
id,
|
1242
|
+
slug,
|
1243
|
+
isCreatingEntry,
|
1244
|
+
isSingleType,
|
1245
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1246
|
+
// All schema infos
|
1247
|
+
components,
|
1248
|
+
contentType: schema,
|
1249
|
+
contentTypes: schemas,
|
1250
|
+
// Form state
|
1251
|
+
form,
|
1252
|
+
// layout infos
|
1253
|
+
layout
|
1254
|
+
};
|
1255
|
+
};
|
1256
|
+
const prefixPluginTranslations = (trad, pluginId) => {
|
1257
|
+
return Object.keys(trad).reduce((acc, current) => {
|
1258
|
+
acc[`${pluginId}.${current}`] = trad[current];
|
1259
|
+
return acc;
|
1260
|
+
}, {});
|
1261
|
+
};
|
1262
|
+
const getTranslation = (id) => `content-manager.${id}`;
|
1263
|
+
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
1264
|
+
id: "notification.error",
|
1265
|
+
defaultMessage: "An error occurred, please try again"
|
1266
|
+
};
|
1267
|
+
const useDocumentActions = () => {
|
1268
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1269
|
+
const { formatMessage } = reactIntl.useIntl();
|
1270
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
1271
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1272
|
+
const navigate = reactRouterDom.useNavigate();
|
1273
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
1274
|
+
const [deleteDocument] = useDeleteDocumentMutation();
|
1275
|
+
const _delete = React__namespace.useCallback(
|
1276
|
+
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
1134
1277
|
try {
|
1135
|
-
trackUsage("
|
1136
|
-
const res = await
|
1278
|
+
trackUsage("willDeleteEntry", trackerProperty);
|
1279
|
+
const res = await deleteDocument({
|
1137
1280
|
collectionType,
|
1138
1281
|
model,
|
1139
1282
|
documentId,
|
1140
|
-
params
|
1141
|
-
data: {
|
1142
|
-
discardDraft
|
1143
|
-
}
|
1283
|
+
params
|
1144
1284
|
});
|
1145
1285
|
if ("error" in res) {
|
1146
|
-
toggleNotification({
|
1286
|
+
toggleNotification({
|
1287
|
+
type: "danger",
|
1288
|
+
message: formatAPIError(res.error)
|
1289
|
+
});
|
1147
1290
|
return { error: res.error };
|
1148
1291
|
}
|
1149
|
-
trackUsage("didUnpublishEntry");
|
1150
1292
|
toggleNotification({
|
1151
1293
|
type: "success",
|
1152
1294
|
message: formatMessage({
|
1153
|
-
id: getTranslation("success.record.
|
1154
|
-
defaultMessage: "
|
1295
|
+
id: getTranslation("success.record.delete"),
|
1296
|
+
defaultMessage: "Deleted document"
|
1155
1297
|
})
|
1156
1298
|
});
|
1299
|
+
trackUsage("didDeleteEntry", trackerProperty);
|
1157
1300
|
return res.data;
|
1158
1301
|
} catch (err) {
|
1159
1302
|
toggleNotification({
|
1160
1303
|
type: "danger",
|
1161
1304
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1162
1305
|
});
|
1306
|
+
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
1163
1307
|
throw err;
|
1164
1308
|
}
|
1165
1309
|
},
|
1166
|
-
[trackUsage,
|
1310
|
+
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
1167
1311
|
);
|
1168
|
-
const [
|
1169
|
-
const
|
1312
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1313
|
+
const deleteMany = React__namespace.useCallback(
|
1170
1314
|
async ({ model, documentIds, params }) => {
|
1171
1315
|
try {
|
1172
|
-
trackUsage("
|
1173
|
-
const res = await
|
1316
|
+
trackUsage("willBulkDeleteEntries");
|
1317
|
+
const res = await deleteManyDocuments({
|
1174
1318
|
model,
|
1175
1319
|
documentIds,
|
1176
1320
|
params
|
1177
1321
|
});
|
1178
1322
|
if ("error" in res) {
|
1179
|
-
toggleNotification({
|
1323
|
+
toggleNotification({
|
1324
|
+
type: "danger",
|
1325
|
+
message: formatAPIError(res.error)
|
1326
|
+
});
|
1180
1327
|
return { error: res.error };
|
1181
1328
|
}
|
1182
|
-
trackUsage("didBulkUnpublishEntries");
|
1183
1329
|
toggleNotification({
|
1184
1330
|
type: "success",
|
1185
1331
|
title: formatMessage({
|
1186
|
-
id: getTranslation("success.records.
|
1187
|
-
defaultMessage: "Successfully
|
1332
|
+
id: getTranslation("success.records.delete"),
|
1333
|
+
defaultMessage: "Successfully deleted."
|
1188
1334
|
}),
|
1189
1335
|
message: ""
|
1190
1336
|
});
|
1337
|
+
trackUsage("didBulkDeleteEntries");
|
1191
1338
|
return res.data;
|
1192
1339
|
} catch (err) {
|
1193
1340
|
toggleNotification({
|
1194
1341
|
type: "danger",
|
1195
1342
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1196
1343
|
});
|
1197
|
-
trackUsage("
|
1344
|
+
trackUsage("didNotBulkDeleteEntries");
|
1198
1345
|
throw err;
|
1199
1346
|
}
|
1200
1347
|
},
|
1201
|
-
[trackUsage,
|
1348
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1202
1349
|
);
|
1203
|
-
const [
|
1204
|
-
const
|
1205
|
-
async ({ model, params }
|
1350
|
+
const [discardDocument] = useDiscardDocumentMutation();
|
1351
|
+
const discard = React__namespace.useCallback(
|
1352
|
+
async ({ collectionType, model, documentId, params }) => {
|
1206
1353
|
try {
|
1207
|
-
const res = await
|
1354
|
+
const res = await discardDocument({
|
1355
|
+
collectionType,
|
1208
1356
|
model,
|
1209
|
-
|
1357
|
+
documentId,
|
1210
1358
|
params
|
1211
1359
|
});
|
1212
1360
|
if ("error" in res) {
|
1213
|
-
toggleNotification({
|
1214
|
-
|
1361
|
+
toggleNotification({
|
1362
|
+
type: "danger",
|
1363
|
+
message: formatAPIError(res.error)
|
1364
|
+
});
|
1215
1365
|
return { error: res.error };
|
1216
1366
|
}
|
1217
|
-
trackUsage("didCreateEntry", trackerProperty);
|
1218
1367
|
toggleNotification({
|
1219
1368
|
type: "success",
|
1220
1369
|
message: formatMessage({
|
1221
|
-
id:
|
1222
|
-
defaultMessage: "
|
1223
|
-
})
|
1370
|
+
id: "content-manager.success.record.discard",
|
1371
|
+
defaultMessage: "Changes discarded"
|
1372
|
+
})
|
1373
|
+
});
|
1374
|
+
return res.data;
|
1375
|
+
} catch (err) {
|
1376
|
+
toggleNotification({
|
1377
|
+
type: "danger",
|
1378
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1379
|
+
});
|
1380
|
+
throw err;
|
1381
|
+
}
|
1382
|
+
},
|
1383
|
+
[discardDocument, formatAPIError, formatMessage, toggleNotification]
|
1384
|
+
);
|
1385
|
+
const [publishDocument] = usePublishDocumentMutation();
|
1386
|
+
const publish = React__namespace.useCallback(
|
1387
|
+
async ({ collectionType, model, documentId, params }, data) => {
|
1388
|
+
try {
|
1389
|
+
trackUsage("willPublishEntry");
|
1390
|
+
const res = await publishDocument({
|
1391
|
+
collectionType,
|
1392
|
+
model,
|
1393
|
+
documentId,
|
1394
|
+
data,
|
1395
|
+
params
|
1396
|
+
});
|
1397
|
+
if ("error" in res) {
|
1398
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1399
|
+
return { error: res.error };
|
1400
|
+
}
|
1401
|
+
trackUsage("didPublishEntry");
|
1402
|
+
toggleNotification({
|
1403
|
+
type: "success",
|
1404
|
+
message: formatMessage({
|
1405
|
+
id: getTranslation("success.record.publish"),
|
1406
|
+
defaultMessage: "Published document"
|
1407
|
+
})
|
1408
|
+
});
|
1409
|
+
return res.data;
|
1410
|
+
} catch (err) {
|
1411
|
+
toggleNotification({
|
1412
|
+
type: "danger",
|
1413
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1414
|
+
});
|
1415
|
+
throw err;
|
1416
|
+
}
|
1417
|
+
},
|
1418
|
+
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1419
|
+
);
|
1420
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1421
|
+
const publishMany = React__namespace.useCallback(
|
1422
|
+
async ({ model, documentIds, params }) => {
|
1423
|
+
try {
|
1424
|
+
const res = await publishManyDocuments({
|
1425
|
+
model,
|
1426
|
+
documentIds,
|
1427
|
+
params
|
1428
|
+
});
|
1429
|
+
if ("error" in res) {
|
1430
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1431
|
+
return { error: res.error };
|
1432
|
+
}
|
1433
|
+
toggleNotification({
|
1434
|
+
type: "success",
|
1435
|
+
message: formatMessage({
|
1436
|
+
id: getTranslation("success.record.publish"),
|
1437
|
+
defaultMessage: "Published document"
|
1438
|
+
})
|
1439
|
+
});
|
1440
|
+
return res.data;
|
1441
|
+
} catch (err) {
|
1442
|
+
toggleNotification({
|
1443
|
+
type: "danger",
|
1444
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1445
|
+
});
|
1446
|
+
throw err;
|
1447
|
+
}
|
1448
|
+
},
|
1449
|
+
[
|
1450
|
+
// trackUsage,
|
1451
|
+
publishManyDocuments,
|
1452
|
+
toggleNotification,
|
1453
|
+
formatMessage,
|
1454
|
+
formatAPIError
|
1455
|
+
]
|
1456
|
+
);
|
1457
|
+
const [updateDocument] = useUpdateDocumentMutation();
|
1458
|
+
const update = React__namespace.useCallback(
|
1459
|
+
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
1460
|
+
try {
|
1461
|
+
trackUsage("willEditEntry", trackerProperty);
|
1462
|
+
const res = await updateDocument({
|
1463
|
+
collectionType,
|
1464
|
+
model,
|
1465
|
+
documentId,
|
1466
|
+
data,
|
1467
|
+
params
|
1468
|
+
});
|
1469
|
+
if ("error" in res) {
|
1470
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1471
|
+
trackUsage("didNotEditEntry", { error: res.error, ...trackerProperty });
|
1472
|
+
return { error: res.error };
|
1473
|
+
}
|
1474
|
+
trackUsage("didEditEntry", trackerProperty);
|
1475
|
+
toggleNotification({
|
1476
|
+
type: "success",
|
1477
|
+
message: formatMessage({
|
1478
|
+
id: getTranslation("success.record.save"),
|
1479
|
+
defaultMessage: "Saved document"
|
1480
|
+
})
|
1481
|
+
});
|
1482
|
+
return res.data;
|
1483
|
+
} catch (err) {
|
1484
|
+
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1485
|
+
toggleNotification({
|
1486
|
+
type: "danger",
|
1487
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1488
|
+
});
|
1489
|
+
throw err;
|
1490
|
+
}
|
1491
|
+
},
|
1492
|
+
[trackUsage, updateDocument, toggleNotification, formatMessage, formatAPIError]
|
1493
|
+
);
|
1494
|
+
const [unpublishDocument] = useUnpublishDocumentMutation();
|
1495
|
+
const unpublish = React__namespace.useCallback(
|
1496
|
+
async ({ collectionType, model, documentId, params }, discardDraft = false) => {
|
1497
|
+
try {
|
1498
|
+
trackUsage("willUnpublishEntry");
|
1499
|
+
const res = await unpublishDocument({
|
1500
|
+
collectionType,
|
1501
|
+
model,
|
1502
|
+
documentId,
|
1503
|
+
params,
|
1504
|
+
data: {
|
1505
|
+
discardDraft
|
1506
|
+
}
|
1507
|
+
});
|
1508
|
+
if ("error" in res) {
|
1509
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1510
|
+
return { error: res.error };
|
1511
|
+
}
|
1512
|
+
trackUsage("didUnpublishEntry");
|
1513
|
+
toggleNotification({
|
1514
|
+
type: "success",
|
1515
|
+
message: formatMessage({
|
1516
|
+
id: getTranslation("success.record.unpublish"),
|
1517
|
+
defaultMessage: "Unpublished document"
|
1518
|
+
})
|
1519
|
+
});
|
1520
|
+
return res.data;
|
1521
|
+
} catch (err) {
|
1522
|
+
toggleNotification({
|
1523
|
+
type: "danger",
|
1524
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1525
|
+
});
|
1526
|
+
throw err;
|
1527
|
+
}
|
1528
|
+
},
|
1529
|
+
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1530
|
+
);
|
1531
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1532
|
+
const unpublishMany = React__namespace.useCallback(
|
1533
|
+
async ({ model, documentIds, params }) => {
|
1534
|
+
try {
|
1535
|
+
trackUsage("willBulkUnpublishEntries");
|
1536
|
+
const res = await unpublishManyDocuments({
|
1537
|
+
model,
|
1538
|
+
documentIds,
|
1539
|
+
params
|
1540
|
+
});
|
1541
|
+
if ("error" in res) {
|
1542
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1543
|
+
return { error: res.error };
|
1544
|
+
}
|
1545
|
+
trackUsage("didBulkUnpublishEntries");
|
1546
|
+
toggleNotification({
|
1547
|
+
type: "success",
|
1548
|
+
title: formatMessage({
|
1549
|
+
id: getTranslation("success.records.unpublish"),
|
1550
|
+
defaultMessage: "Successfully unpublished."
|
1551
|
+
}),
|
1552
|
+
message: ""
|
1553
|
+
});
|
1554
|
+
return res.data;
|
1555
|
+
} catch (err) {
|
1556
|
+
toggleNotification({
|
1557
|
+
type: "danger",
|
1558
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1559
|
+
});
|
1560
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1561
|
+
throw err;
|
1562
|
+
}
|
1563
|
+
},
|
1564
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1565
|
+
);
|
1566
|
+
const [createDocument] = useCreateDocumentMutation();
|
1567
|
+
const create = React__namespace.useCallback(
|
1568
|
+
async ({ model, params }, data, trackerProperty) => {
|
1569
|
+
try {
|
1570
|
+
const res = await createDocument({
|
1571
|
+
model,
|
1572
|
+
data,
|
1573
|
+
params
|
1574
|
+
});
|
1575
|
+
if ("error" in res) {
|
1576
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1577
|
+
trackUsage("didNotCreateEntry", { error: res.error, ...trackerProperty });
|
1578
|
+
return { error: res.error };
|
1579
|
+
}
|
1580
|
+
trackUsage("didCreateEntry", trackerProperty);
|
1581
|
+
toggleNotification({
|
1582
|
+
type: "success",
|
1583
|
+
message: formatMessage({
|
1584
|
+
id: getTranslation("success.record.save"),
|
1585
|
+
defaultMessage: "Saved document"
|
1586
|
+
})
|
1224
1587
|
});
|
1588
|
+
setCurrentStep("contentManager.success");
|
1225
1589
|
return res.data;
|
1226
1590
|
} catch (err) {
|
1227
1591
|
toggleNotification({
|
@@ -1323,10 +1687,10 @@ const useDocumentActions = () => {
|
|
1323
1687
|
update
|
1324
1688
|
};
|
1325
1689
|
};
|
1326
|
-
const ProtectedHistoryPage =
|
1327
|
-
() => Promise.resolve().then(() => require("./History-
|
1690
|
+
const ProtectedHistoryPage = React__namespace.lazy(
|
1691
|
+
() => Promise.resolve().then(() => require("./History-DYl2A8Z_.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1328
1692
|
);
|
1329
|
-
const routes$
|
1693
|
+
const routes$2 = [
|
1330
1694
|
{
|
1331
1695
|
path: ":collectionType/:slug/:id/history",
|
1332
1696
|
Component: ProtectedHistoryPage
|
@@ -1336,32 +1700,45 @@ const routes$1 = [
|
|
1336
1700
|
Component: ProtectedHistoryPage
|
1337
1701
|
}
|
1338
1702
|
];
|
1703
|
+
const ProtectedPreviewPage = React__namespace.lazy(
|
1704
|
+
() => Promise.resolve().then(() => require("./Preview-DfNx8Ke-.js")).then((mod) => ({ default: mod.ProtectedPreviewPage }))
|
1705
|
+
);
|
1706
|
+
const routes$1 = [
|
1707
|
+
{
|
1708
|
+
path: ":collectionType/:slug/:id/preview",
|
1709
|
+
Component: ProtectedPreviewPage
|
1710
|
+
},
|
1711
|
+
{
|
1712
|
+
path: ":collectionType/:slug/preview",
|
1713
|
+
Component: ProtectedPreviewPage
|
1714
|
+
}
|
1715
|
+
];
|
1339
1716
|
const ProtectedEditViewPage = React.lazy(
|
1340
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1717
|
+
() => Promise.resolve().then(() => require("./EditViewPage-wujOq90c.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1341
1718
|
);
|
1342
1719
|
const ProtectedListViewPage = React.lazy(
|
1343
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1720
|
+
() => Promise.resolve().then(() => require("./ListViewPage-BtSi8C1l.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1344
1721
|
);
|
1345
1722
|
const ProtectedListConfiguration = React.lazy(
|
1346
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1723
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-BXnu_OoY.js")).then((mod) => ({
|
1347
1724
|
default: mod.ProtectedListConfiguration
|
1348
1725
|
}))
|
1349
1726
|
);
|
1350
1727
|
const ProtectedEditConfigurationPage = React.lazy(
|
1351
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1728
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-z39Wv3E6.js")).then((mod) => ({
|
1352
1729
|
default: mod.ProtectedEditConfigurationPage
|
1353
1730
|
}))
|
1354
1731
|
);
|
1355
1732
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1356
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1733
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-BTR_hQow.js")).then((mod) => ({
|
1357
1734
|
default: mod.ProtectedComponentConfigurationPage
|
1358
1735
|
}))
|
1359
1736
|
);
|
1360
1737
|
const NoPermissions = React.lazy(
|
1361
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1738
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-DzgWz0M-.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1362
1739
|
);
|
1363
1740
|
const NoContentType = React.lazy(
|
1364
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1741
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-CitJeOq4.js")).then((mod) => ({ default: mod.NoContentType }))
|
1365
1742
|
);
|
1366
1743
|
const CollectionTypePages = () => {
|
1367
1744
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1373,7 +1750,7 @@ const CollectionTypePages = () => {
|
|
1373
1750
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1374
1751
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1375
1752
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1376
|
-
const LIST_PATH = `/content-manager
|
1753
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1377
1754
|
const routes = [
|
1378
1755
|
{
|
1379
1756
|
path: LIST_RELATIVE_PATH,
|
@@ -1407,6 +1784,7 @@ const routes = [
|
|
1407
1784
|
path: "no-content-types",
|
1408
1785
|
Component: NoContentType
|
1409
1786
|
},
|
1787
|
+
...routes$2,
|
1410
1788
|
...routes$1
|
1411
1789
|
];
|
1412
1790
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1505,6 +1883,11 @@ const DocumentActionButton = (action) => {
|
|
1505
1883
|
) : null
|
1506
1884
|
] });
|
1507
1885
|
};
|
1886
|
+
const MenuItem = styledComponents.styled(designSystem.Menu.Item)`
|
1887
|
+
&:hover {
|
1888
|
+
background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
|
1889
|
+
}
|
1890
|
+
`;
|
1508
1891
|
const DocumentActionsMenu = ({
|
1509
1892
|
actions: actions2,
|
1510
1893
|
children,
|
@@ -1542,7 +1925,7 @@ const DocumentActionsMenu = ({
|
|
1542
1925
|
};
|
1543
1926
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1544
1927
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
1545
|
-
|
1928
|
+
designSystem.Menu.Trigger,
|
1546
1929
|
{
|
1547
1930
|
disabled: isDisabled,
|
1548
1931
|
size: "S",
|
@@ -1560,51 +1943,35 @@ const DocumentActionsMenu = ({
|
|
1560
1943
|
]
|
1561
1944
|
}
|
1562
1945
|
),
|
1563
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, {
|
1946
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1564
1947
|
actions2.map((action) => {
|
1565
1948
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
1566
|
-
|
1949
|
+
MenuItem,
|
1567
1950
|
{
|
1568
1951
|
disabled: action.disabled,
|
1569
1952
|
onSelect: handleClick(action),
|
1570
1953
|
display: "block",
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
|
1591
|
-
|
1592
|
-
designSystem.Flex,
|
1593
|
-
{
|
1594
|
-
alignItems: "center",
|
1595
|
-
background: "alternative100",
|
1596
|
-
borderStyle: "solid",
|
1597
|
-
borderColor: "alternative200",
|
1598
|
-
borderWidth: "1px",
|
1599
|
-
height: 5,
|
1600
|
-
paddingLeft: 2,
|
1601
|
-
paddingRight: 2,
|
1602
|
-
hasRadius: true,
|
1603
|
-
color: "alternative600",
|
1604
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1605
|
-
}
|
1606
|
-
)
|
1607
|
-
] })
|
1954
|
+
isVariantDanger: action.variant === "danger",
|
1955
|
+
isDisabled: action.disabled,
|
1956
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
1957
|
+
designSystem.Flex,
|
1958
|
+
{
|
1959
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1960
|
+
gap: 2,
|
1961
|
+
tag: "span",
|
1962
|
+
children: [
|
1963
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1964
|
+
designSystem.Flex,
|
1965
|
+
{
|
1966
|
+
tag: "span",
|
1967
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1968
|
+
children: action.icon
|
1969
|
+
}
|
1970
|
+
),
|
1971
|
+
action.label
|
1972
|
+
]
|
1973
|
+
}
|
1974
|
+
) })
|
1608
1975
|
},
|
1609
1976
|
action.id
|
1610
1977
|
);
|
@@ -1658,11 +2025,6 @@ const convertActionVariantToIconColor = (variant = "secondary") => {
|
|
1658
2025
|
return "primary600";
|
1659
2026
|
}
|
1660
2027
|
};
|
1661
|
-
const StyledMoreButton = styledComponents.styled(designSystem.Menu.Trigger)`
|
1662
|
-
& > span {
|
1663
|
-
display: flex;
|
1664
|
-
}
|
1665
|
-
`;
|
1666
2028
|
const DocumentActionConfirmDialog = ({
|
1667
2029
|
onClose,
|
1668
2030
|
onCancel,
|
@@ -1689,11 +2051,11 @@ const DocumentActionConfirmDialog = ({
|
|
1689
2051
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
1690
2052
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
1691
2053
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
1692
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
|
2054
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1693
2055
|
id: "app.components.Button.cancel",
|
1694
2056
|
defaultMessage: "Cancel"
|
1695
2057
|
}) }) }),
|
1696
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2058
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1697
2059
|
id: "app.components.Button.confirm",
|
1698
2060
|
defaultMessage: "Confirm"
|
1699
2061
|
}) })
|
@@ -1720,6 +2082,18 @@ const DocumentActionModal = ({
|
|
1720
2082
|
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
1721
2083
|
] }) });
|
1722
2084
|
};
|
2085
|
+
const transformData = (data) => {
|
2086
|
+
if (Array.isArray(data)) {
|
2087
|
+
return data.map(transformData);
|
2088
|
+
}
|
2089
|
+
if (typeof data === "object" && data !== null) {
|
2090
|
+
if ("apiData" in data) {
|
2091
|
+
return data.apiData;
|
2092
|
+
}
|
2093
|
+
return mapValues__default.default(transformData)(data);
|
2094
|
+
}
|
2095
|
+
return data;
|
2096
|
+
};
|
1723
2097
|
const PublishAction$1 = ({
|
1724
2098
|
activeTab,
|
1725
2099
|
documentId,
|
@@ -1734,6 +2108,7 @@ const PublishAction$1 = ({
|
|
1734
2108
|
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
1735
2109
|
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
1736
2110
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2111
|
+
const { id } = reactRouterDom.useParams();
|
1737
2112
|
const { formatMessage } = reactIntl.useIntl();
|
1738
2113
|
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1739
2114
|
const { publish } = useDocumentActions();
|
@@ -1787,24 +2162,25 @@ const PublishAction$1 = ({
|
|
1787
2162
|
}
|
1788
2163
|
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1789
2164
|
React__namespace.useEffect(() => {
|
1790
|
-
if (documentId
|
1791
|
-
|
1792
|
-
const { data, error } = await countDraftRelations({
|
1793
|
-
collectionType,
|
1794
|
-
model,
|
1795
|
-
documentId,
|
1796
|
-
params
|
1797
|
-
});
|
1798
|
-
if (error) {
|
1799
|
-
throw error;
|
1800
|
-
}
|
1801
|
-
if (data) {
|
1802
|
-
setServerCountOfDraftRelations(data.data);
|
1803
|
-
}
|
1804
|
-
};
|
1805
|
-
fetchDraftRelationsCount();
|
2165
|
+
if (!document || !document.documentId || isListView) {
|
2166
|
+
return;
|
1806
2167
|
}
|
1807
|
-
|
2168
|
+
const fetchDraftRelationsCount = async () => {
|
2169
|
+
const { data, error } = await countDraftRelations({
|
2170
|
+
collectionType,
|
2171
|
+
model,
|
2172
|
+
documentId,
|
2173
|
+
params
|
2174
|
+
});
|
2175
|
+
if (error) {
|
2176
|
+
throw error;
|
2177
|
+
}
|
2178
|
+
if (data) {
|
2179
|
+
setServerCountOfDraftRelations(data.data);
|
2180
|
+
}
|
2181
|
+
};
|
2182
|
+
fetchDraftRelationsCount();
|
2183
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
1808
2184
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1809
2185
|
if (!schema?.options?.draftAndPublish) {
|
1810
2186
|
return null;
|
@@ -1812,7 +2188,9 @@ const PublishAction$1 = ({
|
|
1812
2188
|
const performPublish = async () => {
|
1813
2189
|
setSubmitting(true);
|
1814
2190
|
try {
|
1815
|
-
const { errors } = await validate(
|
2191
|
+
const { errors } = await validate(true, {
|
2192
|
+
status: "published"
|
2193
|
+
});
|
1816
2194
|
if (errors) {
|
1817
2195
|
toggleNotification({
|
1818
2196
|
type: "danger",
|
@@ -1830,13 +2208,15 @@ const PublishAction$1 = ({
|
|
1830
2208
|
documentId,
|
1831
2209
|
params
|
1832
2210
|
},
|
1833
|
-
formValues
|
2211
|
+
transformData(formValues)
|
1834
2212
|
);
|
1835
2213
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
2214
|
+
if (id === "create") {
|
2215
|
+
navigate({
|
2216
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2217
|
+
search: rawQuery
|
2218
|
+
});
|
2219
|
+
}
|
1840
2220
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1841
2221
|
setErrors(formatValidationErrors(res.error));
|
1842
2222
|
}
|
@@ -1845,7 +2225,8 @@ const PublishAction$1 = ({
|
|
1845
2225
|
}
|
1846
2226
|
};
|
1847
2227
|
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1848
|
-
const
|
2228
|
+
const enableDraftRelationsCount = false;
|
2229
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1849
2230
|
return {
|
1850
2231
|
/**
|
1851
2232
|
* Disabled when:
|
@@ -1862,9 +2243,6 @@ const PublishAction$1 = ({
|
|
1862
2243
|
defaultMessage: "Publish"
|
1863
2244
|
}),
|
1864
2245
|
onClick: async () => {
|
1865
|
-
if (hasDraftRelations) {
|
1866
|
-
return;
|
1867
|
-
}
|
1868
2246
|
await performPublish();
|
1869
2247
|
},
|
1870
2248
|
dialog: hasDraftRelations ? {
|
@@ -1891,6 +2269,7 @@ const PublishAction$1 = ({
|
|
1891
2269
|
};
|
1892
2270
|
};
|
1893
2271
|
PublishAction$1.type = "publish";
|
2272
|
+
PublishAction$1.position = "panel";
|
1894
2273
|
const UpdateAction = ({
|
1895
2274
|
activeTab,
|
1896
2275
|
documentId,
|
@@ -1913,6 +2292,117 @@ const UpdateAction = ({
|
|
1913
2292
|
const validate = strapiAdmin.useForm("UpdateAction", (state) => state.validate);
|
1914
2293
|
const setErrors = strapiAdmin.useForm("UpdateAction", (state) => state.setErrors);
|
1915
2294
|
const resetForm = strapiAdmin.useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
2295
|
+
const handleUpdate = React__namespace.useCallback(async () => {
|
2296
|
+
setSubmitting(true);
|
2297
|
+
try {
|
2298
|
+
if (!modified) {
|
2299
|
+
return;
|
2300
|
+
}
|
2301
|
+
const { errors } = await validate(true, {
|
2302
|
+
status: "draft"
|
2303
|
+
});
|
2304
|
+
if (errors) {
|
2305
|
+
toggleNotification({
|
2306
|
+
type: "danger",
|
2307
|
+
message: formatMessage({
|
2308
|
+
id: "content-manager.validation.error",
|
2309
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2310
|
+
})
|
2311
|
+
});
|
2312
|
+
return;
|
2313
|
+
}
|
2314
|
+
if (isCloning) {
|
2315
|
+
const res = await clone(
|
2316
|
+
{
|
2317
|
+
model,
|
2318
|
+
documentId: cloneMatch.params.origin,
|
2319
|
+
params
|
2320
|
+
},
|
2321
|
+
transformData(document)
|
2322
|
+
);
|
2323
|
+
if ("data" in res) {
|
2324
|
+
navigate(
|
2325
|
+
{
|
2326
|
+
pathname: `../${res.data.documentId}`,
|
2327
|
+
search: rawQuery
|
2328
|
+
},
|
2329
|
+
{ relative: "path" }
|
2330
|
+
);
|
2331
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2332
|
+
setErrors(formatValidationErrors(res.error));
|
2333
|
+
}
|
2334
|
+
} else if (documentId || collectionType === SINGLE_TYPES) {
|
2335
|
+
const res = await update(
|
2336
|
+
{
|
2337
|
+
collectionType,
|
2338
|
+
model,
|
2339
|
+
documentId,
|
2340
|
+
params
|
2341
|
+
},
|
2342
|
+
transformData(document)
|
2343
|
+
);
|
2344
|
+
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2345
|
+
setErrors(formatValidationErrors(res.error));
|
2346
|
+
} else {
|
2347
|
+
resetForm();
|
2348
|
+
}
|
2349
|
+
} else {
|
2350
|
+
const res = await create(
|
2351
|
+
{
|
2352
|
+
model,
|
2353
|
+
params
|
2354
|
+
},
|
2355
|
+
transformData(document)
|
2356
|
+
);
|
2357
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2358
|
+
navigate(
|
2359
|
+
{
|
2360
|
+
pathname: `../${res.data.documentId}`,
|
2361
|
+
search: rawQuery
|
2362
|
+
},
|
2363
|
+
{ replace: true, relative: "path" }
|
2364
|
+
);
|
2365
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2366
|
+
setErrors(formatValidationErrors(res.error));
|
2367
|
+
}
|
2368
|
+
}
|
2369
|
+
} finally {
|
2370
|
+
setSubmitting(false);
|
2371
|
+
}
|
2372
|
+
}, [
|
2373
|
+
clone,
|
2374
|
+
cloneMatch?.params.origin,
|
2375
|
+
collectionType,
|
2376
|
+
create,
|
2377
|
+
document,
|
2378
|
+
documentId,
|
2379
|
+
formatMessage,
|
2380
|
+
formatValidationErrors,
|
2381
|
+
isCloning,
|
2382
|
+
model,
|
2383
|
+
modified,
|
2384
|
+
navigate,
|
2385
|
+
params,
|
2386
|
+
rawQuery,
|
2387
|
+
resetForm,
|
2388
|
+
setErrors,
|
2389
|
+
setSubmitting,
|
2390
|
+
toggleNotification,
|
2391
|
+
update,
|
2392
|
+
validate
|
2393
|
+
]);
|
2394
|
+
React__namespace.useEffect(() => {
|
2395
|
+
const handleKeyDown = (e) => {
|
2396
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
2397
|
+
e.preventDefault();
|
2398
|
+
handleUpdate();
|
2399
|
+
}
|
2400
|
+
};
|
2401
|
+
window.addEventListener("keydown", handleKeyDown);
|
2402
|
+
return () => {
|
2403
|
+
window.removeEventListener("keydown", handleKeyDown);
|
2404
|
+
};
|
2405
|
+
}, [handleUpdate]);
|
1916
2406
|
return {
|
1917
2407
|
/**
|
1918
2408
|
* Disabled when:
|
@@ -1922,87 +2412,14 @@ const UpdateAction = ({
|
|
1922
2412
|
*/
|
1923
2413
|
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1924
2414
|
label: formatMessage({
|
1925
|
-
id: "
|
2415
|
+
id: "global.save",
|
1926
2416
|
defaultMessage: "Save"
|
1927
2417
|
}),
|
1928
|
-
onClick:
|
1929
|
-
setSubmitting(true);
|
1930
|
-
try {
|
1931
|
-
if (activeTab !== "draft") {
|
1932
|
-
const { errors } = await validate();
|
1933
|
-
if (errors) {
|
1934
|
-
toggleNotification({
|
1935
|
-
type: "danger",
|
1936
|
-
message: formatMessage({
|
1937
|
-
id: "content-manager.validation.error",
|
1938
|
-
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1939
|
-
})
|
1940
|
-
});
|
1941
|
-
return;
|
1942
|
-
}
|
1943
|
-
}
|
1944
|
-
if (isCloning) {
|
1945
|
-
const res = await clone(
|
1946
|
-
{
|
1947
|
-
model,
|
1948
|
-
documentId: cloneMatch.params.origin,
|
1949
|
-
params
|
1950
|
-
},
|
1951
|
-
document
|
1952
|
-
);
|
1953
|
-
if ("data" in res) {
|
1954
|
-
navigate(
|
1955
|
-
{
|
1956
|
-
pathname: `../${res.data.documentId}`,
|
1957
|
-
search: rawQuery
|
1958
|
-
},
|
1959
|
-
{ relative: "path" }
|
1960
|
-
);
|
1961
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1962
|
-
setErrors(formatValidationErrors(res.error));
|
1963
|
-
}
|
1964
|
-
} else if (documentId || collectionType === SINGLE_TYPES) {
|
1965
|
-
const res = await update(
|
1966
|
-
{
|
1967
|
-
collectionType,
|
1968
|
-
model,
|
1969
|
-
documentId,
|
1970
|
-
params
|
1971
|
-
},
|
1972
|
-
document
|
1973
|
-
);
|
1974
|
-
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1975
|
-
setErrors(formatValidationErrors(res.error));
|
1976
|
-
} else {
|
1977
|
-
resetForm();
|
1978
|
-
}
|
1979
|
-
} else {
|
1980
|
-
const res = await create(
|
1981
|
-
{
|
1982
|
-
model,
|
1983
|
-
params
|
1984
|
-
},
|
1985
|
-
document
|
1986
|
-
);
|
1987
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1988
|
-
navigate(
|
1989
|
-
{
|
1990
|
-
pathname: `../${res.data.documentId}`,
|
1991
|
-
search: rawQuery
|
1992
|
-
},
|
1993
|
-
{ replace: true, relative: "path" }
|
1994
|
-
);
|
1995
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1996
|
-
setErrors(formatValidationErrors(res.error));
|
1997
|
-
}
|
1998
|
-
}
|
1999
|
-
} finally {
|
2000
|
-
setSubmitting(false);
|
2001
|
-
}
|
2002
|
-
}
|
2418
|
+
onClick: handleUpdate
|
2003
2419
|
};
|
2004
2420
|
};
|
2005
2421
|
UpdateAction.type = "update";
|
2422
|
+
UpdateAction.position = "panel";
|
2006
2423
|
const UNPUBLISH_DRAFT_OPTIONS = {
|
2007
2424
|
KEEP: "keep",
|
2008
2425
|
DISCARD: "discard"
|
@@ -2035,7 +2452,7 @@ const UnpublishAction$1 = ({
|
|
2035
2452
|
id: "app.utils.unpublish",
|
2036
2453
|
defaultMessage: "Unpublish"
|
2037
2454
|
}),
|
2038
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2455
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2039
2456
|
onClick: async () => {
|
2040
2457
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
2041
2458
|
if (!documentId) {
|
@@ -2125,6 +2542,7 @@ const UnpublishAction$1 = ({
|
|
2125
2542
|
};
|
2126
2543
|
};
|
2127
2544
|
UnpublishAction$1.type = "unpublish";
|
2545
|
+
UnpublishAction$1.position = "panel";
|
2128
2546
|
const DiscardAction = ({
|
2129
2547
|
activeTab,
|
2130
2548
|
documentId,
|
@@ -2147,7 +2565,7 @@ const DiscardAction = ({
|
|
2147
2565
|
id: "content-manager.actions.discard.label",
|
2148
2566
|
defaultMessage: "Discard changes"
|
2149
2567
|
}),
|
2150
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2568
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2151
2569
|
position: ["panel", "table-row"],
|
2152
2570
|
variant: "danger",
|
2153
2571
|
dialog: {
|
@@ -2175,11 +2593,7 @@ const DiscardAction = ({
|
|
2175
2593
|
};
|
2176
2594
|
};
|
2177
2595
|
DiscardAction.type = "discard";
|
2178
|
-
|
2179
|
-
path {
|
2180
|
-
fill: currentColor;
|
2181
|
-
}
|
2182
|
-
`;
|
2596
|
+
DiscardAction.position = "panel";
|
2183
2597
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2184
2598
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2185
2599
|
const RelativeTime = React__namespace.forwardRef(
|
@@ -2192,7 +2606,7 @@ const RelativeTime = React__namespace.forwardRef(
|
|
2192
2606
|
});
|
2193
2607
|
const unit = intervals.find((intervalUnit) => {
|
2194
2608
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2195
|
-
});
|
2609
|
+
}) ?? "seconds";
|
2196
2610
|
const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
|
2197
2611
|
const customInterval = customIntervals.find(
|
2198
2612
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2226,19 +2640,29 @@ const getDisplayName = ({
|
|
2226
2640
|
return email ?? "";
|
2227
2641
|
};
|
2228
2642
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2229
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2230
|
-
const statusVariant = status === "draft" ? "
|
2231
|
-
|
2643
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2644
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2645
|
+
const { formatMessage } = reactIntl.useIntl();
|
2646
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2647
|
+
id: `content-manager.containers.List.${status}`,
|
2648
|
+
defaultMessage: capitalise(status)
|
2649
|
+
}) }) });
|
2232
2650
|
};
|
2233
2651
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2234
2652
|
const { formatMessage } = reactIntl.useIntl();
|
2235
2653
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2654
|
+
const params = reactRouterDom.useParams();
|
2236
2655
|
const title = isCreating ? formatMessage({
|
2237
2656
|
id: "content-manager.containers.edit.title.new",
|
2238
2657
|
defaultMessage: "Create an entry"
|
2239
2658
|
}) : documentTitle;
|
2240
2659
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2241
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2660
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2661
|
+
strapiAdmin.BackButton,
|
2662
|
+
{
|
2663
|
+
fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
|
2664
|
+
}
|
2665
|
+
),
|
2242
2666
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2243
2667
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2244
2668
|
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
@@ -2289,7 +2713,7 @@ const HeaderToolbar = () => {
|
|
2289
2713
|
meta: isCloning ? void 0 : meta,
|
2290
2714
|
collectionType
|
2291
2715
|
},
|
2292
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2716
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
|
2293
2717
|
children: (actions2) => {
|
2294
2718
|
const headerActions = actions2.filter((action) => {
|
2295
2719
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -2326,12 +2750,12 @@ const Information = ({ activeTab }) => {
|
|
2326
2750
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2327
2751
|
label: formatMessage({
|
2328
2752
|
id: "content-manager.containers.edit.information.last-published.label",
|
2329
|
-
defaultMessage: "
|
2753
|
+
defaultMessage: "Published"
|
2330
2754
|
}),
|
2331
2755
|
value: formatMessage(
|
2332
2756
|
{
|
2333
2757
|
id: "content-manager.containers.edit.information.last-published.value",
|
2334
|
-
defaultMessage: `
|
2758
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2335
2759
|
},
|
2336
2760
|
{
|
2337
2761
|
time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2344,12 +2768,12 @@ const Information = ({ activeTab }) => {
|
|
2344
2768
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2345
2769
|
label: formatMessage({
|
2346
2770
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2347
|
-
defaultMessage: "
|
2771
|
+
defaultMessage: "Updated"
|
2348
2772
|
}),
|
2349
2773
|
value: formatMessage(
|
2350
2774
|
{
|
2351
2775
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2352
|
-
defaultMessage: `
|
2776
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2353
2777
|
},
|
2354
2778
|
{
|
2355
2779
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2367,12 +2791,12 @@ const Information = ({ activeTab }) => {
|
|
2367
2791
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2368
2792
|
label: formatMessage({
|
2369
2793
|
id: "content-manager.containers.edit.information.document.label",
|
2370
|
-
defaultMessage: "
|
2794
|
+
defaultMessage: "Created"
|
2371
2795
|
}),
|
2372
2796
|
value: formatMessage(
|
2373
2797
|
{
|
2374
2798
|
id: "content-manager.containers.edit.information.document.value",
|
2375
|
-
defaultMessage: `
|
2799
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2376
2800
|
},
|
2377
2801
|
{
|
2378
2802
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2410,25 +2834,77 @@ const Information = ({ activeTab }) => {
|
|
2410
2834
|
);
|
2411
2835
|
};
|
2412
2836
|
const HeaderActions = ({ actions: actions2 }) => {
|
2413
|
-
|
2414
|
-
|
2837
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2838
|
+
const handleClick = (action) => async (e) => {
|
2839
|
+
if (!("options" in action)) {
|
2840
|
+
const { onClick = () => false, dialog, id } = action;
|
2841
|
+
const muteDialog = await onClick(e);
|
2842
|
+
if (dialog && !muteDialog) {
|
2843
|
+
e.preventDefault();
|
2844
|
+
setDialogId(id);
|
2845
|
+
}
|
2846
|
+
}
|
2847
|
+
};
|
2848
|
+
const handleClose = () => {
|
2849
|
+
setDialogId(null);
|
2850
|
+
};
|
2851
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2852
|
+
if (action.options) {
|
2415
2853
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
2416
2854
|
designSystem.SingleSelect,
|
2417
2855
|
{
|
2418
2856
|
size: "S",
|
2419
|
-
disabled: action.disabled,
|
2420
|
-
"aria-label": action.label,
|
2421
2857
|
onChange: action.onSelect,
|
2422
|
-
|
2858
|
+
"aria-label": action.label,
|
2859
|
+
...action,
|
2423
2860
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2424
2861
|
},
|
2425
2862
|
action.id
|
2426
2863
|
);
|
2427
2864
|
} else {
|
2428
|
-
|
2865
|
+
if (action.type === "icon") {
|
2866
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2867
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2868
|
+
designSystem.IconButton,
|
2869
|
+
{
|
2870
|
+
disabled: action.disabled,
|
2871
|
+
label: action.label,
|
2872
|
+
size: "S",
|
2873
|
+
onClick: handleClick(action),
|
2874
|
+
children: action.icon
|
2875
|
+
}
|
2876
|
+
),
|
2877
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2878
|
+
HeaderActionDialog,
|
2879
|
+
{
|
2880
|
+
...action.dialog,
|
2881
|
+
isOpen: dialogId === action.id,
|
2882
|
+
onClose: handleClose
|
2883
|
+
}
|
2884
|
+
) : null
|
2885
|
+
] }, action.id);
|
2886
|
+
}
|
2429
2887
|
}
|
2430
2888
|
}) });
|
2431
2889
|
};
|
2890
|
+
const HeaderActionDialog = ({
|
2891
|
+
onClose,
|
2892
|
+
onCancel,
|
2893
|
+
title,
|
2894
|
+
content: Content,
|
2895
|
+
isOpen
|
2896
|
+
}) => {
|
2897
|
+
const handleClose = async () => {
|
2898
|
+
if (onCancel) {
|
2899
|
+
await onCancel();
|
2900
|
+
}
|
2901
|
+
onClose();
|
2902
|
+
};
|
2903
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2904
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2905
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2906
|
+
] }) });
|
2907
|
+
};
|
2432
2908
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2433
2909
|
const navigate = reactRouterDom.useNavigate();
|
2434
2910
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2445,6 +2921,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2445
2921
|
};
|
2446
2922
|
};
|
2447
2923
|
ConfigureTheViewAction.type = "configure-the-view";
|
2924
|
+
ConfigureTheViewAction.position = "header";
|
2448
2925
|
const EditTheModelAction = ({ model }) => {
|
2449
2926
|
const navigate = reactRouterDom.useNavigate();
|
2450
2927
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2461,6 +2938,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2461
2938
|
};
|
2462
2939
|
};
|
2463
2940
|
EditTheModelAction.type = "edit-the-model";
|
2941
|
+
EditTheModelAction.position = "header";
|
2464
2942
|
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2465
2943
|
const navigate = reactRouterDom.useNavigate();
|
2466
2944
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2469,12 +2947,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2469
2947
|
const { delete: deleteAction } = useDocumentActions();
|
2470
2948
|
const { toggleNotification } = strapiAdmin.useNotification();
|
2471
2949
|
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2950
|
+
const isLocalized = document?.locale != null;
|
2472
2951
|
return {
|
2473
2952
|
disabled: !canDelete || !document,
|
2474
|
-
label: formatMessage(
|
2475
|
-
|
2476
|
-
|
2477
|
-
|
2953
|
+
label: formatMessage(
|
2954
|
+
{
|
2955
|
+
id: "content-manager.actions.delete.label",
|
2956
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2957
|
+
},
|
2958
|
+
{ isLocalized }
|
2959
|
+
),
|
2478
2960
|
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2479
2961
|
dialog: {
|
2480
2962
|
type: "dialog",
|
@@ -2513,420 +2995,119 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2513
2995
|
collectionType,
|
2514
2996
|
params: {
|
2515
2997
|
locale: "*"
|
2516
|
-
}
|
2517
|
-
});
|
2518
|
-
if (!("error" in res)) {
|
2519
|
-
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2520
|
-
}
|
2521
|
-
} finally {
|
2522
|
-
if (!listViewPathMatch) {
|
2523
|
-
setSubmitting(false);
|
2524
|
-
}
|
2525
|
-
}
|
2526
|
-
}
|
2527
|
-
},
|
2528
|
-
variant: "danger",
|
2529
|
-
position: ["header", "table-row"]
|
2530
|
-
};
|
2531
|
-
};
|
2532
|
-
DeleteAction$1.type = "delete";
|
2533
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2534
|
-
const Panels = () => {
|
2535
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2536
|
-
const [
|
2537
|
-
{
|
2538
|
-
query: { status }
|
2539
|
-
}
|
2540
|
-
] = strapiAdmin.useQueryParams({
|
2541
|
-
status: "draft"
|
2542
|
-
});
|
2543
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2544
|
-
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2545
|
-
const props = {
|
2546
|
-
activeTab: status,
|
2547
|
-
model,
|
2548
|
-
documentId: id,
|
2549
|
-
document: isCloning ? void 0 : document,
|
2550
|
-
meta: isCloning ? void 0 : meta,
|
2551
|
-
collectionType
|
2552
|
-
};
|
2553
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2554
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2555
|
-
{
|
2556
|
-
props,
|
2557
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2558
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2559
|
-
}
|
2560
|
-
) });
|
2561
|
-
};
|
2562
|
-
const ActionsPanel = () => {
|
2563
|
-
const { formatMessage } = reactIntl.useIntl();
|
2564
|
-
return {
|
2565
|
-
title: formatMessage({
|
2566
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2567
|
-
defaultMessage: "Document"
|
2568
|
-
}),
|
2569
|
-
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2570
|
-
};
|
2571
|
-
};
|
2572
|
-
ActionsPanel.type = "actions";
|
2573
|
-
const ActionsPanelContent = () => {
|
2574
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2575
|
-
const [
|
2576
|
-
{
|
2577
|
-
query: { status = "draft" }
|
2578
|
-
}
|
2579
|
-
] = strapiAdmin.useQueryParams();
|
2580
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2581
|
-
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2582
|
-
const props = {
|
2583
|
-
activeTab: status,
|
2584
|
-
model,
|
2585
|
-
documentId: id,
|
2586
|
-
document: isCloning ? void 0 : document,
|
2587
|
-
meta: isCloning ? void 0 : meta,
|
2588
|
-
collectionType
|
2589
|
-
};
|
2590
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2591
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2592
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2593
|
-
{
|
2594
|
-
props,
|
2595
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2596
|
-
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
2597
|
-
}
|
2598
|
-
),
|
2599
|
-
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2600
|
-
] });
|
2601
|
-
};
|
2602
|
-
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
2603
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
2604
|
-
designSystem.Flex,
|
2605
|
-
{
|
2606
|
-
ref,
|
2607
|
-
tag: "aside",
|
2608
|
-
"aria-labelledby": "additional-information",
|
2609
|
-
background: "neutral0",
|
2610
|
-
borderColor: "neutral150",
|
2611
|
-
hasRadius: true,
|
2612
|
-
paddingBottom: 4,
|
2613
|
-
paddingLeft: 4,
|
2614
|
-
paddingRight: 4,
|
2615
|
-
paddingTop: 4,
|
2616
|
-
shadow: "tableShadow",
|
2617
|
-
gap: 3,
|
2618
|
-
direction: "column",
|
2619
|
-
justifyContent: "stretch",
|
2620
|
-
alignItems: "flex-start",
|
2621
|
-
children: [
|
2622
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2623
|
-
children
|
2624
|
-
]
|
2625
|
-
}
|
2626
|
-
);
|
2627
|
-
});
|
2628
|
-
const HOOKS = {
|
2629
|
-
/**
|
2630
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2631
|
-
* @constant
|
2632
|
-
* @type {string}
|
2633
|
-
*/
|
2634
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2635
|
-
/**
|
2636
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2637
|
-
* @constant
|
2638
|
-
* @type {string}
|
2639
|
-
*/
|
2640
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2641
|
-
/**
|
2642
|
-
* Hook that allows to mutate the CM's edit view layout
|
2643
|
-
* @constant
|
2644
|
-
* @type {string}
|
2645
|
-
*/
|
2646
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2647
|
-
/**
|
2648
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2649
|
-
* @constant
|
2650
|
-
* @type {string}
|
2651
|
-
*/
|
2652
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2653
|
-
};
|
2654
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2655
|
-
endpoints: (builder) => ({
|
2656
|
-
getContentTypeConfiguration: builder.query({
|
2657
|
-
query: (uid) => ({
|
2658
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2659
|
-
method: "GET"
|
2660
|
-
}),
|
2661
|
-
transformResponse: (response) => response.data,
|
2662
|
-
providesTags: (_result, _error, uid) => [
|
2663
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2664
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2665
|
-
]
|
2666
|
-
}),
|
2667
|
-
getAllContentTypeSettings: builder.query({
|
2668
|
-
query: () => "/content-manager/content-types-settings",
|
2669
|
-
transformResponse: (response) => response.data,
|
2670
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2671
|
-
}),
|
2672
|
-
updateContentTypeConfiguration: builder.mutation({
|
2673
|
-
query: ({ uid, ...body }) => ({
|
2674
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2675
|
-
method: "PUT",
|
2676
|
-
data: body
|
2677
|
-
}),
|
2678
|
-
transformResponse: (response) => response.data,
|
2679
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2680
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2681
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2682
|
-
// Is this necessary?
|
2683
|
-
{ type: "InitialData" }
|
2684
|
-
]
|
2685
|
-
})
|
2686
|
-
})
|
2687
|
-
});
|
2688
|
-
const {
|
2689
|
-
useGetContentTypeConfigurationQuery,
|
2690
|
-
useGetAllContentTypeSettingsQuery,
|
2691
|
-
useUpdateContentTypeConfigurationMutation
|
2692
|
-
} = contentTypesApi;
|
2693
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2694
|
-
const { type } = attribute;
|
2695
|
-
if (type === "relation") {
|
2696
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2697
|
-
}
|
2698
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2699
|
-
};
|
2700
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2701
|
-
if (!mainFieldName) {
|
2702
|
-
return void 0;
|
2703
|
-
}
|
2704
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2705
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2706
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2707
|
-
);
|
2708
|
-
return {
|
2709
|
-
name: mainFieldName,
|
2710
|
-
type: mainFieldType ?? "string"
|
2711
|
-
};
|
2712
|
-
};
|
2713
|
-
const DEFAULT_SETTINGS = {
|
2714
|
-
bulkable: false,
|
2715
|
-
filterable: false,
|
2716
|
-
searchable: false,
|
2717
|
-
pagination: false,
|
2718
|
-
defaultSortBy: "",
|
2719
|
-
defaultSortOrder: "asc",
|
2720
|
-
mainField: "id",
|
2721
|
-
pageSize: 10
|
2722
|
-
};
|
2723
|
-
const useDocumentLayout = (model) => {
|
2724
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2725
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
2726
|
-
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2727
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
2728
|
-
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
2729
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2730
|
-
const {
|
2731
|
-
data,
|
2732
|
-
isLoading: isLoadingConfigs,
|
2733
|
-
error,
|
2734
|
-
isFetching: isFetchingConfigs
|
2735
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2736
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2737
|
-
React__namespace.useEffect(() => {
|
2738
|
-
if (error) {
|
2739
|
-
toggleNotification({
|
2740
|
-
type: "danger",
|
2741
|
-
message: formatAPIError(error)
|
2742
|
-
});
|
2743
|
-
}
|
2744
|
-
}, [error, formatAPIError, toggleNotification]);
|
2745
|
-
const editLayout = React__namespace.useMemo(
|
2746
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2747
|
-
layout: [],
|
2748
|
-
components: {},
|
2749
|
-
metadatas: {},
|
2750
|
-
options: {},
|
2751
|
-
settings: DEFAULT_SETTINGS
|
2752
|
-
},
|
2753
|
-
[data, isLoading, schemas, schema, components]
|
2754
|
-
);
|
2755
|
-
const listLayout = React__namespace.useMemo(() => {
|
2756
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2757
|
-
layout: [],
|
2758
|
-
metadatas: {},
|
2759
|
-
options: {},
|
2760
|
-
settings: DEFAULT_SETTINGS
|
2761
|
-
};
|
2762
|
-
}, [data, isLoading, schemas, schema, components]);
|
2763
|
-
const { layout: edit } = React__namespace.useMemo(
|
2764
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2765
|
-
layout: editLayout,
|
2766
|
-
query
|
2767
|
-
}),
|
2768
|
-
[editLayout, query, runHookWaterfall]
|
2769
|
-
);
|
2770
|
-
return {
|
2771
|
-
error,
|
2772
|
-
isLoading,
|
2773
|
-
edit,
|
2774
|
-
list: listLayout
|
2775
|
-
};
|
2776
|
-
};
|
2777
|
-
const useDocLayout = () => {
|
2778
|
-
const { model } = useDoc();
|
2779
|
-
return useDocumentLayout(model);
|
2780
|
-
};
|
2781
|
-
const formatEditLayout = (data, {
|
2782
|
-
schemas,
|
2783
|
-
schema,
|
2784
|
-
components
|
2785
|
-
}) => {
|
2786
|
-
let currentPanelIndex = 0;
|
2787
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2788
|
-
data.contentType.layouts.edit,
|
2789
|
-
schema?.attributes,
|
2790
|
-
data.contentType.metadatas,
|
2791
|
-
{ configurations: data.components, schemas: components },
|
2792
|
-
schemas
|
2793
|
-
).reduce((panels, row) => {
|
2794
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2795
|
-
panels.push([row]);
|
2796
|
-
currentPanelIndex += 2;
|
2797
|
-
} else {
|
2798
|
-
if (!panels[currentPanelIndex]) {
|
2799
|
-
panels.push([]);
|
2800
|
-
}
|
2801
|
-
panels[currentPanelIndex].push(row);
|
2802
|
-
}
|
2803
|
-
return panels;
|
2804
|
-
}, []);
|
2805
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2806
|
-
(acc, [uid, configuration]) => {
|
2807
|
-
acc[uid] = {
|
2808
|
-
layout: convertEditLayoutToFieldLayouts(
|
2809
|
-
configuration.layouts.edit,
|
2810
|
-
components[uid].attributes,
|
2811
|
-
configuration.metadatas
|
2812
|
-
),
|
2813
|
-
settings: {
|
2814
|
-
...configuration.settings,
|
2815
|
-
icon: components[uid].info.icon,
|
2816
|
-
displayName: components[uid].info.displayName
|
2998
|
+
}
|
2999
|
+
});
|
3000
|
+
if (!("error" in res)) {
|
3001
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
3002
|
+
}
|
3003
|
+
} finally {
|
3004
|
+
if (!listViewPathMatch) {
|
3005
|
+
setSubmitting(false);
|
3006
|
+
}
|
2817
3007
|
}
|
2818
|
-
}
|
2819
|
-
return acc;
|
2820
|
-
},
|
2821
|
-
{}
|
2822
|
-
);
|
2823
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2824
|
-
(acc, [attribute, metadata]) => {
|
2825
|
-
return {
|
2826
|
-
...acc,
|
2827
|
-
[attribute]: metadata.edit
|
2828
|
-
};
|
2829
|
-
},
|
2830
|
-
{}
|
2831
|
-
);
|
2832
|
-
return {
|
2833
|
-
layout: panelledEditAttributes,
|
2834
|
-
components: componentEditAttributes,
|
2835
|
-
metadatas: editMetadatas,
|
2836
|
-
settings: {
|
2837
|
-
...data.contentType.settings,
|
2838
|
-
displayName: schema?.info.displayName
|
3008
|
+
}
|
2839
3009
|
},
|
2840
|
-
|
2841
|
-
|
2842
|
-
...schema?.pluginOptions,
|
2843
|
-
...data.contentType.options
|
2844
|
-
}
|
3010
|
+
variant: "danger",
|
3011
|
+
position: ["header", "table-row"]
|
2845
3012
|
};
|
2846
3013
|
};
|
2847
|
-
|
2848
|
-
|
2849
|
-
|
2850
|
-
|
2851
|
-
|
2852
|
-
|
2853
|
-
|
2854
|
-
|
2855
|
-
|
2856
|
-
|
2857
|
-
|
2858
|
-
|
2859
|
-
|
2860
|
-
|
2861
|
-
|
2862
|
-
|
2863
|
-
|
2864
|
-
|
2865
|
-
|
2866
|
-
|
2867
|
-
|
2868
|
-
|
2869
|
-
|
2870
|
-
|
2871
|
-
|
2872
|
-
|
2873
|
-
|
2874
|
-
|
2875
|
-
|
3014
|
+
DeleteAction$1.type = "delete";
|
3015
|
+
DeleteAction$1.position = ["header", "table-row"];
|
3016
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
3017
|
+
const Panels = () => {
|
3018
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
3019
|
+
const [
|
3020
|
+
{
|
3021
|
+
query: { status }
|
3022
|
+
}
|
3023
|
+
] = strapiAdmin.useQueryParams({
|
3024
|
+
status: "draft"
|
3025
|
+
});
|
3026
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3027
|
+
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
3028
|
+
const props = {
|
3029
|
+
activeTab: status,
|
3030
|
+
model,
|
3031
|
+
documentId: id,
|
3032
|
+
document: isCloning ? void 0 : document,
|
3033
|
+
meta: isCloning ? void 0 : meta,
|
3034
|
+
collectionType
|
3035
|
+
};
|
3036
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3037
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3038
|
+
{
|
3039
|
+
props,
|
3040
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
3041
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
3042
|
+
}
|
3043
|
+
) });
|
2876
3044
|
};
|
2877
|
-
const
|
2878
|
-
|
2879
|
-
schema,
|
2880
|
-
components
|
2881
|
-
}) => {
|
2882
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2883
|
-
(acc, [attribute, metadata]) => {
|
2884
|
-
return {
|
2885
|
-
...acc,
|
2886
|
-
[attribute]: metadata.list
|
2887
|
-
};
|
2888
|
-
},
|
2889
|
-
{}
|
2890
|
-
);
|
2891
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2892
|
-
data.contentType.layouts.list,
|
2893
|
-
schema?.attributes,
|
2894
|
-
listMetadatas,
|
2895
|
-
{ configurations: data.components, schemas: components },
|
2896
|
-
schemas
|
2897
|
-
);
|
3045
|
+
const ActionsPanel = () => {
|
3046
|
+
const { formatMessage } = reactIntl.useIntl();
|
2898
3047
|
return {
|
2899
|
-
|
2900
|
-
|
2901
|
-
|
2902
|
-
|
2903
|
-
|
2904
|
-
...schema?.pluginOptions,
|
2905
|
-
...data.contentType.options
|
2906
|
-
}
|
3048
|
+
title: formatMessage({
|
3049
|
+
id: "content-manager.containers.edit.panels.default.title",
|
3050
|
+
defaultMessage: "Entry"
|
3051
|
+
}),
|
3052
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2907
3053
|
};
|
2908
3054
|
};
|
2909
|
-
|
2910
|
-
|
2911
|
-
|
2912
|
-
|
2913
|
-
|
3055
|
+
ActionsPanel.type = "actions";
|
3056
|
+
const ActionsPanelContent = () => {
|
3057
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
3058
|
+
const [
|
3059
|
+
{
|
3060
|
+
query: { status = "draft" }
|
2914
3061
|
}
|
2915
|
-
|
2916
|
-
|
2917
|
-
|
2918
|
-
|
2919
|
-
|
2920
|
-
|
2921
|
-
|
2922
|
-
|
2923
|
-
|
2924
|
-
|
2925
|
-
|
2926
|
-
|
2927
|
-
|
2928
|
-
|
3062
|
+
] = strapiAdmin.useQueryParams();
|
3063
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3064
|
+
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
3065
|
+
const props = {
|
3066
|
+
activeTab: status,
|
3067
|
+
model,
|
3068
|
+
documentId: id,
|
3069
|
+
document: isCloning ? void 0 : document,
|
3070
|
+
meta: isCloning ? void 0 : meta,
|
3071
|
+
collectionType
|
3072
|
+
};
|
3073
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3074
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3075
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3076
|
+
{
|
3077
|
+
props,
|
3078
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
|
3079
|
+
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
3080
|
+
}
|
3081
|
+
),
|
3082
|
+
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3083
|
+
] });
|
2929
3084
|
};
|
3085
|
+
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
3086
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
3087
|
+
designSystem.Flex,
|
3088
|
+
{
|
3089
|
+
ref,
|
3090
|
+
tag: "aside",
|
3091
|
+
"aria-labelledby": "additional-information",
|
3092
|
+
background: "neutral0",
|
3093
|
+
borderColor: "neutral150",
|
3094
|
+
hasRadius: true,
|
3095
|
+
paddingBottom: 4,
|
3096
|
+
paddingLeft: 4,
|
3097
|
+
paddingRight: 4,
|
3098
|
+
paddingTop: 4,
|
3099
|
+
shadow: "tableShadow",
|
3100
|
+
gap: 3,
|
3101
|
+
direction: "column",
|
3102
|
+
justifyContent: "stretch",
|
3103
|
+
alignItems: "flex-start",
|
3104
|
+
children: [
|
3105
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3106
|
+
children
|
3107
|
+
]
|
3108
|
+
}
|
3109
|
+
);
|
3110
|
+
});
|
2930
3111
|
const ConfirmBulkActionDialog = ({
|
2931
3112
|
onToggleDialog,
|
2932
3113
|
isOpen = false,
|
@@ -2965,6 +3146,7 @@ const ConfirmDialogPublishAll = ({
|
|
2965
3146
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
2966
3147
|
const { model, schema } = useDoc();
|
2967
3148
|
const [{ query }] = strapiAdmin.useQueryParams();
|
3149
|
+
const enableDraftRelationsCount = false;
|
2968
3150
|
const {
|
2969
3151
|
data: countDraftRelations = 0,
|
2970
3152
|
isLoading,
|
@@ -2976,7 +3158,7 @@ const ConfirmDialogPublishAll = ({
|
|
2976
3158
|
locale: query?.plugins?.i18n?.locale
|
2977
3159
|
},
|
2978
3160
|
{
|
2979
|
-
skip:
|
3161
|
+
skip: !enableDraftRelationsCount
|
2980
3162
|
}
|
2981
3163
|
);
|
2982
3164
|
React__namespace.useEffect(() => {
|
@@ -3161,7 +3343,7 @@ const SelectedEntriesTableContent = ({
|
|
3161
3343
|
status: row.status
|
3162
3344
|
}
|
3163
3345
|
) }),
|
3164
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3346
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3165
3347
|
designSystem.IconButton,
|
3166
3348
|
{
|
3167
3349
|
tag: reactRouterDom.Link,
|
@@ -3170,23 +3352,16 @@ const SelectedEntriesTableContent = ({
|
|
3170
3352
|
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3171
3353
|
},
|
3172
3354
|
state: { from: pathname },
|
3173
|
-
label: formatMessage(
|
3174
|
-
|
3175
|
-
|
3176
|
-
|
3177
|
-
{
|
3178
|
-
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3179
|
-
defaultMessage: "item line {number}"
|
3180
|
-
},
|
3181
|
-
{ number: index2 + 1 }
|
3182
|
-
)
|
3183
|
-
}
|
3184
|
-
),
|
3355
|
+
label: formatMessage({
|
3356
|
+
id: "content-manager.bulk-publish.edit",
|
3357
|
+
defaultMessage: "Edit"
|
3358
|
+
}),
|
3185
3359
|
target: "_blank",
|
3186
3360
|
marginLeft: "auto",
|
3187
|
-
|
3361
|
+
variant: "ghost",
|
3362
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3188
3363
|
}
|
3189
|
-
) })
|
3364
|
+
) }) })
|
3190
3365
|
] }, row.id)) })
|
3191
3366
|
] });
|
3192
3367
|
};
|
@@ -3354,8 +3529,7 @@ const PublishAction = ({ documents, model }) => {
|
|
3354
3529
|
const refetchList = () => {
|
3355
3530
|
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3356
3531
|
};
|
3357
|
-
if (!showPublishButton)
|
3358
|
-
return null;
|
3532
|
+
if (!showPublishButton) return null;
|
3359
3533
|
return {
|
3360
3534
|
actionType: "publish",
|
3361
3535
|
variant: "tertiary",
|
@@ -3423,8 +3597,7 @@ const DeleteAction = ({ documents, model }) => {
|
|
3423
3597
|
selectRow([]);
|
3424
3598
|
}
|
3425
3599
|
};
|
3426
|
-
if (!hasDeletePermission)
|
3427
|
-
return null;
|
3600
|
+
if (!hasDeletePermission) return null;
|
3428
3601
|
return {
|
3429
3602
|
variant: "danger-light",
|
3430
3603
|
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
@@ -3473,8 +3646,7 @@ const UnpublishAction = ({ documents, model }) => {
|
|
3473
3646
|
}
|
3474
3647
|
};
|
3475
3648
|
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3476
|
-
if (!showUnpublishButton)
|
3477
|
-
return null;
|
3649
|
+
if (!showUnpublishButton) return null;
|
3478
3650
|
return {
|
3479
3651
|
variant: "tertiary",
|
3480
3652
|
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
@@ -3579,7 +3751,7 @@ const TableActions = ({ document }) => {
|
|
3579
3751
|
strapiAdmin.DescriptionComponentRenderer,
|
3580
3752
|
{
|
3581
3753
|
props,
|
3582
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3754
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
|
3583
3755
|
children: (actions2) => {
|
3584
3756
|
const tableRowActions = actions2.filter((action) => {
|
3585
3757
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3638,6 +3810,7 @@ const EditAction = ({ documentId }) => {
|
|
3638
3810
|
};
|
3639
3811
|
};
|
3640
3812
|
EditAction.type = "edit";
|
3813
|
+
EditAction.position = "table-row";
|
3641
3814
|
const StyledPencil = styledComponents.styled(Icons.Pencil)`
|
3642
3815
|
path {
|
3643
3816
|
fill: currentColor;
|
@@ -3714,6 +3887,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3714
3887
|
};
|
3715
3888
|
};
|
3716
3889
|
CloneAction.type = "clone";
|
3890
|
+
CloneAction.position = "table-row";
|
3717
3891
|
const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
|
3718
3892
|
path {
|
3719
3893
|
fill: currentColor;
|
@@ -3800,7 +3974,14 @@ class ContentManagerPlugin {
|
|
3800
3974
|
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3801
3975
|
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3802
3976
|
getBulkActions: () => this.bulkActions,
|
3803
|
-
getDocumentActions: () =>
|
3977
|
+
getDocumentActions: (position) => {
|
3978
|
+
if (position) {
|
3979
|
+
return this.documentActions.filter(
|
3980
|
+
(action) => action.position == void 0 || [action.position].flat().includes(position)
|
3981
|
+
);
|
3982
|
+
}
|
3983
|
+
return this.documentActions;
|
3984
|
+
},
|
3804
3985
|
getEditViewSidePanels: () => this.editViewSidePanels,
|
3805
3986
|
getHeaderActions: () => this.headerActions
|
3806
3987
|
}
|
@@ -3810,10 +3991,8 @@ class ContentManagerPlugin {
|
|
3810
3991
|
const getPrintableType = (value) => {
|
3811
3992
|
const nativeType = typeof value;
|
3812
3993
|
if (nativeType === "object") {
|
3813
|
-
if (value === null)
|
3814
|
-
|
3815
|
-
if (Array.isArray(value))
|
3816
|
-
return "array";
|
3994
|
+
if (value === null) return "null";
|
3995
|
+
if (Array.isArray(value)) return "array";
|
3817
3996
|
if (value instanceof Object && value.constructor.name !== "Object") {
|
3818
3997
|
return value.constructor.name;
|
3819
3998
|
}
|
@@ -3824,17 +4003,27 @@ const HistoryAction = ({ model, document }) => {
|
|
3824
4003
|
const { formatMessage } = reactIntl.useIntl();
|
3825
4004
|
const [{ query }] = strapiAdmin.useQueryParams();
|
3826
4005
|
const navigate = reactRouterDom.useNavigate();
|
4006
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
4007
|
+
const { pathname } = reactRouterDom.useLocation();
|
3827
4008
|
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
3828
4009
|
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3829
4010
|
return null;
|
3830
4011
|
}
|
4012
|
+
const handleOnClick = () => {
|
4013
|
+
const destination = { pathname: "history", search: pluginsQueryParams };
|
4014
|
+
trackUsage("willNavigate", {
|
4015
|
+
from: pathname,
|
4016
|
+
to: `${pathname}/${destination.pathname}`
|
4017
|
+
});
|
4018
|
+
navigate(destination);
|
4019
|
+
};
|
3831
4020
|
return {
|
3832
4021
|
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
3833
4022
|
label: formatMessage({
|
3834
4023
|
id: "content-manager.history.document-action",
|
3835
4024
|
defaultMessage: "Content History"
|
3836
4025
|
}),
|
3837
|
-
onClick:
|
4026
|
+
onClick: handleOnClick,
|
3838
4027
|
disabled: (
|
3839
4028
|
/**
|
3840
4029
|
* The user is creating a new document.
|
@@ -3856,6 +4045,7 @@ const HistoryAction = ({ model, document }) => {
|
|
3856
4045
|
};
|
3857
4046
|
};
|
3858
4047
|
HistoryAction.type = "history";
|
4048
|
+
HistoryAction.position = "header";
|
3859
4049
|
const historyAdmin = {
|
3860
4050
|
bootstrap(app) {
|
3861
4051
|
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
@@ -3902,6 +4092,88 @@ const { setInitialData } = actions;
|
|
3902
4092
|
const reducer = toolkit.combineReducers({
|
3903
4093
|
app: reducer$1
|
3904
4094
|
});
|
4095
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4096
|
+
endpoints: (builder) => ({
|
4097
|
+
getPreviewUrl: builder.query({
|
4098
|
+
query({ query, params }) {
|
4099
|
+
return {
|
4100
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4101
|
+
method: "GET",
|
4102
|
+
config: {
|
4103
|
+
params: query
|
4104
|
+
}
|
4105
|
+
};
|
4106
|
+
}
|
4107
|
+
})
|
4108
|
+
})
|
4109
|
+
});
|
4110
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4111
|
+
const ConditionalTooltip = ({ isShown, label, children }) => {
|
4112
|
+
if (isShown) {
|
4113
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { label, children });
|
4114
|
+
}
|
4115
|
+
return children;
|
4116
|
+
};
|
4117
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4118
|
+
const { formatMessage } = reactIntl.useIntl();
|
4119
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
4120
|
+
const { pathname } = reactRouterDom.useLocation();
|
4121
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
4122
|
+
const isModified = strapiAdmin.useForm("PreviewSidePanel", (state) => state.modified);
|
4123
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4124
|
+
params: {
|
4125
|
+
contentType: model
|
4126
|
+
},
|
4127
|
+
query: {
|
4128
|
+
documentId,
|
4129
|
+
locale: document?.locale,
|
4130
|
+
status: document?.status
|
4131
|
+
}
|
4132
|
+
});
|
4133
|
+
if (!data?.data?.url || error) {
|
4134
|
+
return null;
|
4135
|
+
}
|
4136
|
+
const trackNavigation = () => {
|
4137
|
+
const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
|
4138
|
+
trackUsage("willNavigate", { from: pathname, to: destinationPathname });
|
4139
|
+
};
|
4140
|
+
return {
|
4141
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4142
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(
|
4143
|
+
ConditionalTooltip,
|
4144
|
+
{
|
4145
|
+
label: formatMessage({
|
4146
|
+
id: "content-manager.preview.panel.button-disabled-tooltip",
|
4147
|
+
defaultMessage: "Please save to open the preview"
|
4148
|
+
}),
|
4149
|
+
isShown: isModified,
|
4150
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { cursor: "not-allowed", width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
|
4151
|
+
designSystem.Button,
|
4152
|
+
{
|
4153
|
+
variant: "tertiary",
|
4154
|
+
tag: reactRouterDom.Link,
|
4155
|
+
to: { pathname: "preview", search: qs.stringify(query, { encode: false }) },
|
4156
|
+
onClick: trackNavigation,
|
4157
|
+
width: "100%",
|
4158
|
+
disabled: isModified,
|
4159
|
+
pointerEvents: isModified ? "none" : void 0,
|
4160
|
+
tabIndex: isModified ? -1 : void 0,
|
4161
|
+
children: formatMessage({
|
4162
|
+
id: "content-manager.preview.panel.button",
|
4163
|
+
defaultMessage: "Open preview"
|
4164
|
+
})
|
4165
|
+
}
|
4166
|
+
) })
|
4167
|
+
}
|
4168
|
+
)
|
4169
|
+
};
|
4170
|
+
};
|
4171
|
+
const previewAdmin = {
|
4172
|
+
bootstrap(app) {
|
4173
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4174
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4175
|
+
}
|
4176
|
+
};
|
3905
4177
|
const index = {
|
3906
4178
|
register(app) {
|
3907
4179
|
const cm = new ContentManagerPlugin();
|
@@ -3921,7 +4193,7 @@ const index = {
|
|
3921
4193
|
app.router.addRoute({
|
3922
4194
|
path: "content-manager/*",
|
3923
4195
|
lazy: async () => {
|
3924
|
-
const { Layout } = await Promise.resolve().then(() => require("./layout-
|
4196
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-C3fN7Ejz.js"));
|
3925
4197
|
return {
|
3926
4198
|
Component: Layout
|
3927
4199
|
};
|
@@ -3934,11 +4206,14 @@ const index = {
|
|
3934
4206
|
if (typeof historyAdmin.bootstrap === "function") {
|
3935
4207
|
historyAdmin.bootstrap(app);
|
3936
4208
|
}
|
4209
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4210
|
+
previewAdmin.bootstrap(app);
|
4211
|
+
}
|
3937
4212
|
},
|
3938
4213
|
async registerTrads({ locales }) {
|
3939
4214
|
const importedTrads = await Promise.all(
|
3940
4215
|
locales.map((locale) => {
|
3941
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-
|
4216
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-BK8Xyl5I.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-9K52xZIr.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B2Kyv8Z9.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-7sfIbjxE.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`, 3).then(({ default: data }) => {
|
3942
4217
|
return {
|
3943
4218
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3944
4219
|
locale
|
@@ -3984,6 +4259,7 @@ exports.getMainField = getMainField;
|
|
3984
4259
|
exports.getTranslation = getTranslation;
|
3985
4260
|
exports.index = index;
|
3986
4261
|
exports.setInitialData = setInitialData;
|
4262
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3987
4263
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3988
4264
|
exports.useDoc = useDoc;
|
3989
4265
|
exports.useDocLayout = useDocLayout;
|
@@ -3995,5 +4271,6 @@ exports.useGetAllContentTypeSettingsQuery = useGetAllContentTypeSettingsQuery;
|
|
3995
4271
|
exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
3996
4272
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3997
4273
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
4274
|
+
exports.useGetPreviewUrlQuery = useGetPreviewUrlQuery;
|
3998
4275
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3999
|
-
//# sourceMappingURL=index-
|
4276
|
+
//# sourceMappingURL=index-BUWEmX8m.js.map
|