@strapi/content-manager 0.0.0-experimental.9df68962083938acba06546a7901c68a63266aec → 0.0.0-experimental.9f812af47f0e9db3d5531382c836c2ac0776afdf
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/LICENSE +18 -3
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-BSEZcJVB.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-BSEZcJVB.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs → ComponentConfigurationPage-BiASGi7x.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-BiASGi7x.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-DjFJw56M.js → EditConfigurationPage-D2rtvneE.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-D2rtvneE.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs → EditConfigurationPage-vN4zupij.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-vN4zupij.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-BwisF04Q.js} +63 -13
- package/dist/_chunks/EditViewPage-BwisF04Q.js.map +1 -0
- package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-_A31Cl4g.mjs} +63 -12
- package/dist/_chunks/EditViewPage-_A31Cl4g.mjs.map +1 -0
- package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-CvIunNOj.mjs} +405 -256
- package/dist/_chunks/Field-CvIunNOj.mjs.map +1 -0
- package/dist/_chunks/{Field-Boxf9Ajp.js → Field-Dsu6-FrM.js} +409 -260
- package/dist/_chunks/Field-Dsu6-FrM.js.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-DHrru2AV.mjs → Form-DK0fG0Gj.mjs} +37 -18
- package/dist/_chunks/Form-DK0fG0Gj.mjs.map +1 -0
- package/dist/_chunks/{Form-y5g1SRsh.js → Form-DUwWcCmA.js} +39 -21
- package/dist/_chunks/Form-DUwWcCmA.js.map +1 -0
- package/dist/_chunks/{History-CqN6K7SX.js → History-CeCDhoJG.js} +81 -114
- package/dist/_chunks/History-CeCDhoJG.js.map +1 -0
- package/dist/_chunks/{History-Bru_KoeP.mjs → History-DP8gmXpm.mjs} +82 -114
- package/dist/_chunks/History-DP8gmXpm.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-BCkO5iuN.mjs} +25 -12
- package/dist/_chunks/ListConfigurationPage-BCkO5iuN.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-C-bAd44a.js} +25 -13
- package/dist/_chunks/ListConfigurationPage-C-bAd44a.js.map +1 -0
- package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-BKTZFhsM.js} +121 -81
- package/dist/_chunks/ListViewPage-BKTZFhsM.js.map +1 -0
- package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-Cf_DgaFV.mjs} +118 -77
- package/dist/_chunks/ListViewPage-Cf_DgaFV.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-D3Cm3v3q.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-D3Cm3v3q.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-nHIyvJcB.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-nHIyvJcB.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-BALVSJ7x.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-BALVSJ7x.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-CChGWBj5.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-CChGWBj5.js.map} +1 -1
- package/dist/_chunks/Preview-C4NBzKUV.mjs +294 -0
- package/dist/_chunks/Preview-C4NBzKUV.mjs.map +1 -0
- package/dist/_chunks/Preview-CT28Ckpg.js +312 -0
- package/dist/_chunks/Preview-CT28Ckpg.js.map +1 -0
- package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-C8uC89cT.mjs} +76 -42
- package/dist/_chunks/Relations-C8uC89cT.mjs.map +1 -0
- package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-CvkPCng_.js} +76 -43
- package/dist/_chunks/Relations-CvkPCng_.js.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-BK8Xyl5I.js} +32 -18
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-BK8Xyl5I.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-Dtk_ot79.mjs} +32 -18
- package/dist/_chunks/{en-Ux26r5pl.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-DVPWZkbS.js → index-CnX_j5h-.js} +1235 -746
- package/dist/_chunks/index-CnX_j5h-.js.map +1 -0
- package/dist/_chunks/{index-DJXJw9V5.mjs → index-Dh2aGTGJ.mjs} +1252 -763
- package/dist/_chunks/index-Dh2aGTGJ.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-Bau7ZfLV.mjs → layout-B5qsPihj.mjs} +26 -13
- package/dist/_chunks/layout-B5qsPihj.mjs.map +1 -0
- package/dist/_chunks/{layout-Dm6fbiQj.js → layout-B_qdWGny.js} +26 -14
- package/dist/_chunks/layout-B_qdWGny.js.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-CKnpRgrN.js → relations-ChcieiF5.js} +6 -7
- package/dist/_chunks/relations-ChcieiF5.js.map +1 -0
- package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-DMXpNY-e.mjs} +6 -7
- package/dist/_chunks/relations-DMXpNY-e.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 +5 -4
- package/dist/admin/src/content-manager.d.ts +3 -2
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +2 -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/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/router.d.ts +1 -1
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +19 -20
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +686 -360
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +687 -360
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/uid.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +16 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +4 -4
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +7 -6
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- 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 +12 -10
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +7 -6
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/preview.d.ts +27 -0
- package/dist/shared/contracts/preview.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +4 -0
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +17 -15
- package/dist/_chunks/EditViewPage-CPj61RMh.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-zT3fBr4Y.js.map +0 -1
- package/dist/_chunks/Field-Boxf9Ajp.js.map +0 -1
- package/dist/_chunks/Field-dha5VnIQ.mjs.map +0 -1
- package/dist/_chunks/Form-DHrru2AV.mjs.map +0 -1
- package/dist/_chunks/Form-y5g1SRsh.js.map +0 -1
- package/dist/_chunks/History-Bru_KoeP.mjs.map +0 -1
- package/dist/_chunks/History-CqN6K7SX.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-D8wGABj0.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-R_p-SbHZ.js.map +0 -1
- package/dist/_chunks/ListViewPage-SID6TRb9.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-pEw_zug9.js.map +0 -1
- package/dist/_chunks/Relations-B9Crnhnn.mjs.map +0 -1
- package/dist/_chunks/Relations-DjTQ5kGB.js.map +0 -1
- package/dist/_chunks/index-DJXJw9V5.mjs.map +0 -1
- package/dist/_chunks/index-DVPWZkbS.js.map +0 -1
- package/dist/_chunks/layout-Bau7ZfLV.mjs.map +0 -1
- package/dist/_chunks/layout-Dm6fbiQj.js.map +0 -1
- package/dist/_chunks/relations-BH_kBSJ0.mjs.map +0 -1
- package/dist/_chunks/relations-CKnpRgrN.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
@@ -2,20 +2,20 @@
|
|
2
2
|
const Icons = require("@strapi/icons");
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
4
4
|
const strapiAdmin = require("@strapi/admin/strapi-admin");
|
5
|
-
const qs = require("qs");
|
6
|
-
const reactIntl = require("react-intl");
|
7
|
-
const reactRouterDom = require("react-router-dom");
|
8
5
|
const React = require("react");
|
9
6
|
const designSystem = require("@strapi/design-system");
|
7
|
+
const mapValues = require("lodash/fp/mapValues");
|
8
|
+
const reactIntl = require("react-intl");
|
9
|
+
const reactRouterDom = require("react-router-dom");
|
10
10
|
const styledComponents = require("styled-components");
|
11
11
|
const yup = require("yup");
|
12
|
+
const qs = require("qs");
|
12
13
|
const pipe = require("lodash/fp/pipe");
|
13
14
|
const dateFns = require("date-fns");
|
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";
|
@@ -70,42 +78,6 @@ const useInjectionZone = (area) => {
|
|
70
78
|
const [page, position] = area.split(".");
|
71
79
|
return contentManagerPlugin.getInjectedComponents(page, position);
|
72
80
|
};
|
73
|
-
const HistoryAction = ({ model, document }) => {
|
74
|
-
const { formatMessage } = reactIntl.useIntl();
|
75
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
76
|
-
const navigate = reactRouterDom.useNavigate();
|
77
|
-
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
78
|
-
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
79
|
-
return null;
|
80
|
-
}
|
81
|
-
return {
|
82
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
83
|
-
label: formatMessage({
|
84
|
-
id: "content-manager.history.document-action",
|
85
|
-
defaultMessage: "Content History"
|
86
|
-
}),
|
87
|
-
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
88
|
-
disabled: (
|
89
|
-
/**
|
90
|
-
* The user is creating a new document.
|
91
|
-
* It hasn't been saved yet, so there's no history to go to
|
92
|
-
*/
|
93
|
-
!document || /**
|
94
|
-
* The document has been created but the current dimension has never been saved.
|
95
|
-
* For example, the user is creating a new locale in an existing document,
|
96
|
-
* so there's no history for the document in that locale
|
97
|
-
*/
|
98
|
-
!document.id || /**
|
99
|
-
* History is only available for content types created by the user.
|
100
|
-
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
101
|
-
* which start with `admin::` or `plugin::`
|
102
|
-
*/
|
103
|
-
!model.startsWith("api::")
|
104
|
-
),
|
105
|
-
position: "header"
|
106
|
-
};
|
107
|
-
};
|
108
|
-
HistoryAction.type = "history";
|
109
81
|
const ID = "id";
|
110
82
|
const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
|
111
83
|
const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
|
@@ -157,6 +129,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
157
129
|
if (!slug) {
|
158
130
|
throw new Error("Cannot find the slug param in the URL");
|
159
131
|
}
|
132
|
+
const [{ rawQuery }] = strapiAdmin.useQueryParams();
|
160
133
|
const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
|
161
134
|
const contentTypePermissions = React__namespace.useMemo(() => {
|
162
135
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -167,7 +140,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
167
140
|
return { ...acc, [action]: [permission] };
|
168
141
|
}, {});
|
169
142
|
}, [slug, userPermissions]);
|
170
|
-
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
|
+
);
|
171
151
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
172
152
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
173
153
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -215,7 +195,8 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
|
215
195
|
"Document",
|
216
196
|
"InitialData",
|
217
197
|
"HistoryVersion",
|
218
|
-
"Relations"
|
198
|
+
"Relations",
|
199
|
+
"UidAvailability"
|
219
200
|
]
|
220
201
|
});
|
221
202
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -229,7 +210,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
229
210
|
params: query
|
230
211
|
}
|
231
212
|
}),
|
232
|
-
invalidatesTags: (_result,
|
213
|
+
invalidatesTags: (_result, error, { model }) => {
|
214
|
+
if (error) {
|
215
|
+
return [];
|
216
|
+
}
|
217
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
218
|
+
}
|
233
219
|
}),
|
234
220
|
cloneDocument: builder.mutation({
|
235
221
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -240,7 +226,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
240
226
|
params
|
241
227
|
}
|
242
228
|
}),
|
243
|
-
invalidatesTags: (_result, _error, { model }) => [
|
229
|
+
invalidatesTags: (_result, _error, { model }) => [
|
230
|
+
{ type: "Document", id: `${model}_LIST` },
|
231
|
+
{ type: "UidAvailability", id: model }
|
232
|
+
]
|
244
233
|
}),
|
245
234
|
/**
|
246
235
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -257,8 +246,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
257
246
|
}),
|
258
247
|
invalidatesTags: (result, _error, { model }) => [
|
259
248
|
{ type: "Document", id: `${model}_LIST` },
|
260
|
-
"Relations"
|
261
|
-
|
249
|
+
"Relations",
|
250
|
+
{ type: "UidAvailability", id: model }
|
251
|
+
],
|
252
|
+
transformResponse: (response, meta, arg) => {
|
253
|
+
if (!("data" in response) && arg.model === "plugin::users-permissions.user") {
|
254
|
+
return {
|
255
|
+
data: response,
|
256
|
+
meta: {
|
257
|
+
availableStatus: [],
|
258
|
+
availableLocales: []
|
259
|
+
}
|
260
|
+
};
|
261
|
+
}
|
262
|
+
return response;
|
263
|
+
}
|
262
264
|
}),
|
263
265
|
deleteDocument: builder.mutation({
|
264
266
|
query: ({ collectionType, model, documentId, params }) => ({
|
@@ -298,7 +300,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
298
300
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
299
301
|
},
|
300
302
|
{ type: "Document", id: `${model}_LIST` },
|
301
|
-
"Relations"
|
303
|
+
"Relations",
|
304
|
+
{ type: "UidAvailability", id: model }
|
302
305
|
];
|
303
306
|
}
|
304
307
|
}),
|
@@ -311,11 +314,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
311
314
|
url: `/content-manager/collection-types/${model}`,
|
312
315
|
method: "GET",
|
313
316
|
config: {
|
314
|
-
params
|
317
|
+
params: qs.stringify(params, { encode: true })
|
315
318
|
}
|
316
319
|
}),
|
317
320
|
providesTags: (result, _error, arg) => {
|
318
321
|
return [
|
322
|
+
{ type: "Document", id: `ALL_LIST` },
|
319
323
|
{ type: "Document", id: `${arg.model}_LIST` },
|
320
324
|
...result?.results.map(({ documentId }) => ({
|
321
325
|
type: "Document",
|
@@ -354,6 +358,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
354
358
|
{
|
355
359
|
type: "Document",
|
356
360
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
361
|
+
},
|
362
|
+
// Make it easy to invalidate all individual documents queries for a model
|
363
|
+
{
|
364
|
+
type: "Document",
|
365
|
+
id: `${model}_ALL_ITEMS`
|
357
366
|
}
|
358
367
|
];
|
359
368
|
}
|
@@ -417,8 +426,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
417
426
|
type: "Document",
|
418
427
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
419
428
|
},
|
420
|
-
"Relations"
|
429
|
+
"Relations",
|
430
|
+
{ type: "UidAvailability", id: model }
|
421
431
|
];
|
432
|
+
},
|
433
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
434
|
+
const patchResult = dispatch(
|
435
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
436
|
+
Object.assign(draft.data, data);
|
437
|
+
})
|
438
|
+
);
|
439
|
+
try {
|
440
|
+
await queryFulfilled;
|
441
|
+
} catch {
|
442
|
+
patchResult.undo();
|
443
|
+
}
|
422
444
|
}
|
423
445
|
}),
|
424
446
|
unpublishDocument: builder.mutation({
|
@@ -471,8 +493,7 @@ const {
|
|
471
493
|
useUnpublishManyDocumentsMutation
|
472
494
|
} = documentApi;
|
473
495
|
const buildValidParams = (query) => {
|
474
|
-
if (!query)
|
475
|
-
return query;
|
496
|
+
if (!query) return query;
|
476
497
|
const { plugins: _, ...validQueryParams } = {
|
477
498
|
...query,
|
478
499
|
...Object.values(query?.plugins ?? {}).reduce(
|
@@ -480,28 +501,44 @@ const buildValidParams = (query) => {
|
|
480
501
|
{}
|
481
502
|
)
|
482
503
|
};
|
483
|
-
if ("_q" in validQueryParams) {
|
484
|
-
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
485
|
-
}
|
486
504
|
return validQueryParams;
|
487
505
|
};
|
488
506
|
const isBaseQueryError = (error) => {
|
489
507
|
return error.name !== void 0;
|
490
508
|
};
|
491
|
-
const
|
509
|
+
const arrayValidator = (attribute, options) => ({
|
510
|
+
message: strapiAdmin.translatedErrors.required,
|
511
|
+
test(value) {
|
512
|
+
if (options.status === "draft") {
|
513
|
+
return true;
|
514
|
+
}
|
515
|
+
if (!attribute.required) {
|
516
|
+
return true;
|
517
|
+
}
|
518
|
+
if (!value) {
|
519
|
+
return false;
|
520
|
+
}
|
521
|
+
if (Array.isArray(value) && value.length === 0) {
|
522
|
+
return false;
|
523
|
+
}
|
524
|
+
return true;
|
525
|
+
}
|
526
|
+
});
|
527
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
492
528
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
493
529
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
494
530
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
495
531
|
return acc;
|
496
532
|
}
|
497
533
|
const validations = [
|
534
|
+
addNullableValidation,
|
498
535
|
addRequiredValidation,
|
499
536
|
addMinLengthValidation,
|
500
537
|
addMaxLengthValidation,
|
501
538
|
addMinValidation,
|
502
539
|
addMaxValidation,
|
503
540
|
addRegexValidation
|
504
|
-
].map((fn) => fn(attribute));
|
541
|
+
].map((fn) => fn(attribute, options));
|
505
542
|
const transformSchema = pipe__default.default(...validations);
|
506
543
|
switch (attribute.type) {
|
507
544
|
case "component": {
|
@@ -511,12 +548,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
511
548
|
...acc,
|
512
549
|
[name]: transformSchema(
|
513
550
|
yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
|
514
|
-
)
|
551
|
+
).test(arrayValidator(attribute, options))
|
515
552
|
};
|
516
553
|
} else {
|
517
554
|
return {
|
518
555
|
...acc,
|
519
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
556
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
520
557
|
};
|
521
558
|
}
|
522
559
|
}
|
@@ -538,7 +575,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
538
575
|
}
|
539
576
|
)
|
540
577
|
)
|
541
|
-
)
|
578
|
+
).test(arrayValidator(attribute, options))
|
542
579
|
};
|
543
580
|
case "relation":
|
544
581
|
return {
|
@@ -550,7 +587,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
550
587
|
} else if (Array.isArray(value)) {
|
551
588
|
return yup__namespace.array().of(
|
552
589
|
yup__namespace.object().shape({
|
553
|
-
id: yup__namespace.
|
590
|
+
id: yup__namespace.number().required()
|
554
591
|
})
|
555
592
|
);
|
556
593
|
} else if (typeof value === "object") {
|
@@ -602,6 +639,14 @@ const createAttributeSchema = (attribute) => {
|
|
602
639
|
if (!value || typeof value === "string" && value.length === 0) {
|
603
640
|
return true;
|
604
641
|
}
|
642
|
+
if (typeof value === "object") {
|
643
|
+
try {
|
644
|
+
JSON.stringify(value);
|
645
|
+
return true;
|
646
|
+
} catch (err) {
|
647
|
+
return false;
|
648
|
+
}
|
649
|
+
}
|
605
650
|
try {
|
606
651
|
JSON.parse(value);
|
607
652
|
return true;
|
@@ -620,13 +665,7 @@ const createAttributeSchema = (attribute) => {
|
|
620
665
|
return yup__namespace.mixed();
|
621
666
|
}
|
622
667
|
};
|
623
|
-
const
|
624
|
-
if (attribute.required) {
|
625
|
-
return schema.required({
|
626
|
-
id: strapiAdmin.translatedErrors.required.id,
|
627
|
-
defaultMessage: "This field is required."
|
628
|
-
});
|
629
|
-
}
|
668
|
+
const nullableSchema = (schema) => {
|
630
669
|
return schema?.nullable ? schema.nullable() : (
|
631
670
|
// In some cases '.nullable' will not be available on the schema.
|
632
671
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -634,7 +673,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
634
673
|
schema
|
635
674
|
);
|
636
675
|
};
|
637
|
-
const
|
676
|
+
const addNullableValidation = () => (schema) => {
|
677
|
+
return nullableSchema(schema);
|
678
|
+
};
|
679
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
680
|
+
if (options.status === "draft" || !attribute.required) {
|
681
|
+
return schema;
|
682
|
+
}
|
683
|
+
if (attribute.required && "required" in schema) {
|
684
|
+
return schema.required(strapiAdmin.translatedErrors.required);
|
685
|
+
}
|
686
|
+
return schema;
|
687
|
+
};
|
688
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
689
|
+
if (options.status === "draft") {
|
690
|
+
return schema;
|
691
|
+
}
|
638
692
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
639
693
|
return schema.min(attribute.minLength, {
|
640
694
|
...strapiAdmin.translatedErrors.minLength,
|
@@ -656,10 +710,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
656
710
|
}
|
657
711
|
return schema;
|
658
712
|
};
|
659
|
-
const addMinValidation = (attribute) => (schema) => {
|
660
|
-
if ("
|
713
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
714
|
+
if (options.status === "draft") {
|
715
|
+
return schema;
|
716
|
+
}
|
717
|
+
if ("min" in attribute && "min" in schema) {
|
661
718
|
const min = toInteger(attribute.min);
|
662
|
-
if (
|
719
|
+
if (min) {
|
663
720
|
return schema.min(min, {
|
664
721
|
...strapiAdmin.translatedErrors.min,
|
665
722
|
values: {
|
@@ -777,16 +834,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
777
834
|
}, {});
|
778
835
|
return componentsByKey;
|
779
836
|
};
|
780
|
-
const
|
837
|
+
const HOOKS = {
|
838
|
+
/**
|
839
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
840
|
+
* @constant
|
841
|
+
* @type {string}
|
842
|
+
*/
|
843
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
844
|
+
/**
|
845
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
846
|
+
* @constant
|
847
|
+
* @type {string}
|
848
|
+
*/
|
849
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
850
|
+
/**
|
851
|
+
* Hook that allows to mutate the CM's edit view layout
|
852
|
+
* @constant
|
853
|
+
* @type {string}
|
854
|
+
*/
|
855
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
856
|
+
/**
|
857
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
858
|
+
* @constant
|
859
|
+
* @type {string}
|
860
|
+
*/
|
861
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
862
|
+
};
|
863
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
864
|
+
endpoints: (builder) => ({
|
865
|
+
getContentTypeConfiguration: builder.query({
|
866
|
+
query: (uid) => ({
|
867
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
868
|
+
method: "GET"
|
869
|
+
}),
|
870
|
+
transformResponse: (response) => response.data,
|
871
|
+
providesTags: (_result, _error, uid) => [
|
872
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
873
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
874
|
+
]
|
875
|
+
}),
|
876
|
+
getAllContentTypeSettings: builder.query({
|
877
|
+
query: () => "/content-manager/content-types-settings",
|
878
|
+
transformResponse: (response) => response.data,
|
879
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
880
|
+
}),
|
881
|
+
updateContentTypeConfiguration: builder.mutation({
|
882
|
+
query: ({ uid, ...body }) => ({
|
883
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
884
|
+
method: "PUT",
|
885
|
+
data: body
|
886
|
+
}),
|
887
|
+
transformResponse: (response) => response.data,
|
888
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
889
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
890
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
891
|
+
// Is this necessary?
|
892
|
+
{ type: "InitialData" }
|
893
|
+
]
|
894
|
+
})
|
895
|
+
})
|
896
|
+
});
|
897
|
+
const {
|
898
|
+
useGetContentTypeConfigurationQuery,
|
899
|
+
useGetAllContentTypeSettingsQuery,
|
900
|
+
useUpdateContentTypeConfigurationMutation
|
901
|
+
} = contentTypesApi;
|
902
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
903
|
+
const { type } = attribute;
|
904
|
+
if (type === "relation") {
|
905
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
906
|
+
}
|
907
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
908
|
+
};
|
909
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
910
|
+
if (!mainFieldName) {
|
911
|
+
return void 0;
|
912
|
+
}
|
913
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
914
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
915
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
916
|
+
);
|
917
|
+
return {
|
918
|
+
name: mainFieldName,
|
919
|
+
type: mainFieldType ?? "string"
|
920
|
+
};
|
921
|
+
};
|
922
|
+
const DEFAULT_SETTINGS = {
|
923
|
+
bulkable: false,
|
924
|
+
filterable: false,
|
925
|
+
searchable: false,
|
926
|
+
pagination: false,
|
927
|
+
defaultSortBy: "",
|
928
|
+
defaultSortOrder: "asc",
|
929
|
+
mainField: "id",
|
930
|
+
pageSize: 10
|
931
|
+
};
|
932
|
+
const useDocumentLayout = (model) => {
|
933
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
934
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
935
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
781
936
|
const { toggleNotification } = strapiAdmin.useNotification();
|
782
937
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
938
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
783
939
|
const {
|
784
|
-
|
785
|
-
isLoading:
|
786
|
-
|
787
|
-
|
788
|
-
} =
|
789
|
-
const
|
940
|
+
data,
|
941
|
+
isLoading: isLoadingConfigs,
|
942
|
+
error,
|
943
|
+
isFetching: isFetchingConfigs
|
944
|
+
} = useGetContentTypeConfigurationQuery(model);
|
945
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
790
946
|
React__namespace.useEffect(() => {
|
791
947
|
if (error) {
|
792
948
|
toggleNotification({
|
@@ -794,40 +950,256 @@ const useDocument = (args, opts) => {
|
|
794
950
|
message: formatAPIError(error)
|
795
951
|
});
|
796
952
|
}
|
797
|
-
}, [
|
798
|
-
const
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
(document) => {
|
806
|
-
if (!validationSchema) {
|
807
|
-
throw new Error(
|
808
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
809
|
-
);
|
810
|
-
}
|
811
|
-
try {
|
812
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
813
|
-
return null;
|
814
|
-
} catch (error2) {
|
815
|
-
if (error2 instanceof yup.ValidationError) {
|
816
|
-
return strapiAdmin.getYupValidationErrors(error2);
|
817
|
-
}
|
818
|
-
throw error2;
|
819
|
-
}
|
953
|
+
}, [error, formatAPIError, toggleNotification]);
|
954
|
+
const editLayout = React__namespace.useMemo(
|
955
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
956
|
+
layout: [],
|
957
|
+
components: {},
|
958
|
+
metadatas: {},
|
959
|
+
options: {},
|
960
|
+
settings: DEFAULT_SETTINGS
|
820
961
|
},
|
821
|
-
[
|
962
|
+
[data, isLoading, schemas, schema, components]
|
963
|
+
);
|
964
|
+
const listLayout = React__namespace.useMemo(() => {
|
965
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
966
|
+
layout: [],
|
967
|
+
metadatas: {},
|
968
|
+
options: {},
|
969
|
+
settings: DEFAULT_SETTINGS
|
970
|
+
};
|
971
|
+
}, [data, isLoading, schemas, schema, components]);
|
972
|
+
const { layout: edit } = React__namespace.useMemo(
|
973
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
974
|
+
layout: editLayout,
|
975
|
+
query
|
976
|
+
}),
|
977
|
+
[editLayout, query, runHookWaterfall]
|
822
978
|
);
|
823
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
824
979
|
return {
|
825
|
-
|
826
|
-
document: data?.data,
|
827
|
-
meta: data?.meta,
|
980
|
+
error,
|
828
981
|
isLoading,
|
829
|
-
|
830
|
-
|
982
|
+
edit,
|
983
|
+
list: listLayout
|
984
|
+
};
|
985
|
+
};
|
986
|
+
const useDocLayout = () => {
|
987
|
+
const { model } = useDoc();
|
988
|
+
return useDocumentLayout(model);
|
989
|
+
};
|
990
|
+
const formatEditLayout = (data, {
|
991
|
+
schemas,
|
992
|
+
schema,
|
993
|
+
components
|
994
|
+
}) => {
|
995
|
+
let currentPanelIndex = 0;
|
996
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
997
|
+
data.contentType.layouts.edit,
|
998
|
+
schema?.attributes,
|
999
|
+
data.contentType.metadatas,
|
1000
|
+
{ configurations: data.components, schemas: components },
|
1001
|
+
schemas
|
1002
|
+
).reduce((panels, row) => {
|
1003
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
1004
|
+
panels.push([row]);
|
1005
|
+
currentPanelIndex += 2;
|
1006
|
+
} else {
|
1007
|
+
if (!panels[currentPanelIndex]) {
|
1008
|
+
panels.push([row]);
|
1009
|
+
} else {
|
1010
|
+
panels[currentPanelIndex].push(row);
|
1011
|
+
}
|
1012
|
+
}
|
1013
|
+
return panels;
|
1014
|
+
}, []);
|
1015
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
1016
|
+
(acc, [uid, configuration]) => {
|
1017
|
+
acc[uid] = {
|
1018
|
+
layout: convertEditLayoutToFieldLayouts(
|
1019
|
+
configuration.layouts.edit,
|
1020
|
+
components[uid].attributes,
|
1021
|
+
configuration.metadatas,
|
1022
|
+
{ configurations: data.components, schemas: components }
|
1023
|
+
),
|
1024
|
+
settings: {
|
1025
|
+
...configuration.settings,
|
1026
|
+
icon: components[uid].info.icon,
|
1027
|
+
displayName: components[uid].info.displayName
|
1028
|
+
}
|
1029
|
+
};
|
1030
|
+
return acc;
|
1031
|
+
},
|
1032
|
+
{}
|
1033
|
+
);
|
1034
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1035
|
+
(acc, [attribute, metadata]) => {
|
1036
|
+
return {
|
1037
|
+
...acc,
|
1038
|
+
[attribute]: metadata.edit
|
1039
|
+
};
|
1040
|
+
},
|
1041
|
+
{}
|
1042
|
+
);
|
1043
|
+
return {
|
1044
|
+
layout: panelledEditAttributes,
|
1045
|
+
components: componentEditAttributes,
|
1046
|
+
metadatas: editMetadatas,
|
1047
|
+
settings: {
|
1048
|
+
...data.contentType.settings,
|
1049
|
+
displayName: schema?.info.displayName
|
1050
|
+
},
|
1051
|
+
options: {
|
1052
|
+
...schema?.options,
|
1053
|
+
...schema?.pluginOptions,
|
1054
|
+
...data.contentType.options
|
1055
|
+
}
|
1056
|
+
};
|
1057
|
+
};
|
1058
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1059
|
+
return rows.map(
|
1060
|
+
(row) => row.map((field) => {
|
1061
|
+
const attribute = attributes[field.name];
|
1062
|
+
if (!attribute) {
|
1063
|
+
return null;
|
1064
|
+
}
|
1065
|
+
const { edit: metadata } = metadatas[field.name];
|
1066
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1067
|
+
return {
|
1068
|
+
attribute,
|
1069
|
+
disabled: !metadata.editable,
|
1070
|
+
hint: metadata.description,
|
1071
|
+
label: metadata.label ?? "",
|
1072
|
+
name: field.name,
|
1073
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1074
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1075
|
+
schemas,
|
1076
|
+
components: components?.schemas ?? {}
|
1077
|
+
}),
|
1078
|
+
placeholder: metadata.placeholder ?? "",
|
1079
|
+
required: attribute.required ?? false,
|
1080
|
+
size: field.size,
|
1081
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1082
|
+
visible: metadata.visible ?? true,
|
1083
|
+
type: attribute.type
|
1084
|
+
};
|
1085
|
+
}).filter((field) => field !== null)
|
1086
|
+
);
|
1087
|
+
};
|
1088
|
+
const formatListLayout = (data, {
|
1089
|
+
schemas,
|
1090
|
+
schema,
|
1091
|
+
components
|
1092
|
+
}) => {
|
1093
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1094
|
+
(acc, [attribute, metadata]) => {
|
1095
|
+
return {
|
1096
|
+
...acc,
|
1097
|
+
[attribute]: metadata.list
|
1098
|
+
};
|
1099
|
+
},
|
1100
|
+
{}
|
1101
|
+
);
|
1102
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1103
|
+
data.contentType.layouts.list,
|
1104
|
+
schema?.attributes,
|
1105
|
+
listMetadatas,
|
1106
|
+
{ configurations: data.components, schemas: components },
|
1107
|
+
schemas
|
1108
|
+
);
|
1109
|
+
return {
|
1110
|
+
layout: listAttributes,
|
1111
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1112
|
+
metadatas: listMetadatas,
|
1113
|
+
options: {
|
1114
|
+
...schema?.options,
|
1115
|
+
...schema?.pluginOptions,
|
1116
|
+
...data.contentType.options
|
1117
|
+
}
|
1118
|
+
};
|
1119
|
+
};
|
1120
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1121
|
+
return columns.map((name) => {
|
1122
|
+
const attribute = attributes[name];
|
1123
|
+
if (!attribute) {
|
1124
|
+
return null;
|
1125
|
+
}
|
1126
|
+
const metadata = metadatas[name];
|
1127
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1128
|
+
return {
|
1129
|
+
attribute,
|
1130
|
+
label: metadata.label ?? "",
|
1131
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1132
|
+
schemas,
|
1133
|
+
components: components?.schemas ?? {}
|
1134
|
+
}),
|
1135
|
+
name,
|
1136
|
+
searchable: metadata.searchable ?? true,
|
1137
|
+
sortable: metadata.sortable ?? true
|
1138
|
+
};
|
1139
|
+
}).filter((field) => field !== null);
|
1140
|
+
};
|
1141
|
+
const useDocument = (args, opts) => {
|
1142
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1143
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1144
|
+
const {
|
1145
|
+
currentData: data,
|
1146
|
+
isLoading: isLoadingDocument,
|
1147
|
+
isFetching: isFetchingDocument,
|
1148
|
+
error
|
1149
|
+
} = useGetDocumentQuery(args, {
|
1150
|
+
...opts,
|
1151
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1152
|
+
});
|
1153
|
+
const {
|
1154
|
+
components,
|
1155
|
+
schema,
|
1156
|
+
schemas,
|
1157
|
+
isLoading: isLoadingSchema
|
1158
|
+
} = useContentTypeSchema(args.model);
|
1159
|
+
React__namespace.useEffect(() => {
|
1160
|
+
if (error) {
|
1161
|
+
toggleNotification({
|
1162
|
+
type: "danger",
|
1163
|
+
message: formatAPIError(error)
|
1164
|
+
});
|
1165
|
+
}
|
1166
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1167
|
+
const validationSchema = React__namespace.useMemo(() => {
|
1168
|
+
if (!schema) {
|
1169
|
+
return null;
|
1170
|
+
}
|
1171
|
+
return createYupSchema(schema.attributes, components);
|
1172
|
+
}, [schema, components]);
|
1173
|
+
const validate = React__namespace.useCallback(
|
1174
|
+
(document) => {
|
1175
|
+
if (!validationSchema) {
|
1176
|
+
throw new Error(
|
1177
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1178
|
+
);
|
1179
|
+
}
|
1180
|
+
try {
|
1181
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1182
|
+
return null;
|
1183
|
+
} catch (error2) {
|
1184
|
+
if (error2 instanceof yup.ValidationError) {
|
1185
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
1186
|
+
}
|
1187
|
+
throw error2;
|
1188
|
+
}
|
1189
|
+
},
|
1190
|
+
[validationSchema]
|
1191
|
+
);
|
1192
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1193
|
+
const hasError = !!error;
|
1194
|
+
return {
|
1195
|
+
components,
|
1196
|
+
document: data?.data,
|
1197
|
+
meta: data?.meta,
|
1198
|
+
isLoading,
|
1199
|
+
hasError,
|
1200
|
+
schema,
|
1201
|
+
schemas,
|
1202
|
+
validate
|
831
1203
|
};
|
832
1204
|
};
|
833
1205
|
const useDoc = () => {
|
@@ -840,22 +1212,60 @@ const useDoc = () => {
|
|
840
1212
|
if (!slug) {
|
841
1213
|
throw new Error("Could not find model in url params");
|
842
1214
|
}
|
1215
|
+
const document = useDocument(
|
1216
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1217
|
+
{
|
1218
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1219
|
+
}
|
1220
|
+
);
|
1221
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
843
1222
|
return {
|
844
1223
|
collectionType,
|
845
1224
|
model: slug,
|
846
|
-
id:
|
847
|
-
...
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
1225
|
+
id: returnId,
|
1226
|
+
...document
|
1227
|
+
};
|
1228
|
+
};
|
1229
|
+
const useContentManagerContext = () => {
|
1230
|
+
const {
|
1231
|
+
collectionType,
|
1232
|
+
model,
|
1233
|
+
id,
|
1234
|
+
components,
|
1235
|
+
isLoading: isLoadingDoc,
|
1236
|
+
schema,
|
1237
|
+
schemas
|
1238
|
+
} = useDoc();
|
1239
|
+
const layout = useDocumentLayout(model);
|
1240
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1241
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1242
|
+
const slug = model;
|
1243
|
+
const isCreatingEntry = id === "create";
|
1244
|
+
useContentTypeSchema();
|
1245
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1246
|
+
const error = layout.error;
|
1247
|
+
return {
|
1248
|
+
error,
|
1249
|
+
isLoading,
|
1250
|
+
// Base metadata
|
1251
|
+
model,
|
1252
|
+
collectionType,
|
1253
|
+
id,
|
1254
|
+
slug,
|
1255
|
+
isCreatingEntry,
|
1256
|
+
isSingleType,
|
1257
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1258
|
+
// All schema infos
|
1259
|
+
components,
|
1260
|
+
contentType: schema,
|
1261
|
+
contentTypes: schemas,
|
1262
|
+
// Form state
|
1263
|
+
form,
|
1264
|
+
// layout infos
|
1265
|
+
layout
|
853
1266
|
};
|
854
1267
|
};
|
855
1268
|
const prefixPluginTranslations = (trad, pluginId) => {
|
856
|
-
if (!pluginId) {
|
857
|
-
throw new TypeError("pluginId can't be empty");
|
858
|
-
}
|
859
1269
|
return Object.keys(trad).reduce((acc, current) => {
|
860
1270
|
acc[`${pluginId}.${current}`] = trad[current];
|
861
1271
|
return acc;
|
@@ -871,6 +1281,8 @@ const useDocumentActions = () => {
|
|
871
1281
|
const { formatMessage } = reactIntl.useIntl();
|
872
1282
|
const { trackUsage } = strapiAdmin.useTracking();
|
873
1283
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1284
|
+
const navigate = reactRouterDom.useNavigate();
|
1285
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
874
1286
|
const [deleteDocument] = useDeleteDocumentMutation();
|
875
1287
|
const _delete = React__namespace.useCallback(
|
876
1288
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1185,6 +1597,7 @@ const useDocumentActions = () => {
|
|
1185
1597
|
defaultMessage: "Saved document"
|
1186
1598
|
})
|
1187
1599
|
});
|
1600
|
+
setCurrentStep("contentManager.success");
|
1188
1601
|
return res.data;
|
1189
1602
|
} catch (err) {
|
1190
1603
|
toggleNotification({
|
@@ -1206,7 +1619,6 @@ const useDocumentActions = () => {
|
|
1206
1619
|
sourceId
|
1207
1620
|
});
|
1208
1621
|
if ("error" in res) {
|
1209
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1210
1622
|
return { error: res.error };
|
1211
1623
|
}
|
1212
1624
|
toggleNotification({
|
@@ -1225,7 +1637,7 @@ const useDocumentActions = () => {
|
|
1225
1637
|
throw err;
|
1226
1638
|
}
|
1227
1639
|
},
|
1228
|
-
[autoCloneDocument,
|
1640
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1229
1641
|
);
|
1230
1642
|
const [cloneDocument] = useCloneDocumentMutation();
|
1231
1643
|
const clone = React__namespace.useCallback(
|
@@ -1251,6 +1663,7 @@ const useDocumentActions = () => {
|
|
1251
1663
|
defaultMessage: "Cloned document"
|
1252
1664
|
})
|
1253
1665
|
});
|
1666
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1254
1667
|
return res.data;
|
1255
1668
|
} catch (err) {
|
1256
1669
|
toggleNotification({
|
@@ -1261,7 +1674,7 @@ const useDocumentActions = () => {
|
|
1261
1674
|
throw err;
|
1262
1675
|
}
|
1263
1676
|
},
|
1264
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1677
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1265
1678
|
);
|
1266
1679
|
const [getDoc] = useLazyGetDocumentQuery();
|
1267
1680
|
const getDocument = React__namespace.useCallback(
|
@@ -1286,10 +1699,10 @@ const useDocumentActions = () => {
|
|
1286
1699
|
update
|
1287
1700
|
};
|
1288
1701
|
};
|
1289
|
-
const ProtectedHistoryPage =
|
1290
|
-
() => Promise.resolve().then(() => require("./History-
|
1702
|
+
const ProtectedHistoryPage = React__namespace.lazy(
|
1703
|
+
() => Promise.resolve().then(() => require("./History-CeCDhoJG.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1291
1704
|
);
|
1292
|
-
const routes$
|
1705
|
+
const routes$2 = [
|
1293
1706
|
{
|
1294
1707
|
path: ":collectionType/:slug/:id/history",
|
1295
1708
|
Component: ProtectedHistoryPage
|
@@ -1299,32 +1712,45 @@ const routes$1 = [
|
|
1299
1712
|
Component: ProtectedHistoryPage
|
1300
1713
|
}
|
1301
1714
|
];
|
1715
|
+
const ProtectedPreviewPage = React__namespace.lazy(
|
1716
|
+
() => Promise.resolve().then(() => require("./Preview-CT28Ckpg.js")).then((mod) => ({ default: mod.ProtectedPreviewPage }))
|
1717
|
+
);
|
1718
|
+
const routes$1 = [
|
1719
|
+
{
|
1720
|
+
path: ":collectionType/:slug/:id/preview",
|
1721
|
+
Component: ProtectedPreviewPage
|
1722
|
+
},
|
1723
|
+
{
|
1724
|
+
path: ":collectionType/:slug/preview",
|
1725
|
+
Component: ProtectedPreviewPage
|
1726
|
+
}
|
1727
|
+
];
|
1302
1728
|
const ProtectedEditViewPage = React.lazy(
|
1303
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1729
|
+
() => Promise.resolve().then(() => require("./EditViewPage-BwisF04Q.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1304
1730
|
);
|
1305
1731
|
const ProtectedListViewPage = React.lazy(
|
1306
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1732
|
+
() => Promise.resolve().then(() => require("./ListViewPage-BKTZFhsM.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1307
1733
|
);
|
1308
1734
|
const ProtectedListConfiguration = React.lazy(
|
1309
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1735
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-C-bAd44a.js")).then((mod) => ({
|
1310
1736
|
default: mod.ProtectedListConfiguration
|
1311
1737
|
}))
|
1312
1738
|
);
|
1313
1739
|
const ProtectedEditConfigurationPage = React.lazy(
|
1314
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1740
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-D2rtvneE.js")).then((mod) => ({
|
1315
1741
|
default: mod.ProtectedEditConfigurationPage
|
1316
1742
|
}))
|
1317
1743
|
);
|
1318
1744
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1319
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1745
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-BSEZcJVB.js")).then((mod) => ({
|
1320
1746
|
default: mod.ProtectedComponentConfigurationPage
|
1321
1747
|
}))
|
1322
1748
|
);
|
1323
1749
|
const NoPermissions = React.lazy(
|
1324
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1750
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-CChGWBj5.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1325
1751
|
);
|
1326
1752
|
const NoContentType = React.lazy(
|
1327
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1753
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-D3Cm3v3q.js")).then((mod) => ({ default: mod.NoContentType }))
|
1328
1754
|
);
|
1329
1755
|
const CollectionTypePages = () => {
|
1330
1756
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1336,7 +1762,7 @@ const CollectionTypePages = () => {
|
|
1336
1762
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1337
1763
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1338
1764
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1339
|
-
const LIST_PATH = `/content-manager
|
1765
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1340
1766
|
const routes = [
|
1341
1767
|
{
|
1342
1768
|
path: LIST_RELATIVE_PATH,
|
@@ -1370,6 +1796,7 @@ const routes = [
|
|
1370
1796
|
path: "no-content-types",
|
1371
1797
|
Component: NoContentType
|
1372
1798
|
},
|
1799
|
+
...routes$2,
|
1373
1800
|
...routes$1
|
1374
1801
|
];
|
1375
1802
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1438,12 +1865,14 @@ const DocumentActionButton = (action) => {
|
|
1438
1865
|
/* @__PURE__ */ jsxRuntime.jsx(
|
1439
1866
|
designSystem.Button,
|
1440
1867
|
{
|
1441
|
-
flex:
|
1868
|
+
flex: "auto",
|
1442
1869
|
startIcon: action.icon,
|
1443
1870
|
disabled: action.disabled,
|
1444
1871
|
onClick: handleClick(action),
|
1445
1872
|
justifyContent: "center",
|
1446
1873
|
variant: action.variant || "default",
|
1874
|
+
paddingTop: "7px",
|
1875
|
+
paddingBottom: "7px",
|
1447
1876
|
children: action.label
|
1448
1877
|
}
|
1449
1878
|
),
|
@@ -1451,7 +1880,7 @@ const DocumentActionButton = (action) => {
|
|
1451
1880
|
DocumentActionConfirmDialog,
|
1452
1881
|
{
|
1453
1882
|
...action.dialog,
|
1454
|
-
variant: action.variant,
|
1883
|
+
variant: action.dialog?.variant ?? action.variant,
|
1455
1884
|
isOpen: dialogId === action.id,
|
1456
1885
|
onClose: handleClose
|
1457
1886
|
}
|
@@ -1466,6 +1895,11 @@ const DocumentActionButton = (action) => {
|
|
1466
1895
|
) : null
|
1467
1896
|
] });
|
1468
1897
|
};
|
1898
|
+
const MenuItem = styledComponents.styled(designSystem.Menu.Item)`
|
1899
|
+
&:hover {
|
1900
|
+
background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
|
1901
|
+
}
|
1902
|
+
`;
|
1469
1903
|
const DocumentActionsMenu = ({
|
1470
1904
|
actions: actions2,
|
1471
1905
|
children,
|
@@ -1508,9 +1942,9 @@ const DocumentActionsMenu = ({
|
|
1508
1942
|
disabled: isDisabled,
|
1509
1943
|
size: "S",
|
1510
1944
|
endIcon: null,
|
1511
|
-
paddingTop: "
|
1512
|
-
paddingLeft: "
|
1513
|
-
paddingRight: "
|
1945
|
+
paddingTop: "4px",
|
1946
|
+
paddingLeft: "7px",
|
1947
|
+
paddingRight: "7px",
|
1514
1948
|
variant,
|
1515
1949
|
children: [
|
1516
1950
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
@@ -1521,36 +1955,35 @@ const DocumentActionsMenu = ({
|
|
1521
1955
|
]
|
1522
1956
|
}
|
1523
1957
|
),
|
1524
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, {
|
1958
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1525
1959
|
actions2.map((action) => {
|
1526
1960
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
1527
|
-
|
1961
|
+
MenuItem,
|
1528
1962
|
{
|
1529
1963
|
disabled: action.disabled,
|
1530
1964
|
onSelect: handleClick(action),
|
1531
1965
|
display: "block",
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
] })
|
1966
|
+
isVariantDanger: action.variant === "danger",
|
1967
|
+
isDisabled: action.disabled,
|
1968
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
1969
|
+
designSystem.Flex,
|
1970
|
+
{
|
1971
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1972
|
+
gap: 2,
|
1973
|
+
tag: "span",
|
1974
|
+
children: [
|
1975
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1976
|
+
designSystem.Flex,
|
1977
|
+
{
|
1978
|
+
tag: "span",
|
1979
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1980
|
+
children: action.icon
|
1981
|
+
}
|
1982
|
+
),
|
1983
|
+
action.label
|
1984
|
+
]
|
1985
|
+
}
|
1986
|
+
) })
|
1554
1987
|
},
|
1555
1988
|
action.id
|
1556
1989
|
);
|
@@ -1630,11 +2063,11 @@ const DocumentActionConfirmDialog = ({
|
|
1630
2063
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
1631
2064
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
1632
2065
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
1633
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
|
2066
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1634
2067
|
id: "app.components.Button.cancel",
|
1635
2068
|
defaultMessage: "Cancel"
|
1636
2069
|
}) }) }),
|
1637
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2070
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1638
2071
|
id: "app.components.Button.confirm",
|
1639
2072
|
defaultMessage: "Confirm"
|
1640
2073
|
}) })
|
@@ -1661,6 +2094,18 @@ const DocumentActionModal = ({
|
|
1661
2094
|
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
1662
2095
|
] }) });
|
1663
2096
|
};
|
2097
|
+
const transformData = (data) => {
|
2098
|
+
if (Array.isArray(data)) {
|
2099
|
+
return data.map(transformData);
|
2100
|
+
}
|
2101
|
+
if (typeof data === "object" && data !== null) {
|
2102
|
+
if ("apiData" in data) {
|
2103
|
+
return data.apiData;
|
2104
|
+
}
|
2105
|
+
return mapValues__default.default(transformData)(data);
|
2106
|
+
}
|
2107
|
+
return data;
|
2108
|
+
};
|
1664
2109
|
const PublishAction$1 = ({
|
1665
2110
|
activeTab,
|
1666
2111
|
documentId,
|
@@ -1673,13 +2118,18 @@ const PublishAction$1 = ({
|
|
1673
2118
|
const navigate = reactRouterDom.useNavigate();
|
1674
2119
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1675
2120
|
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2121
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
1676
2122
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2123
|
+
const { id } = reactRouterDom.useParams();
|
1677
2124
|
const { formatMessage } = reactIntl.useIntl();
|
1678
|
-
const { canPublish
|
1679
|
-
"PublishAction",
|
1680
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1681
|
-
);
|
2125
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1682
2126
|
const { publish } = useDocumentActions();
|
2127
|
+
const [
|
2128
|
+
countDraftRelations,
|
2129
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2130
|
+
] = useLazyGetDraftRelationCountQuery();
|
2131
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
2132
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1683
2133
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1684
2134
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1685
2135
|
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1688,10 +2138,107 @@ const PublishAction$1 = ({
|
|
1688
2138
|
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1689
2139
|
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1690
2140
|
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
2141
|
+
React__namespace.useEffect(() => {
|
2142
|
+
if (isErrorDraftRelations) {
|
2143
|
+
toggleNotification({
|
2144
|
+
type: "danger",
|
2145
|
+
message: formatMessage({
|
2146
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2147
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2148
|
+
})
|
2149
|
+
});
|
2150
|
+
}
|
2151
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2152
|
+
React__namespace.useEffect(() => {
|
2153
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2154
|
+
const extractDraftRelations = (data) => {
|
2155
|
+
const relations = data.connect || [];
|
2156
|
+
relations.forEach((relation) => {
|
2157
|
+
if (relation.status === "draft") {
|
2158
|
+
localDraftRelations.add(relation.id);
|
2159
|
+
}
|
2160
|
+
});
|
2161
|
+
};
|
2162
|
+
const traverseAndExtract = (data) => {
|
2163
|
+
Object.entries(data).forEach(([key, value]) => {
|
2164
|
+
if (key === "connect" && Array.isArray(value)) {
|
2165
|
+
extractDraftRelations({ connect: value });
|
2166
|
+
} else if (typeof value === "object" && value !== null) {
|
2167
|
+
traverseAndExtract(value);
|
2168
|
+
}
|
2169
|
+
});
|
2170
|
+
};
|
2171
|
+
if (!documentId || modified) {
|
2172
|
+
traverseAndExtract(formValues);
|
2173
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2174
|
+
}
|
2175
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2176
|
+
React__namespace.useEffect(() => {
|
2177
|
+
if (!document || !document.documentId || isListView) {
|
2178
|
+
return;
|
2179
|
+
}
|
2180
|
+
const fetchDraftRelationsCount = async () => {
|
2181
|
+
const { data, error } = await countDraftRelations({
|
2182
|
+
collectionType,
|
2183
|
+
model,
|
2184
|
+
documentId,
|
2185
|
+
params
|
2186
|
+
});
|
2187
|
+
if (error) {
|
2188
|
+
throw error;
|
2189
|
+
}
|
2190
|
+
if (data) {
|
2191
|
+
setServerCountOfDraftRelations(data.data);
|
2192
|
+
}
|
2193
|
+
};
|
2194
|
+
fetchDraftRelationsCount();
|
2195
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2196
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
2197
|
+
if (!schema?.options?.draftAndPublish) {
|
2198
|
+
return null;
|
2199
|
+
}
|
2200
|
+
const performPublish = async () => {
|
2201
|
+
setSubmitting(true);
|
2202
|
+
try {
|
2203
|
+
const { errors } = await validate(true, {
|
2204
|
+
status: "published"
|
2205
|
+
});
|
2206
|
+
if (errors) {
|
2207
|
+
toggleNotification({
|
2208
|
+
type: "danger",
|
2209
|
+
message: formatMessage({
|
2210
|
+
id: "content-manager.validation.error",
|
2211
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2212
|
+
})
|
2213
|
+
});
|
2214
|
+
return;
|
2215
|
+
}
|
2216
|
+
const res = await publish(
|
2217
|
+
{
|
2218
|
+
collectionType,
|
2219
|
+
model,
|
2220
|
+
documentId,
|
2221
|
+
params
|
2222
|
+
},
|
2223
|
+
transformData(formValues)
|
2224
|
+
);
|
2225
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2226
|
+
if (id === "create") {
|
2227
|
+
navigate({
|
2228
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2229
|
+
search: rawQuery
|
2230
|
+
});
|
2231
|
+
}
|
2232
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2233
|
+
setErrors(formatValidationErrors(res.error));
|
2234
|
+
}
|
2235
|
+
} finally {
|
2236
|
+
setSubmitting(false);
|
2237
|
+
}
|
2238
|
+
};
|
2239
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2240
|
+
const enableDraftRelationsCount = false;
|
2241
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1695
2242
|
return {
|
1696
2243
|
/**
|
1697
2244
|
* Disabled when:
|
@@ -1701,52 +2248,40 @@ const PublishAction$1 = ({
|
|
1701
2248
|
* - the document is already published & not modified
|
1702
2249
|
* - the document is being created & not modified
|
1703
2250
|
* - the user doesn't have the permission to publish
|
1704
|
-
* - the user doesn't have the permission to create a new document
|
1705
|
-
* - the user doesn't have the permission to update the document
|
1706
2251
|
*/
|
1707
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2252
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1708
2253
|
label: formatMessage({
|
1709
2254
|
id: "app.utils.publish",
|
1710
2255
|
defaultMessage: "Publish"
|
1711
2256
|
}),
|
1712
2257
|
onClick: async () => {
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
documentId,
|
1731
|
-
params
|
1732
|
-
},
|
1733
|
-
formValues
|
1734
|
-
);
|
1735
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1736
|
-
navigate({
|
1737
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1738
|
-
search: rawQuery
|
1739
|
-
});
|
1740
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1741
|
-
setErrors(formatValidationErrors(res.error));
|
2258
|
+
await performPublish();
|
2259
|
+
},
|
2260
|
+
dialog: hasDraftRelations ? {
|
2261
|
+
type: "dialog",
|
2262
|
+
variant: "danger",
|
2263
|
+
footer: null,
|
2264
|
+
title: formatMessage({
|
2265
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2266
|
+
defaultMessage: "Confirmation"
|
2267
|
+
}),
|
2268
|
+
content: formatMessage(
|
2269
|
+
{
|
2270
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2271
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2272
|
+
},
|
2273
|
+
{
|
2274
|
+
count: totalDraftRelations
|
1742
2275
|
}
|
1743
|
-
|
1744
|
-
|
2276
|
+
),
|
2277
|
+
onConfirm: async () => {
|
2278
|
+
await performPublish();
|
1745
2279
|
}
|
1746
|
-
}
|
2280
|
+
} : void 0
|
1747
2281
|
};
|
1748
2282
|
};
|
1749
2283
|
PublishAction$1.type = "publish";
|
2284
|
+
PublishAction$1.position = "panel";
|
1750
2285
|
const UpdateAction = ({
|
1751
2286
|
activeTab,
|
1752
2287
|
documentId,
|
@@ -1759,10 +2294,6 @@ const UpdateAction = ({
|
|
1759
2294
|
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
1760
2295
|
const isCloning = cloneMatch !== null;
|
1761
2296
|
const { formatMessage } = reactIntl.useIntl();
|
1762
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1763
|
-
canCreate: canCreate2,
|
1764
|
-
canUpdate: canUpdate2
|
1765
|
-
}));
|
1766
2297
|
const { create, update, clone } = useDocumentActions();
|
1767
2298
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1768
2299
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
@@ -1773,90 +2304,134 @@ const UpdateAction = ({
|
|
1773
2304
|
const validate = strapiAdmin.useForm("UpdateAction", (state) => state.validate);
|
1774
2305
|
const setErrors = strapiAdmin.useForm("UpdateAction", (state) => state.setErrors);
|
1775
2306
|
const resetForm = strapiAdmin.useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
1776
|
-
|
1777
|
-
|
1778
|
-
|
1779
|
-
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
1797
|
-
|
1798
|
-
|
1799
|
-
|
1800
|
-
|
1801
|
-
}
|
1802
|
-
|
1803
|
-
|
1804
|
-
if (
|
1805
|
-
|
2307
|
+
const handleUpdate = React__namespace.useCallback(async () => {
|
2308
|
+
setSubmitting(true);
|
2309
|
+
try {
|
2310
|
+
if (!modified) {
|
2311
|
+
return;
|
2312
|
+
}
|
2313
|
+
const { errors } = await validate(true, {
|
2314
|
+
status: "draft"
|
2315
|
+
});
|
2316
|
+
if (errors) {
|
2317
|
+
toggleNotification({
|
2318
|
+
type: "danger",
|
2319
|
+
message: formatMessage({
|
2320
|
+
id: "content-manager.validation.error",
|
2321
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2322
|
+
})
|
2323
|
+
});
|
2324
|
+
return;
|
2325
|
+
}
|
2326
|
+
if (isCloning) {
|
2327
|
+
const res = await clone(
|
2328
|
+
{
|
2329
|
+
model,
|
2330
|
+
documentId: cloneMatch.params.origin,
|
2331
|
+
params
|
2332
|
+
},
|
2333
|
+
transformData(document)
|
2334
|
+
);
|
2335
|
+
if ("data" in res) {
|
2336
|
+
navigate(
|
1806
2337
|
{
|
1807
|
-
|
1808
|
-
documentId: cloneMatch.params.origin,
|
1809
|
-
params
|
1810
|
-
},
|
1811
|
-
document
|
1812
|
-
);
|
1813
|
-
if ("data" in res) {
|
1814
|
-
navigate({
|
1815
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2338
|
+
pathname: `../${res.data.documentId}`,
|
1816
2339
|
search: rawQuery
|
1817
|
-
});
|
1818
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1819
|
-
setErrors(formatValidationErrors(res.error));
|
1820
|
-
}
|
1821
|
-
} else if (documentId || collectionType === SINGLE_TYPES) {
|
1822
|
-
const res = await update(
|
1823
|
-
{
|
1824
|
-
collectionType,
|
1825
|
-
model,
|
1826
|
-
documentId,
|
1827
|
-
params
|
1828
2340
|
},
|
1829
|
-
|
2341
|
+
{ relative: "path" }
|
1830
2342
|
);
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
2343
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2344
|
+
setErrors(formatValidationErrors(res.error));
|
2345
|
+
}
|
2346
|
+
} else if (documentId || collectionType === SINGLE_TYPES) {
|
2347
|
+
const res = await update(
|
2348
|
+
{
|
2349
|
+
collectionType,
|
2350
|
+
model,
|
2351
|
+
documentId,
|
2352
|
+
params
|
2353
|
+
},
|
2354
|
+
transformData(document)
|
2355
|
+
);
|
2356
|
+
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2357
|
+
setErrors(formatValidationErrors(res.error));
|
1836
2358
|
} else {
|
1837
|
-
|
2359
|
+
resetForm();
|
2360
|
+
}
|
2361
|
+
} else {
|
2362
|
+
const res = await create(
|
2363
|
+
{
|
2364
|
+
model,
|
2365
|
+
params
|
2366
|
+
},
|
2367
|
+
transformData(document)
|
2368
|
+
);
|
2369
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2370
|
+
navigate(
|
1838
2371
|
{
|
1839
|
-
|
1840
|
-
|
2372
|
+
pathname: `../${res.data.documentId}`,
|
2373
|
+
search: rawQuery
|
1841
2374
|
},
|
1842
|
-
|
2375
|
+
{ replace: true, relative: "path" }
|
1843
2376
|
);
|
1844
|
-
|
1845
|
-
|
1846
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1847
|
-
search: rawQuery
|
1848
|
-
});
|
1849
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1850
|
-
setErrors(formatValidationErrors(res.error));
|
1851
|
-
}
|
2377
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2378
|
+
setErrors(formatValidationErrors(res.error));
|
1852
2379
|
}
|
1853
|
-
} finally {
|
1854
|
-
setSubmitting(false);
|
1855
2380
|
}
|
2381
|
+
} finally {
|
2382
|
+
setSubmitting(false);
|
1856
2383
|
}
|
2384
|
+
}, [
|
2385
|
+
clone,
|
2386
|
+
cloneMatch?.params.origin,
|
2387
|
+
collectionType,
|
2388
|
+
create,
|
2389
|
+
document,
|
2390
|
+
documentId,
|
2391
|
+
formatMessage,
|
2392
|
+
formatValidationErrors,
|
2393
|
+
isCloning,
|
2394
|
+
model,
|
2395
|
+
modified,
|
2396
|
+
navigate,
|
2397
|
+
params,
|
2398
|
+
rawQuery,
|
2399
|
+
resetForm,
|
2400
|
+
setErrors,
|
2401
|
+
setSubmitting,
|
2402
|
+
toggleNotification,
|
2403
|
+
update,
|
2404
|
+
validate
|
2405
|
+
]);
|
2406
|
+
React__namespace.useEffect(() => {
|
2407
|
+
const handleKeyDown = (e) => {
|
2408
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
2409
|
+
e.preventDefault();
|
2410
|
+
handleUpdate();
|
2411
|
+
}
|
2412
|
+
};
|
2413
|
+
window.addEventListener("keydown", handleKeyDown);
|
2414
|
+
return () => {
|
2415
|
+
window.removeEventListener("keydown", handleKeyDown);
|
2416
|
+
};
|
2417
|
+
}, [handleUpdate]);
|
2418
|
+
return {
|
2419
|
+
/**
|
2420
|
+
* Disabled when:
|
2421
|
+
* - the form is submitting
|
2422
|
+
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
2423
|
+
* - the active tab is the published tab
|
2424
|
+
*/
|
2425
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
2426
|
+
label: formatMessage({
|
2427
|
+
id: "global.save",
|
2428
|
+
defaultMessage: "Save"
|
2429
|
+
}),
|
2430
|
+
onClick: handleUpdate
|
1857
2431
|
};
|
1858
2432
|
};
|
1859
2433
|
UpdateAction.type = "update";
|
2434
|
+
UpdateAction.position = "panel";
|
1860
2435
|
const UNPUBLISH_DRAFT_OPTIONS = {
|
1861
2436
|
KEEP: "keep",
|
1862
2437
|
DISCARD: "discard"
|
@@ -1889,7 +2464,7 @@ const UnpublishAction$1 = ({
|
|
1889
2464
|
id: "app.utils.unpublish",
|
1890
2465
|
defaultMessage: "Unpublish"
|
1891
2466
|
}),
|
1892
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2467
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1893
2468
|
onClick: async () => {
|
1894
2469
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1895
2470
|
if (!documentId) {
|
@@ -1979,6 +2554,7 @@ const UnpublishAction$1 = ({
|
|
1979
2554
|
};
|
1980
2555
|
};
|
1981
2556
|
UnpublishAction$1.type = "unpublish";
|
2557
|
+
UnpublishAction$1.position = "panel";
|
1982
2558
|
const DiscardAction = ({
|
1983
2559
|
activeTab,
|
1984
2560
|
documentId,
|
@@ -2001,7 +2577,7 @@ const DiscardAction = ({
|
|
2001
2577
|
id: "content-manager.actions.discard.label",
|
2002
2578
|
defaultMessage: "Discard changes"
|
2003
2579
|
}),
|
2004
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2580
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2005
2581
|
position: ["panel", "table-row"],
|
2006
2582
|
variant: "danger",
|
2007
2583
|
dialog: {
|
@@ -2029,11 +2605,7 @@ const DiscardAction = ({
|
|
2029
2605
|
};
|
2030
2606
|
};
|
2031
2607
|
DiscardAction.type = "discard";
|
2032
|
-
|
2033
|
-
path {
|
2034
|
-
fill: currentColor;
|
2035
|
-
}
|
2036
|
-
`;
|
2608
|
+
DiscardAction.position = "panel";
|
2037
2609
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2038
2610
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2039
2611
|
const RelativeTime = React__namespace.forwardRef(
|
@@ -2046,7 +2618,7 @@ const RelativeTime = React__namespace.forwardRef(
|
|
2046
2618
|
});
|
2047
2619
|
const unit = intervals.find((intervalUnit) => {
|
2048
2620
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2049
|
-
});
|
2621
|
+
}) ?? "seconds";
|
2050
2622
|
const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
|
2051
2623
|
const customInterval = customIntervals.find(
|
2052
2624
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2080,34 +2652,34 @@ const getDisplayName = ({
|
|
2080
2652
|
return email ?? "";
|
2081
2653
|
};
|
2082
2654
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2083
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2084
|
-
const statusVariant = status === "draft" ? "
|
2085
|
-
|
2655
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2656
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2657
|
+
const { formatMessage } = reactIntl.useIntl();
|
2658
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2659
|
+
id: `content-manager.containers.List.${status}`,
|
2660
|
+
defaultMessage: capitalise(status)
|
2661
|
+
}) }) });
|
2086
2662
|
};
|
2087
2663
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2088
2664
|
const { formatMessage } = reactIntl.useIntl();
|
2089
2665
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2666
|
+
const params = reactRouterDom.useParams();
|
2090
2667
|
const title = isCreating ? formatMessage({
|
2091
2668
|
id: "content-manager.containers.edit.title.new",
|
2092
2669
|
defaultMessage: "Create an entry"
|
2093
2670
|
}) : documentTitle;
|
2094
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2095
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2096
|
-
|
2097
|
-
designSystem.Flex,
|
2671
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2672
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2673
|
+
strapiAdmin.BackButton,
|
2098
2674
|
{
|
2099
|
-
|
2100
|
-
justifyContent: "space-between",
|
2101
|
-
paddingTop: 1,
|
2102
|
-
gap: "80px",
|
2103
|
-
alignItems: "flex-start",
|
2104
|
-
children: [
|
2105
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2106
|
-
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2107
|
-
]
|
2675
|
+
fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
|
2108
2676
|
}
|
2109
2677
|
),
|
2110
|
-
|
2678
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2679
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2680
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2681
|
+
] }),
|
2682
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2111
2683
|
] });
|
2112
2684
|
};
|
2113
2685
|
const HeaderToolbar = () => {
|
@@ -2153,7 +2725,7 @@ const HeaderToolbar = () => {
|
|
2153
2725
|
meta: isCloning ? void 0 : meta,
|
2154
2726
|
collectionType
|
2155
2727
|
},
|
2156
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2728
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
|
2157
2729
|
children: (actions2) => {
|
2158
2730
|
const headerActions = actions2.filter((action) => {
|
2159
2731
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -2190,12 +2762,12 @@ const Information = ({ activeTab }) => {
|
|
2190
2762
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2191
2763
|
label: formatMessage({
|
2192
2764
|
id: "content-manager.containers.edit.information.last-published.label",
|
2193
|
-
defaultMessage: "
|
2765
|
+
defaultMessage: "Published"
|
2194
2766
|
}),
|
2195
2767
|
value: formatMessage(
|
2196
2768
|
{
|
2197
2769
|
id: "content-manager.containers.edit.information.last-published.value",
|
2198
|
-
defaultMessage: `
|
2770
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2199
2771
|
},
|
2200
2772
|
{
|
2201
2773
|
time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2208,12 +2780,12 @@ const Information = ({ activeTab }) => {
|
|
2208
2780
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2209
2781
|
label: formatMessage({
|
2210
2782
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2211
|
-
defaultMessage: "
|
2783
|
+
defaultMessage: "Updated"
|
2212
2784
|
}),
|
2213
2785
|
value: formatMessage(
|
2214
2786
|
{
|
2215
2787
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2216
|
-
defaultMessage: `
|
2788
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2217
2789
|
},
|
2218
2790
|
{
|
2219
2791
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2231,12 +2803,12 @@ const Information = ({ activeTab }) => {
|
|
2231
2803
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2232
2804
|
label: formatMessage({
|
2233
2805
|
id: "content-manager.containers.edit.information.document.label",
|
2234
|
-
defaultMessage: "
|
2806
|
+
defaultMessage: "Created"
|
2235
2807
|
}),
|
2236
2808
|
value: formatMessage(
|
2237
2809
|
{
|
2238
2810
|
id: "content-manager.containers.edit.information.document.value",
|
2239
|
-
defaultMessage: `
|
2811
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2240
2812
|
},
|
2241
2813
|
{
|
2242
2814
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2274,25 +2846,77 @@ const Information = ({ activeTab }) => {
|
|
2274
2846
|
);
|
2275
2847
|
};
|
2276
2848
|
const HeaderActions = ({ actions: actions2 }) => {
|
2277
|
-
|
2278
|
-
|
2849
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2850
|
+
const handleClick = (action) => async (e) => {
|
2851
|
+
if (!("options" in action)) {
|
2852
|
+
const { onClick = () => false, dialog, id } = action;
|
2853
|
+
const muteDialog = await onClick(e);
|
2854
|
+
if (dialog && !muteDialog) {
|
2855
|
+
e.preventDefault();
|
2856
|
+
setDialogId(id);
|
2857
|
+
}
|
2858
|
+
}
|
2859
|
+
};
|
2860
|
+
const handleClose = () => {
|
2861
|
+
setDialogId(null);
|
2862
|
+
};
|
2863
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2864
|
+
if (action.options) {
|
2279
2865
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
2280
2866
|
designSystem.SingleSelect,
|
2281
2867
|
{
|
2282
2868
|
size: "S",
|
2283
|
-
disabled: action.disabled,
|
2284
|
-
"aria-label": action.label,
|
2285
2869
|
onChange: action.onSelect,
|
2286
|
-
|
2870
|
+
"aria-label": action.label,
|
2871
|
+
...action,
|
2287
2872
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2288
2873
|
},
|
2289
2874
|
action.id
|
2290
2875
|
);
|
2291
2876
|
} else {
|
2292
|
-
|
2877
|
+
if (action.type === "icon") {
|
2878
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2879
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2880
|
+
designSystem.IconButton,
|
2881
|
+
{
|
2882
|
+
disabled: action.disabled,
|
2883
|
+
label: action.label,
|
2884
|
+
size: "S",
|
2885
|
+
onClick: handleClick(action),
|
2886
|
+
children: action.icon
|
2887
|
+
}
|
2888
|
+
),
|
2889
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2890
|
+
HeaderActionDialog,
|
2891
|
+
{
|
2892
|
+
...action.dialog,
|
2893
|
+
isOpen: dialogId === action.id,
|
2894
|
+
onClose: handleClose
|
2895
|
+
}
|
2896
|
+
) : null
|
2897
|
+
] }, action.id);
|
2898
|
+
}
|
2293
2899
|
}
|
2294
2900
|
}) });
|
2295
2901
|
};
|
2902
|
+
const HeaderActionDialog = ({
|
2903
|
+
onClose,
|
2904
|
+
onCancel,
|
2905
|
+
title,
|
2906
|
+
content: Content,
|
2907
|
+
isOpen
|
2908
|
+
}) => {
|
2909
|
+
const handleClose = async () => {
|
2910
|
+
if (onCancel) {
|
2911
|
+
await onCancel();
|
2912
|
+
}
|
2913
|
+
onClose();
|
2914
|
+
};
|
2915
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2916
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2917
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2918
|
+
] }) });
|
2919
|
+
};
|
2296
2920
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2297
2921
|
const navigate = reactRouterDom.useNavigate();
|
2298
2922
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2309,6 +2933,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2309
2933
|
};
|
2310
2934
|
};
|
2311
2935
|
ConfigureTheViewAction.type = "configure-the-view";
|
2936
|
+
ConfigureTheViewAction.position = "header";
|
2312
2937
|
const EditTheModelAction = ({ model }) => {
|
2313
2938
|
const navigate = reactRouterDom.useNavigate();
|
2314
2939
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2325,6 +2950,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2325
2950
|
};
|
2326
2951
|
};
|
2327
2952
|
EditTheModelAction.type = "edit-the-model";
|
2953
|
+
EditTheModelAction.position = "header";
|
2328
2954
|
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2329
2955
|
const navigate = reactRouterDom.useNavigate();
|
2330
2956
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2333,12 +2959,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2333
2959
|
const { delete: deleteAction } = useDocumentActions();
|
2334
2960
|
const { toggleNotification } = strapiAdmin.useNotification();
|
2335
2961
|
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2962
|
+
const isLocalized = document?.locale != null;
|
2336
2963
|
return {
|
2337
2964
|
disabled: !canDelete || !document,
|
2338
|
-
label: formatMessage(
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2965
|
+
label: formatMessage(
|
2966
|
+
{
|
2967
|
+
id: "content-manager.actions.delete.label",
|
2968
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2969
|
+
},
|
2970
|
+
{ isLocalized }
|
2971
|
+
),
|
2342
2972
|
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2343
2973
|
dialog: {
|
2344
2974
|
type: "dialog",
|
@@ -2394,403 +3024,102 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2394
3024
|
};
|
2395
3025
|
};
|
2396
3026
|
DeleteAction$1.type = "delete";
|
3027
|
+
DeleteAction$1.position = ["header", "table-row"];
|
2397
3028
|
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2398
3029
|
const Panels = () => {
|
2399
3030
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2400
3031
|
const [
|
2401
3032
|
{
|
2402
|
-
query: { status }
|
2403
|
-
}
|
2404
|
-
] = strapiAdmin.useQueryParams({
|
2405
|
-
status: "draft"
|
2406
|
-
});
|
2407
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2408
|
-
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2409
|
-
const props = {
|
2410
|
-
activeTab: status,
|
2411
|
-
model,
|
2412
|
-
documentId: id,
|
2413
|
-
document: isCloning ? void 0 : document,
|
2414
|
-
meta: isCloning ? void 0 : meta,
|
2415
|
-
collectionType
|
2416
|
-
};
|
2417
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2418
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2419
|
-
{
|
2420
|
-
props,
|
2421
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2422
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2423
|
-
}
|
2424
|
-
) });
|
2425
|
-
};
|
2426
|
-
const ActionsPanel = () => {
|
2427
|
-
const { formatMessage } = reactIntl.useIntl();
|
2428
|
-
return {
|
2429
|
-
title: formatMessage({
|
2430
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2431
|
-
defaultMessage: "Document"
|
2432
|
-
}),
|
2433
|
-
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2434
|
-
};
|
2435
|
-
};
|
2436
|
-
ActionsPanel.type = "actions";
|
2437
|
-
const ActionsPanelContent = () => {
|
2438
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2439
|
-
const [
|
2440
|
-
{
|
2441
|
-
query: { status = "draft" }
|
2442
|
-
}
|
2443
|
-
] = strapiAdmin.useQueryParams();
|
2444
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2445
|
-
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2446
|
-
const props = {
|
2447
|
-
activeTab: status,
|
2448
|
-
model,
|
2449
|
-
documentId: id,
|
2450
|
-
document: isCloning ? void 0 : document,
|
2451
|
-
meta: isCloning ? void 0 : meta,
|
2452
|
-
collectionType
|
2453
|
-
};
|
2454
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2455
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2456
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2457
|
-
{
|
2458
|
-
props,
|
2459
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2460
|
-
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
2461
|
-
}
|
2462
|
-
),
|
2463
|
-
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2464
|
-
] });
|
2465
|
-
};
|
2466
|
-
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
2467
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
2468
|
-
designSystem.Flex,
|
2469
|
-
{
|
2470
|
-
ref,
|
2471
|
-
tag: "aside",
|
2472
|
-
"aria-labelledby": "additional-information",
|
2473
|
-
background: "neutral0",
|
2474
|
-
borderColor: "neutral150",
|
2475
|
-
hasRadius: true,
|
2476
|
-
paddingBottom: 4,
|
2477
|
-
paddingLeft: 4,
|
2478
|
-
paddingRight: 4,
|
2479
|
-
paddingTop: 4,
|
2480
|
-
shadow: "tableShadow",
|
2481
|
-
gap: 3,
|
2482
|
-
direction: "column",
|
2483
|
-
justifyContent: "stretch",
|
2484
|
-
alignItems: "flex-start",
|
2485
|
-
children: [
|
2486
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2487
|
-
children
|
2488
|
-
]
|
2489
|
-
}
|
2490
|
-
);
|
2491
|
-
});
|
2492
|
-
const HOOKS = {
|
2493
|
-
/**
|
2494
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2495
|
-
* @constant
|
2496
|
-
* @type {string}
|
2497
|
-
*/
|
2498
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2499
|
-
/**
|
2500
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2501
|
-
* @constant
|
2502
|
-
* @type {string}
|
2503
|
-
*/
|
2504
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2505
|
-
/**
|
2506
|
-
* Hook that allows to mutate the CM's edit view layout
|
2507
|
-
* @constant
|
2508
|
-
* @type {string}
|
2509
|
-
*/
|
2510
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2511
|
-
/**
|
2512
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2513
|
-
* @constant
|
2514
|
-
* @type {string}
|
2515
|
-
*/
|
2516
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2517
|
-
};
|
2518
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2519
|
-
endpoints: (builder) => ({
|
2520
|
-
getContentTypeConfiguration: builder.query({
|
2521
|
-
query: (uid) => ({
|
2522
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2523
|
-
method: "GET"
|
2524
|
-
}),
|
2525
|
-
transformResponse: (response) => response.data,
|
2526
|
-
providesTags: (_result, _error, uid) => [
|
2527
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2528
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2529
|
-
]
|
2530
|
-
}),
|
2531
|
-
getAllContentTypeSettings: builder.query({
|
2532
|
-
query: () => "/content-manager/content-types-settings",
|
2533
|
-
transformResponse: (response) => response.data,
|
2534
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2535
|
-
}),
|
2536
|
-
updateContentTypeConfiguration: builder.mutation({
|
2537
|
-
query: ({ uid, ...body }) => ({
|
2538
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2539
|
-
method: "PUT",
|
2540
|
-
data: body
|
2541
|
-
}),
|
2542
|
-
transformResponse: (response) => response.data,
|
2543
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2544
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2545
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2546
|
-
// Is this necessary?
|
2547
|
-
{ type: "InitialData" }
|
2548
|
-
]
|
2549
|
-
})
|
2550
|
-
})
|
2551
|
-
});
|
2552
|
-
const {
|
2553
|
-
useGetContentTypeConfigurationQuery,
|
2554
|
-
useGetAllContentTypeSettingsQuery,
|
2555
|
-
useUpdateContentTypeConfigurationMutation
|
2556
|
-
} = contentTypesApi;
|
2557
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2558
|
-
const { type } = attribute;
|
2559
|
-
if (type === "relation") {
|
2560
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2561
|
-
}
|
2562
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2563
|
-
};
|
2564
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2565
|
-
if (!mainFieldName) {
|
2566
|
-
return void 0;
|
2567
|
-
}
|
2568
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2569
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2570
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2571
|
-
);
|
2572
|
-
return {
|
2573
|
-
name: mainFieldName,
|
2574
|
-
type: mainFieldType ?? "string"
|
2575
|
-
};
|
2576
|
-
};
|
2577
|
-
const DEFAULT_SETTINGS = {
|
2578
|
-
bulkable: false,
|
2579
|
-
filterable: false,
|
2580
|
-
searchable: false,
|
2581
|
-
pagination: false,
|
2582
|
-
defaultSortBy: "",
|
2583
|
-
defaultSortOrder: "asc",
|
2584
|
-
mainField: "id",
|
2585
|
-
pageSize: 10
|
2586
|
-
};
|
2587
|
-
const useDocumentLayout = (model) => {
|
2588
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2589
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
2590
|
-
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2591
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
2592
|
-
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
2593
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2594
|
-
const {
|
2595
|
-
data,
|
2596
|
-
isLoading: isLoadingConfigs,
|
2597
|
-
error,
|
2598
|
-
isFetching: isFetchingConfigs
|
2599
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2600
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2601
|
-
React__namespace.useEffect(() => {
|
2602
|
-
if (error) {
|
2603
|
-
toggleNotification({
|
2604
|
-
type: "danger",
|
2605
|
-
message: formatAPIError(error)
|
2606
|
-
});
|
2607
|
-
}
|
2608
|
-
}, [error, formatAPIError, toggleNotification]);
|
2609
|
-
const editLayout = React__namespace.useMemo(
|
2610
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2611
|
-
layout: [],
|
2612
|
-
components: {},
|
2613
|
-
metadatas: {},
|
2614
|
-
options: {},
|
2615
|
-
settings: DEFAULT_SETTINGS
|
2616
|
-
},
|
2617
|
-
[data, isLoading, schemas, schema, components]
|
2618
|
-
);
|
2619
|
-
const listLayout = React__namespace.useMemo(() => {
|
2620
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2621
|
-
layout: [],
|
2622
|
-
metadatas: {},
|
2623
|
-
options: {},
|
2624
|
-
settings: DEFAULT_SETTINGS
|
2625
|
-
};
|
2626
|
-
}, [data, isLoading, schemas, schema, components]);
|
2627
|
-
const { layout: edit } = React__namespace.useMemo(
|
2628
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2629
|
-
layout: editLayout,
|
2630
|
-
query
|
2631
|
-
}),
|
2632
|
-
[editLayout, query, runHookWaterfall]
|
2633
|
-
);
|
2634
|
-
return {
|
2635
|
-
error,
|
2636
|
-
isLoading,
|
2637
|
-
edit,
|
2638
|
-
list: listLayout
|
2639
|
-
};
|
2640
|
-
};
|
2641
|
-
const useDocLayout = () => {
|
2642
|
-
const { model } = useDoc();
|
2643
|
-
return useDocumentLayout(model);
|
2644
|
-
};
|
2645
|
-
const formatEditLayout = (data, {
|
2646
|
-
schemas,
|
2647
|
-
schema,
|
2648
|
-
components
|
2649
|
-
}) => {
|
2650
|
-
let currentPanelIndex = 0;
|
2651
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2652
|
-
data.contentType.layouts.edit,
|
2653
|
-
schema?.attributes,
|
2654
|
-
data.contentType.metadatas,
|
2655
|
-
{ configurations: data.components, schemas: components },
|
2656
|
-
schemas
|
2657
|
-
).reduce((panels, row) => {
|
2658
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2659
|
-
panels.push([row]);
|
2660
|
-
currentPanelIndex += 2;
|
2661
|
-
} else {
|
2662
|
-
if (!panels[currentPanelIndex]) {
|
2663
|
-
panels.push([]);
|
2664
|
-
}
|
2665
|
-
panels[currentPanelIndex].push(row);
|
2666
|
-
}
|
2667
|
-
return panels;
|
2668
|
-
}, []);
|
2669
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2670
|
-
(acc, [uid, configuration]) => {
|
2671
|
-
acc[uid] = {
|
2672
|
-
layout: convertEditLayoutToFieldLayouts(
|
2673
|
-
configuration.layouts.edit,
|
2674
|
-
components[uid].attributes,
|
2675
|
-
configuration.metadatas
|
2676
|
-
),
|
2677
|
-
settings: {
|
2678
|
-
...configuration.settings,
|
2679
|
-
icon: components[uid].info.icon,
|
2680
|
-
displayName: components[uid].info.displayName
|
2681
|
-
}
|
2682
|
-
};
|
2683
|
-
return acc;
|
2684
|
-
},
|
2685
|
-
{}
|
2686
|
-
);
|
2687
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2688
|
-
(acc, [attribute, metadata]) => {
|
2689
|
-
return {
|
2690
|
-
...acc,
|
2691
|
-
[attribute]: metadata.edit
|
2692
|
-
};
|
2693
|
-
},
|
2694
|
-
{}
|
2695
|
-
);
|
2696
|
-
return {
|
2697
|
-
layout: panelledEditAttributes,
|
2698
|
-
components: componentEditAttributes,
|
2699
|
-
metadatas: editMetadatas,
|
2700
|
-
settings: {
|
2701
|
-
...data.contentType.settings,
|
2702
|
-
displayName: schema?.info.displayName
|
2703
|
-
},
|
2704
|
-
options: {
|
2705
|
-
...schema?.options,
|
2706
|
-
...schema?.pluginOptions,
|
2707
|
-
...data.contentType.options
|
3033
|
+
query: { status }
|
2708
3034
|
}
|
3035
|
+
] = strapiAdmin.useQueryParams({
|
3036
|
+
status: "draft"
|
3037
|
+
});
|
3038
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3039
|
+
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
3040
|
+
const props = {
|
3041
|
+
activeTab: status,
|
3042
|
+
model,
|
3043
|
+
documentId: id,
|
3044
|
+
document: isCloning ? void 0 : document,
|
3045
|
+
meta: isCloning ? void 0 : meta,
|
3046
|
+
collectionType
|
2709
3047
|
};
|
3048
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3049
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3050
|
+
{
|
3051
|
+
props,
|
3052
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
3053
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
3054
|
+
}
|
3055
|
+
) });
|
2710
3056
|
};
|
2711
|
-
const
|
2712
|
-
|
2713
|
-
(row) => row.map((field) => {
|
2714
|
-
const attribute = attributes[field.name];
|
2715
|
-
if (!attribute) {
|
2716
|
-
return null;
|
2717
|
-
}
|
2718
|
-
const { edit: metadata } = metadatas[field.name];
|
2719
|
-
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2720
|
-
return {
|
2721
|
-
attribute,
|
2722
|
-
disabled: !metadata.editable,
|
2723
|
-
hint: metadata.description,
|
2724
|
-
label: metadata.label ?? "",
|
2725
|
-
name: field.name,
|
2726
|
-
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
2727
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2728
|
-
schemas,
|
2729
|
-
components: components?.schemas ?? {}
|
2730
|
-
}),
|
2731
|
-
placeholder: metadata.placeholder ?? "",
|
2732
|
-
required: attribute.required ?? false,
|
2733
|
-
size: field.size,
|
2734
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
2735
|
-
visible: metadata.visible ?? true,
|
2736
|
-
type: attribute.type
|
2737
|
-
};
|
2738
|
-
}).filter((field) => field !== null)
|
2739
|
-
);
|
2740
|
-
};
|
2741
|
-
const formatListLayout = (data, {
|
2742
|
-
schemas,
|
2743
|
-
schema,
|
2744
|
-
components
|
2745
|
-
}) => {
|
2746
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2747
|
-
(acc, [attribute, metadata]) => {
|
2748
|
-
return {
|
2749
|
-
...acc,
|
2750
|
-
[attribute]: metadata.list
|
2751
|
-
};
|
2752
|
-
},
|
2753
|
-
{}
|
2754
|
-
);
|
2755
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2756
|
-
data.contentType.layouts.list,
|
2757
|
-
schema?.attributes,
|
2758
|
-
listMetadatas,
|
2759
|
-
{ configurations: data.components, schemas: components },
|
2760
|
-
schemas
|
2761
|
-
);
|
3057
|
+
const ActionsPanel = () => {
|
3058
|
+
const { formatMessage } = reactIntl.useIntl();
|
2762
3059
|
return {
|
2763
|
-
|
2764
|
-
|
2765
|
-
|
2766
|
-
|
2767
|
-
|
2768
|
-
...schema?.pluginOptions,
|
2769
|
-
...data.contentType.options
|
2770
|
-
}
|
3060
|
+
title: formatMessage({
|
3061
|
+
id: "content-manager.containers.edit.panels.default.title",
|
3062
|
+
defaultMessage: "Entry"
|
3063
|
+
}),
|
3064
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2771
3065
|
};
|
2772
3066
|
};
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
3067
|
+
ActionsPanel.type = "actions";
|
3068
|
+
const ActionsPanelContent = () => {
|
3069
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
3070
|
+
const [
|
3071
|
+
{
|
3072
|
+
query: { status = "draft" }
|
2778
3073
|
}
|
2779
|
-
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
3074
|
+
] = strapiAdmin.useQueryParams();
|
3075
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3076
|
+
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
3077
|
+
const props = {
|
3078
|
+
activeTab: status,
|
3079
|
+
model,
|
3080
|
+
documentId: id,
|
3081
|
+
document: isCloning ? void 0 : document,
|
3082
|
+
meta: isCloning ? void 0 : meta,
|
3083
|
+
collectionType
|
3084
|
+
};
|
3085
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3086
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3087
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3088
|
+
{
|
3089
|
+
props,
|
3090
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
|
3091
|
+
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
3092
|
+
}
|
3093
|
+
),
|
3094
|
+
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3095
|
+
] });
|
2793
3096
|
};
|
3097
|
+
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
3098
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
3099
|
+
designSystem.Flex,
|
3100
|
+
{
|
3101
|
+
ref,
|
3102
|
+
tag: "aside",
|
3103
|
+
"aria-labelledby": "additional-information",
|
3104
|
+
background: "neutral0",
|
3105
|
+
borderColor: "neutral150",
|
3106
|
+
hasRadius: true,
|
3107
|
+
paddingBottom: 4,
|
3108
|
+
paddingLeft: 4,
|
3109
|
+
paddingRight: 4,
|
3110
|
+
paddingTop: 4,
|
3111
|
+
shadow: "tableShadow",
|
3112
|
+
gap: 3,
|
3113
|
+
direction: "column",
|
3114
|
+
justifyContent: "stretch",
|
3115
|
+
alignItems: "flex-start",
|
3116
|
+
children: [
|
3117
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3118
|
+
children
|
3119
|
+
]
|
3120
|
+
}
|
3121
|
+
);
|
3122
|
+
});
|
2794
3123
|
const ConfirmBulkActionDialog = ({
|
2795
3124
|
onToggleDialog,
|
2796
3125
|
isOpen = false,
|
@@ -2798,7 +3127,7 @@ const ConfirmBulkActionDialog = ({
|
|
2798
3127
|
endAction
|
2799
3128
|
}) => {
|
2800
3129
|
const { formatMessage } = reactIntl.useIntl();
|
2801
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, {
|
3130
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2802
3131
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
|
2803
3132
|
id: "app.components.ConfirmDialog.title",
|
2804
3133
|
defaultMessage: "Confirmation"
|
@@ -2829,6 +3158,7 @@ const ConfirmDialogPublishAll = ({
|
|
2829
3158
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
2830
3159
|
const { model, schema } = useDoc();
|
2831
3160
|
const [{ query }] = strapiAdmin.useQueryParams();
|
3161
|
+
const enableDraftRelationsCount = false;
|
2832
3162
|
const {
|
2833
3163
|
data: countDraftRelations = 0,
|
2834
3164
|
isLoading,
|
@@ -2840,7 +3170,7 @@ const ConfirmDialogPublishAll = ({
|
|
2840
3170
|
locale: query?.plugins?.i18n?.locale
|
2841
3171
|
},
|
2842
3172
|
{
|
2843
|
-
skip:
|
3173
|
+
skip: !enableDraftRelationsCount
|
2844
3174
|
}
|
2845
3175
|
);
|
2846
3176
|
React__namespace.useEffect(() => {
|
@@ -2919,7 +3249,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
|
2919
3249
|
)
|
2920
3250
|
);
|
2921
3251
|
} else {
|
2922
|
-
messages.push(
|
3252
|
+
messages.push(
|
3253
|
+
...formatErrorMessages(
|
3254
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3255
|
+
value,
|
3256
|
+
currentKey,
|
3257
|
+
formatMessage
|
3258
|
+
)
|
3259
|
+
);
|
2923
3260
|
}
|
2924
3261
|
} else {
|
2925
3262
|
messages.push(
|
@@ -3018,7 +3355,7 @@ const SelectedEntriesTableContent = ({
|
|
3018
3355
|
status: row.status
|
3019
3356
|
}
|
3020
3357
|
) }),
|
3021
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3358
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3022
3359
|
designSystem.IconButton,
|
3023
3360
|
{
|
3024
3361
|
tag: reactRouterDom.Link,
|
@@ -3027,23 +3364,16 @@ const SelectedEntriesTableContent = ({
|
|
3027
3364
|
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3028
3365
|
},
|
3029
3366
|
state: { from: pathname },
|
3030
|
-
label: formatMessage(
|
3031
|
-
|
3032
|
-
|
3033
|
-
|
3034
|
-
{
|
3035
|
-
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3036
|
-
defaultMessage: "item line {number}"
|
3037
|
-
},
|
3038
|
-
{ number: index2 + 1 }
|
3039
|
-
)
|
3040
|
-
}
|
3041
|
-
),
|
3367
|
+
label: formatMessage({
|
3368
|
+
id: "content-manager.bulk-publish.edit",
|
3369
|
+
defaultMessage: "Edit"
|
3370
|
+
}),
|
3042
3371
|
target: "_blank",
|
3043
3372
|
marginLeft: "auto",
|
3044
|
-
|
3373
|
+
variant: "ghost",
|
3374
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3045
3375
|
}
|
3046
|
-
) })
|
3376
|
+
) }) })
|
3047
3377
|
] }, row.id)) })
|
3048
3378
|
] });
|
3049
3379
|
};
|
@@ -3080,7 +3410,13 @@ const SelectedEntriesModalContent = ({
|
|
3080
3410
|
);
|
3081
3411
|
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3082
3412
|
if (data.length > 0 && schema) {
|
3083
|
-
const validate = createYupSchema(
|
3413
|
+
const validate = createYupSchema(
|
3414
|
+
schema.attributes,
|
3415
|
+
components,
|
3416
|
+
// Since this is the "Publish" action, the validation
|
3417
|
+
// schema must enforce the rules for published entities
|
3418
|
+
{ status: "published" }
|
3419
|
+
);
|
3084
3420
|
const validationErrors2 = {};
|
3085
3421
|
const rows2 = data.map((entry) => {
|
3086
3422
|
try {
|
@@ -3205,8 +3541,7 @@ const PublishAction = ({ documents, model }) => {
|
|
3205
3541
|
const refetchList = () => {
|
3206
3542
|
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3207
3543
|
};
|
3208
|
-
if (!showPublishButton)
|
3209
|
-
return null;
|
3544
|
+
if (!showPublishButton) return null;
|
3210
3545
|
return {
|
3211
3546
|
actionType: "publish",
|
3212
3547
|
variant: "tertiary",
|
@@ -3274,8 +3609,7 @@ const DeleteAction = ({ documents, model }) => {
|
|
3274
3609
|
selectRow([]);
|
3275
3610
|
}
|
3276
3611
|
};
|
3277
|
-
if (!hasDeletePermission)
|
3278
|
-
return null;
|
3612
|
+
if (!hasDeletePermission) return null;
|
3279
3613
|
return {
|
3280
3614
|
variant: "danger-light",
|
3281
3615
|
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
@@ -3324,8 +3658,7 @@ const UnpublishAction = ({ documents, model }) => {
|
|
3324
3658
|
}
|
3325
3659
|
};
|
3326
3660
|
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3327
|
-
if (!showUnpublishButton)
|
3328
|
-
return null;
|
3661
|
+
if (!showUnpublishButton) return null;
|
3329
3662
|
return {
|
3330
3663
|
variant: "tertiary",
|
3331
3664
|
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
@@ -3430,7 +3763,7 @@ const TableActions = ({ document }) => {
|
|
3430
3763
|
strapiAdmin.DescriptionComponentRenderer,
|
3431
3764
|
{
|
3432
3765
|
props,
|
3433
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3766
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
|
3434
3767
|
children: (actions2) => {
|
3435
3768
|
const tableRowActions = actions2.filter((action) => {
|
3436
3769
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3489,6 +3822,7 @@ const EditAction = ({ documentId }) => {
|
|
3489
3822
|
};
|
3490
3823
|
};
|
3491
3824
|
EditAction.type = "edit";
|
3825
|
+
EditAction.position = "table-row";
|
3492
3826
|
const StyledPencil = styledComponents.styled(Icons.Pencil)`
|
3493
3827
|
path {
|
3494
3828
|
fill: currentColor;
|
@@ -3541,7 +3875,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3541
3875
|
}),
|
3542
3876
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3543
3877
|
footer: ({ onClose }) => {
|
3544
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3878
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3545
3879
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3546
3880
|
id: "cancel",
|
3547
3881
|
defaultMessage: "Cancel"
|
@@ -3565,6 +3899,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3565
3899
|
};
|
3566
3900
|
};
|
3567
3901
|
CloneAction.type = "clone";
|
3902
|
+
CloneAction.position = "table-row";
|
3568
3903
|
const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
|
3569
3904
|
path {
|
3570
3905
|
fill: currentColor;
|
@@ -3582,8 +3917,7 @@ class ContentManagerPlugin {
|
|
3582
3917
|
documentActions = [
|
3583
3918
|
...DEFAULT_ACTIONS,
|
3584
3919
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3585
|
-
...DEFAULT_HEADER_ACTIONS
|
3586
|
-
HistoryAction
|
3920
|
+
...DEFAULT_HEADER_ACTIONS
|
3587
3921
|
];
|
3588
3922
|
editViewSidePanels = [ActionsPanel];
|
3589
3923
|
headerActions = [];
|
@@ -3652,7 +3986,14 @@ class ContentManagerPlugin {
|
|
3652
3986
|
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3653
3987
|
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3654
3988
|
getBulkActions: () => this.bulkActions,
|
3655
|
-
getDocumentActions: () =>
|
3989
|
+
getDocumentActions: (position) => {
|
3990
|
+
if (position) {
|
3991
|
+
return this.documentActions.filter(
|
3992
|
+
(action) => action.position == void 0 || [action.position].flat().includes(position)
|
3993
|
+
);
|
3994
|
+
}
|
3995
|
+
return this.documentActions;
|
3996
|
+
},
|
3656
3997
|
getEditViewSidePanels: () => this.editViewSidePanels,
|
3657
3998
|
getHeaderActions: () => this.headerActions
|
3658
3999
|
}
|
@@ -3662,16 +4003,71 @@ class ContentManagerPlugin {
|
|
3662
4003
|
const getPrintableType = (value) => {
|
3663
4004
|
const nativeType = typeof value;
|
3664
4005
|
if (nativeType === "object") {
|
3665
|
-
if (value === null)
|
3666
|
-
|
3667
|
-
if (Array.isArray(value))
|
3668
|
-
return "array";
|
4006
|
+
if (value === null) return "null";
|
4007
|
+
if (Array.isArray(value)) return "array";
|
3669
4008
|
if (value instanceof Object && value.constructor.name !== "Object") {
|
3670
4009
|
return value.constructor.name;
|
3671
4010
|
}
|
3672
4011
|
}
|
3673
4012
|
return nativeType;
|
3674
4013
|
};
|
4014
|
+
const HistoryAction = ({ model, document }) => {
|
4015
|
+
const { formatMessage } = reactIntl.useIntl();
|
4016
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
4017
|
+
const navigate = reactRouterDom.useNavigate();
|
4018
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
4019
|
+
const { pathname } = reactRouterDom.useLocation();
|
4020
|
+
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
4021
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
4022
|
+
return null;
|
4023
|
+
}
|
4024
|
+
const handleOnClick = () => {
|
4025
|
+
const destination = { pathname: "history", search: pluginsQueryParams };
|
4026
|
+
trackUsage("willNavigate", {
|
4027
|
+
from: pathname,
|
4028
|
+
to: `${pathname}/${destination.pathname}`
|
4029
|
+
});
|
4030
|
+
navigate(destination);
|
4031
|
+
};
|
4032
|
+
return {
|
4033
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
4034
|
+
label: formatMessage({
|
4035
|
+
id: "content-manager.history.document-action",
|
4036
|
+
defaultMessage: "Content History"
|
4037
|
+
}),
|
4038
|
+
onClick: handleOnClick,
|
4039
|
+
disabled: (
|
4040
|
+
/**
|
4041
|
+
* The user is creating a new document.
|
4042
|
+
* It hasn't been saved yet, so there's no history to go to
|
4043
|
+
*/
|
4044
|
+
!document || /**
|
4045
|
+
* The document has been created but the current dimension has never been saved.
|
4046
|
+
* For example, the user is creating a new locale in an existing document,
|
4047
|
+
* so there's no history for the document in that locale
|
4048
|
+
*/
|
4049
|
+
!document.id || /**
|
4050
|
+
* History is only available for content types created by the user.
|
4051
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
4052
|
+
* which start with `admin::` or `plugin::`
|
4053
|
+
*/
|
4054
|
+
!model.startsWith("api::")
|
4055
|
+
),
|
4056
|
+
position: "header"
|
4057
|
+
};
|
4058
|
+
};
|
4059
|
+
HistoryAction.type = "history";
|
4060
|
+
HistoryAction.position = "header";
|
4061
|
+
const historyAdmin = {
|
4062
|
+
bootstrap(app) {
|
4063
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
4064
|
+
addDocumentAction((actions2) => {
|
4065
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
4066
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
4067
|
+
return actions2;
|
4068
|
+
});
|
4069
|
+
}
|
4070
|
+
};
|
3675
4071
|
const initialState = {
|
3676
4072
|
collectionTypeLinks: [],
|
3677
4073
|
components: [],
|
@@ -3708,6 +4104,88 @@ const { setInitialData } = actions;
|
|
3708
4104
|
const reducer = toolkit.combineReducers({
|
3709
4105
|
app: reducer$1
|
3710
4106
|
});
|
4107
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4108
|
+
endpoints: (builder) => ({
|
4109
|
+
getPreviewUrl: builder.query({
|
4110
|
+
query({ query, params }) {
|
4111
|
+
return {
|
4112
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4113
|
+
method: "GET",
|
4114
|
+
config: {
|
4115
|
+
params: query
|
4116
|
+
}
|
4117
|
+
};
|
4118
|
+
}
|
4119
|
+
})
|
4120
|
+
})
|
4121
|
+
});
|
4122
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4123
|
+
const ConditionalTooltip = ({ isShown, label, children }) => {
|
4124
|
+
if (isShown) {
|
4125
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { label, children });
|
4126
|
+
}
|
4127
|
+
return children;
|
4128
|
+
};
|
4129
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4130
|
+
const { formatMessage } = reactIntl.useIntl();
|
4131
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
4132
|
+
const { pathname } = reactRouterDom.useLocation();
|
4133
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
4134
|
+
const isModified = strapiAdmin.useForm("PreviewSidePanel", (state) => state.modified);
|
4135
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4136
|
+
params: {
|
4137
|
+
contentType: model
|
4138
|
+
},
|
4139
|
+
query: {
|
4140
|
+
documentId,
|
4141
|
+
locale: document?.locale,
|
4142
|
+
status: document?.status
|
4143
|
+
}
|
4144
|
+
});
|
4145
|
+
if (!data?.data?.url || error) {
|
4146
|
+
return null;
|
4147
|
+
}
|
4148
|
+
const trackNavigation = () => {
|
4149
|
+
const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
|
4150
|
+
trackUsage("willNavigate", { from: pathname, to: destinationPathname });
|
4151
|
+
};
|
4152
|
+
return {
|
4153
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4154
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(
|
4155
|
+
ConditionalTooltip,
|
4156
|
+
{
|
4157
|
+
label: formatMessage({
|
4158
|
+
id: "content-manager.preview.panel.button-disabled-tooltip",
|
4159
|
+
defaultMessage: "Please save to open the preview"
|
4160
|
+
}),
|
4161
|
+
isShown: isModified,
|
4162
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { cursor: "not-allowed", width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
|
4163
|
+
designSystem.Button,
|
4164
|
+
{
|
4165
|
+
variant: "tertiary",
|
4166
|
+
tag: reactRouterDom.Link,
|
4167
|
+
to: { pathname: "preview", search: qs.stringify(query, { encode: false }) },
|
4168
|
+
onClick: trackNavigation,
|
4169
|
+
width: "100%",
|
4170
|
+
disabled: isModified,
|
4171
|
+
pointerEvents: isModified ? "none" : void 0,
|
4172
|
+
tabIndex: isModified ? -1 : void 0,
|
4173
|
+
children: formatMessage({
|
4174
|
+
id: "content-manager.preview.panel.button",
|
4175
|
+
defaultMessage: "Open preview"
|
4176
|
+
})
|
4177
|
+
}
|
4178
|
+
) })
|
4179
|
+
}
|
4180
|
+
)
|
4181
|
+
};
|
4182
|
+
};
|
4183
|
+
const previewAdmin = {
|
4184
|
+
bootstrap(app) {
|
4185
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4186
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4187
|
+
}
|
4188
|
+
};
|
3711
4189
|
const index = {
|
3712
4190
|
register(app) {
|
3713
4191
|
const cm = new ContentManagerPlugin();
|
@@ -3727,7 +4205,7 @@ const index = {
|
|
3727
4205
|
app.router.addRoute({
|
3728
4206
|
path: "content-manager/*",
|
3729
4207
|
lazy: async () => {
|
3730
|
-
const { Layout } = await Promise.resolve().then(() => require("./layout-
|
4208
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-B_qdWGny.js"));
|
3731
4209
|
return {
|
3732
4210
|
Component: Layout
|
3733
4211
|
};
|
@@ -3736,10 +4214,18 @@ const index = {
|
|
3736
4214
|
});
|
3737
4215
|
app.registerPlugin(cm.config);
|
3738
4216
|
},
|
4217
|
+
bootstrap(app) {
|
4218
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4219
|
+
historyAdmin.bootstrap(app);
|
4220
|
+
}
|
4221
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4222
|
+
previewAdmin.bootstrap(app);
|
4223
|
+
}
|
4224
|
+
},
|
3739
4225
|
async registerTrads({ locales }) {
|
3740
4226
|
const importedTrads = await Promise.all(
|
3741
4227
|
locales.map((locale) => {
|
3742
|
-
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-
|
4228
|
+
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 }) => {
|
3743
4229
|
return {
|
3744
4230
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3745
4231
|
locale
|
@@ -3757,6 +4243,7 @@ const index = {
|
|
3757
4243
|
};
|
3758
4244
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
3759
4245
|
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4246
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3760
4247
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3761
4248
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3762
4249
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3784,6 +4271,7 @@ exports.getMainField = getMainField;
|
|
3784
4271
|
exports.getTranslation = getTranslation;
|
3785
4272
|
exports.index = index;
|
3786
4273
|
exports.setInitialData = setInitialData;
|
4274
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3787
4275
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3788
4276
|
exports.useDoc = useDoc;
|
3789
4277
|
exports.useDocLayout = useDocLayout;
|
@@ -3795,5 +4283,6 @@ exports.useGetAllContentTypeSettingsQuery = useGetAllContentTypeSettingsQuery;
|
|
3795
4283
|
exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
3796
4284
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3797
4285
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
4286
|
+
exports.useGetPreviewUrlQuery = useGetPreviewUrlQuery;
|
3798
4287
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3799
|
-
//# sourceMappingURL=index-
|
4288
|
+
//# sourceMappingURL=index-CnX_j5h-.js.map
|