@strapi/content-manager 0.0.0-experimental.d53e940834bf72ddc725f1d2fd36dac9abec30cb → 0.0.0-experimental.d6bba97c7ed8309e57888e84d4788fa279d473fd
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-DmwmiFQy.mjs → ComponentConfigurationPage-D4J64ny7.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-D4J64ny7.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-DHV8IFbd.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-DHV8IFbd.js.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-JT3E7NZy.mjs → EditConfigurationPage-DMnf8orh.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-DMnf8orh.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js → EditConfigurationPage-q76oeVU1.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-q76oeVU1.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-BXoY-ITh.js} +63 -13
- package/dist/_chunks/EditViewPage-BXoY-ITh.js.map +1 -0
- package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-COVXj9bh.mjs} +63 -12
- package/dist/_chunks/EditViewPage-COVXj9bh.mjs.map +1 -0
- package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-CcppsFQR.mjs} +300 -203
- package/dist/_chunks/Field-CcppsFQR.mjs.map +1 -0
- package/dist/_chunks/{Field-Boxf9Ajp.js → Field-Dj1nOvt8.js} +303 -207
- package/dist/_chunks/Field-Dj1nOvt8.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-DbWwH0-A.mjs} +37 -18
- package/dist/_chunks/Form-DbWwH0-A.mjs.map +1 -0
- package/dist/_chunks/{Form-y5g1SRsh.js → Form-aTchNxab.js} +39 -21
- package/dist/_chunks/Form-aTchNxab.js.map +1 -0
- package/dist/_chunks/{History-CqN6K7SX.js → History-Cs6XM6EU.js} +81 -114
- package/dist/_chunks/History-Cs6XM6EU.js.map +1 -0
- package/dist/_chunks/{History-Bru_KoeP.mjs → History-tU567_hc.mjs} +82 -114
- package/dist/_chunks/History-tU567_hc.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-7LeytuFD.js} +25 -13
- package/dist/_chunks/ListConfigurationPage-7LeytuFD.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-DQryo_4i.mjs} +25 -12
- package/dist/_chunks/ListConfigurationPage-DQryo_4i.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-B50esy_x.mjs} +118 -77
- package/dist/_chunks/ListViewPage-B50esy_x.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-CaGBu5H5.js} +121 -81
- package/dist/_chunks/ListViewPage-CaGBu5H5.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-BaBE00IO.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-BaBE00IO.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-CiPP8cLx.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-CiPP8cLx.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-0-CW106p.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-0-CW106p.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-DQn5cqZz.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-DQn5cqZz.js.map} +1 -1
- package/dist/_chunks/Preview-C1dBkhXf.mjs +272 -0
- package/dist/_chunks/Preview-C1dBkhXf.mjs.map +1 -0
- package/dist/_chunks/Preview-DH1h7kJ6.js +290 -0
- package/dist/_chunks/Preview-DH1h7kJ6.js.map +1 -0
- package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-Bvne4TvU.mjs} +76 -42
- package/dist/_chunks/Relations-Bvne4TvU.mjs.map +1 -0
- package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-CkECnBOd.js} +76 -43
- package/dist/_chunks/Relations-CkECnBOd.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-BN1pPa5v.js} +1135 -693
- package/dist/_chunks/index-BN1pPa5v.js.map +1 -0
- package/dist/_chunks/{index-DJXJw9V5.mjs → index-ByPZ754U.mjs} +1156 -714
- package/dist/_chunks/index-ByPZ754U.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-CUTOYU8I.mjs} +26 -13
- package/dist/_chunks/layout-CUTOYU8I.mjs.map +1 -0
- package/dist/_chunks/{layout-Dm6fbiQj.js → layout-nBPDlXjr.js} +26 -14
- package/dist/_chunks/layout-nBPDlXjr.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-B6B-b7lI.js} +6 -7
- package/dist/_chunks/relations-B6B-b7lI.js.map +1 -0
- package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-CBc5HYHC.mjs} +6 -7
- package/dist/_chunks/relations-CBc5HYHC.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/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/constants.d.ts +1 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/router.d.ts +1 -1
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +19 -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 +615 -299
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +615 -298
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/uid.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +4 -4
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/constants.d.ts +2 -0
- package/dist/server/src/preview/constants.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +13 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +16 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +32 -0
- package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview.d.ts +12 -0
- package/dist/server/src/preview/services/preview.d.ts.map +1 -0
- package/dist/server/src/preview/utils.d.ts +19 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +8 -8
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -4
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
- package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/preview.d.ts +27 -0
- package/dist/shared/contracts/preview.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +4 -0
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +15 -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,7 +246,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
257
246
|
}),
|
258
247
|
invalidatesTags: (result, _error, { model }) => [
|
259
248
|
{ type: "Document", id: `${model}_LIST` },
|
260
|
-
"Relations"
|
249
|
+
"Relations",
|
250
|
+
{ type: "UidAvailability", id: model }
|
261
251
|
]
|
262
252
|
}),
|
263
253
|
deleteDocument: builder.mutation({
|
@@ -298,7 +288,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
298
288
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
299
289
|
},
|
300
290
|
{ type: "Document", id: `${model}_LIST` },
|
301
|
-
"Relations"
|
291
|
+
"Relations",
|
292
|
+
{ type: "UidAvailability", id: model }
|
302
293
|
];
|
303
294
|
}
|
304
295
|
}),
|
@@ -311,11 +302,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
311
302
|
url: `/content-manager/collection-types/${model}`,
|
312
303
|
method: "GET",
|
313
304
|
config: {
|
314
|
-
params
|
305
|
+
params: qs.stringify(params, { encode: true })
|
315
306
|
}
|
316
307
|
}),
|
317
308
|
providesTags: (result, _error, arg) => {
|
318
309
|
return [
|
310
|
+
{ type: "Document", id: `ALL_LIST` },
|
319
311
|
{ type: "Document", id: `${arg.model}_LIST` },
|
320
312
|
...result?.results.map(({ documentId }) => ({
|
321
313
|
type: "Document",
|
@@ -354,6 +346,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
354
346
|
{
|
355
347
|
type: "Document",
|
356
348
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
349
|
+
},
|
350
|
+
// Make it easy to invalidate all individual documents queries for a model
|
351
|
+
{
|
352
|
+
type: "Document",
|
353
|
+
id: `${model}_ALL_ITEMS`
|
357
354
|
}
|
358
355
|
];
|
359
356
|
}
|
@@ -417,8 +414,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
417
414
|
type: "Document",
|
418
415
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
419
416
|
},
|
420
|
-
"Relations"
|
417
|
+
"Relations",
|
418
|
+
{ type: "UidAvailability", id: model }
|
421
419
|
];
|
420
|
+
},
|
421
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
422
|
+
const patchResult = dispatch(
|
423
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
424
|
+
Object.assign(draft.data, data);
|
425
|
+
})
|
426
|
+
);
|
427
|
+
try {
|
428
|
+
await queryFulfilled;
|
429
|
+
} catch {
|
430
|
+
patchResult.undo();
|
431
|
+
}
|
422
432
|
}
|
423
433
|
}),
|
424
434
|
unpublishDocument: builder.mutation({
|
@@ -471,8 +481,7 @@ const {
|
|
471
481
|
useUnpublishManyDocumentsMutation
|
472
482
|
} = documentApi;
|
473
483
|
const buildValidParams = (query) => {
|
474
|
-
if (!query)
|
475
|
-
return query;
|
484
|
+
if (!query) return query;
|
476
485
|
const { plugins: _, ...validQueryParams } = {
|
477
486
|
...query,
|
478
487
|
...Object.values(query?.plugins ?? {}).reduce(
|
@@ -480,28 +489,44 @@ const buildValidParams = (query) => {
|
|
480
489
|
{}
|
481
490
|
)
|
482
491
|
};
|
483
|
-
if ("_q" in validQueryParams) {
|
484
|
-
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
485
|
-
}
|
486
492
|
return validQueryParams;
|
487
493
|
};
|
488
494
|
const isBaseQueryError = (error) => {
|
489
495
|
return error.name !== void 0;
|
490
496
|
};
|
491
|
-
const
|
497
|
+
const arrayValidator = (attribute, options) => ({
|
498
|
+
message: strapiAdmin.translatedErrors.required,
|
499
|
+
test(value) {
|
500
|
+
if (options.status === "draft") {
|
501
|
+
return true;
|
502
|
+
}
|
503
|
+
if (!attribute.required) {
|
504
|
+
return true;
|
505
|
+
}
|
506
|
+
if (!value) {
|
507
|
+
return false;
|
508
|
+
}
|
509
|
+
if (Array.isArray(value) && value.length === 0) {
|
510
|
+
return false;
|
511
|
+
}
|
512
|
+
return true;
|
513
|
+
}
|
514
|
+
});
|
515
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
492
516
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
493
517
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
494
518
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
495
519
|
return acc;
|
496
520
|
}
|
497
521
|
const validations = [
|
522
|
+
addNullableValidation,
|
498
523
|
addRequiredValidation,
|
499
524
|
addMinLengthValidation,
|
500
525
|
addMaxLengthValidation,
|
501
526
|
addMinValidation,
|
502
527
|
addMaxValidation,
|
503
528
|
addRegexValidation
|
504
|
-
].map((fn) => fn(attribute));
|
529
|
+
].map((fn) => fn(attribute, options));
|
505
530
|
const transformSchema = pipe__default.default(...validations);
|
506
531
|
switch (attribute.type) {
|
507
532
|
case "component": {
|
@@ -511,12 +536,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
511
536
|
...acc,
|
512
537
|
[name]: transformSchema(
|
513
538
|
yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
|
514
|
-
)
|
539
|
+
).test(arrayValidator(attribute, options))
|
515
540
|
};
|
516
541
|
} else {
|
517
542
|
return {
|
518
543
|
...acc,
|
519
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
544
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
520
545
|
};
|
521
546
|
}
|
522
547
|
}
|
@@ -538,7 +563,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
538
563
|
}
|
539
564
|
)
|
540
565
|
)
|
541
|
-
)
|
566
|
+
).test(arrayValidator(attribute, options))
|
542
567
|
};
|
543
568
|
case "relation":
|
544
569
|
return {
|
@@ -550,7 +575,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
550
575
|
} else if (Array.isArray(value)) {
|
551
576
|
return yup__namespace.array().of(
|
552
577
|
yup__namespace.object().shape({
|
553
|
-
id: yup__namespace.
|
578
|
+
id: yup__namespace.number().required()
|
554
579
|
})
|
555
580
|
);
|
556
581
|
} else if (typeof value === "object") {
|
@@ -602,6 +627,14 @@ const createAttributeSchema = (attribute) => {
|
|
602
627
|
if (!value || typeof value === "string" && value.length === 0) {
|
603
628
|
return true;
|
604
629
|
}
|
630
|
+
if (typeof value === "object") {
|
631
|
+
try {
|
632
|
+
JSON.stringify(value);
|
633
|
+
return true;
|
634
|
+
} catch (err) {
|
635
|
+
return false;
|
636
|
+
}
|
637
|
+
}
|
605
638
|
try {
|
606
639
|
JSON.parse(value);
|
607
640
|
return true;
|
@@ -620,13 +653,7 @@ const createAttributeSchema = (attribute) => {
|
|
620
653
|
return yup__namespace.mixed();
|
621
654
|
}
|
622
655
|
};
|
623
|
-
const
|
624
|
-
if (attribute.required) {
|
625
|
-
return schema.required({
|
626
|
-
id: strapiAdmin.translatedErrors.required.id,
|
627
|
-
defaultMessage: "This field is required."
|
628
|
-
});
|
629
|
-
}
|
656
|
+
const nullableSchema = (schema) => {
|
630
657
|
return schema?.nullable ? schema.nullable() : (
|
631
658
|
// In some cases '.nullable' will not be available on the schema.
|
632
659
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -634,7 +661,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
634
661
|
schema
|
635
662
|
);
|
636
663
|
};
|
637
|
-
const
|
664
|
+
const addNullableValidation = () => (schema) => {
|
665
|
+
return nullableSchema(schema);
|
666
|
+
};
|
667
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
668
|
+
if (options.status === "draft" || !attribute.required) {
|
669
|
+
return schema;
|
670
|
+
}
|
671
|
+
if (attribute.required && "required" in schema) {
|
672
|
+
return schema.required(strapiAdmin.translatedErrors.required);
|
673
|
+
}
|
674
|
+
return schema;
|
675
|
+
};
|
676
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
677
|
+
if (options.status === "draft") {
|
678
|
+
return schema;
|
679
|
+
}
|
638
680
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
639
681
|
return schema.min(attribute.minLength, {
|
640
682
|
...strapiAdmin.translatedErrors.minLength,
|
@@ -656,10 +698,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
656
698
|
}
|
657
699
|
return schema;
|
658
700
|
};
|
659
|
-
const addMinValidation = (attribute) => (schema) => {
|
660
|
-
if ("
|
701
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
702
|
+
if (options.status === "draft") {
|
703
|
+
return schema;
|
704
|
+
}
|
705
|
+
if ("min" in attribute && "min" in schema) {
|
661
706
|
const min = toInteger(attribute.min);
|
662
|
-
if (
|
707
|
+
if (min) {
|
663
708
|
return schema.min(min, {
|
664
709
|
...strapiAdmin.translatedErrors.min,
|
665
710
|
values: {
|
@@ -777,16 +822,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
777
822
|
}, {});
|
778
823
|
return componentsByKey;
|
779
824
|
};
|
780
|
-
const
|
825
|
+
const HOOKS = {
|
826
|
+
/**
|
827
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
828
|
+
* @constant
|
829
|
+
* @type {string}
|
830
|
+
*/
|
831
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
832
|
+
/**
|
833
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
834
|
+
* @constant
|
835
|
+
* @type {string}
|
836
|
+
*/
|
837
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
838
|
+
/**
|
839
|
+
* Hook that allows to mutate the CM's edit view layout
|
840
|
+
* @constant
|
841
|
+
* @type {string}
|
842
|
+
*/
|
843
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
844
|
+
/**
|
845
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
846
|
+
* @constant
|
847
|
+
* @type {string}
|
848
|
+
*/
|
849
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
850
|
+
};
|
851
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
852
|
+
endpoints: (builder) => ({
|
853
|
+
getContentTypeConfiguration: builder.query({
|
854
|
+
query: (uid) => ({
|
855
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
856
|
+
method: "GET"
|
857
|
+
}),
|
858
|
+
transformResponse: (response) => response.data,
|
859
|
+
providesTags: (_result, _error, uid) => [
|
860
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
861
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
862
|
+
]
|
863
|
+
}),
|
864
|
+
getAllContentTypeSettings: builder.query({
|
865
|
+
query: () => "/content-manager/content-types-settings",
|
866
|
+
transformResponse: (response) => response.data,
|
867
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
868
|
+
}),
|
869
|
+
updateContentTypeConfiguration: builder.mutation({
|
870
|
+
query: ({ uid, ...body }) => ({
|
871
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
872
|
+
method: "PUT",
|
873
|
+
data: body
|
874
|
+
}),
|
875
|
+
transformResponse: (response) => response.data,
|
876
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
877
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
878
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
879
|
+
// Is this necessary?
|
880
|
+
{ type: "InitialData" }
|
881
|
+
]
|
882
|
+
})
|
883
|
+
})
|
884
|
+
});
|
885
|
+
const {
|
886
|
+
useGetContentTypeConfigurationQuery,
|
887
|
+
useGetAllContentTypeSettingsQuery,
|
888
|
+
useUpdateContentTypeConfigurationMutation
|
889
|
+
} = contentTypesApi;
|
890
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
891
|
+
const { type } = attribute;
|
892
|
+
if (type === "relation") {
|
893
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
894
|
+
}
|
895
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
896
|
+
};
|
897
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
898
|
+
if (!mainFieldName) {
|
899
|
+
return void 0;
|
900
|
+
}
|
901
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
902
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
903
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
904
|
+
);
|
905
|
+
return {
|
906
|
+
name: mainFieldName,
|
907
|
+
type: mainFieldType ?? "string"
|
908
|
+
};
|
909
|
+
};
|
910
|
+
const DEFAULT_SETTINGS = {
|
911
|
+
bulkable: false,
|
912
|
+
filterable: false,
|
913
|
+
searchable: false,
|
914
|
+
pagination: false,
|
915
|
+
defaultSortBy: "",
|
916
|
+
defaultSortOrder: "asc",
|
917
|
+
mainField: "id",
|
918
|
+
pageSize: 10
|
919
|
+
};
|
920
|
+
const useDocumentLayout = (model) => {
|
921
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
922
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
923
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
781
924
|
const { toggleNotification } = strapiAdmin.useNotification();
|
782
925
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
926
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
783
927
|
const {
|
784
|
-
|
785
|
-
isLoading:
|
786
|
-
|
787
|
-
|
788
|
-
} =
|
789
|
-
const
|
928
|
+
data,
|
929
|
+
isLoading: isLoadingConfigs,
|
930
|
+
error,
|
931
|
+
isFetching: isFetchingConfigs
|
932
|
+
} = useGetContentTypeConfigurationQuery(model);
|
933
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
790
934
|
React__namespace.useEffect(() => {
|
791
935
|
if (error) {
|
792
936
|
toggleNotification({
|
@@ -794,68 +938,322 @@ const useDocument = (args, opts) => {
|
|
794
938
|
message: formatAPIError(error)
|
795
939
|
});
|
796
940
|
}
|
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
|
-
}
|
941
|
+
}, [error, formatAPIError, toggleNotification]);
|
942
|
+
const editLayout = React__namespace.useMemo(
|
943
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
944
|
+
layout: [],
|
945
|
+
components: {},
|
946
|
+
metadatas: {},
|
947
|
+
options: {},
|
948
|
+
settings: DEFAULT_SETTINGS
|
820
949
|
},
|
821
|
-
[
|
950
|
+
[data, isLoading, schemas, schema, components]
|
951
|
+
);
|
952
|
+
const listLayout = React__namespace.useMemo(() => {
|
953
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
954
|
+
layout: [],
|
955
|
+
metadatas: {},
|
956
|
+
options: {},
|
957
|
+
settings: DEFAULT_SETTINGS
|
958
|
+
};
|
959
|
+
}, [data, isLoading, schemas, schema, components]);
|
960
|
+
const { layout: edit } = React__namespace.useMemo(
|
961
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
962
|
+
layout: editLayout,
|
963
|
+
query
|
964
|
+
}),
|
965
|
+
[editLayout, query, runHookWaterfall]
|
822
966
|
);
|
823
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
824
967
|
return {
|
825
|
-
|
826
|
-
document: data?.data,
|
827
|
-
meta: data?.meta,
|
968
|
+
error,
|
828
969
|
isLoading,
|
829
|
-
|
830
|
-
|
970
|
+
edit,
|
971
|
+
list: listLayout
|
831
972
|
};
|
832
973
|
};
|
833
|
-
const
|
834
|
-
const {
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
974
|
+
const useDocLayout = () => {
|
975
|
+
const { model } = useDoc();
|
976
|
+
return useDocumentLayout(model);
|
977
|
+
};
|
978
|
+
const formatEditLayout = (data, {
|
979
|
+
schemas,
|
980
|
+
schema,
|
981
|
+
components
|
982
|
+
}) => {
|
983
|
+
let currentPanelIndex = 0;
|
984
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
985
|
+
data.contentType.layouts.edit,
|
986
|
+
schema?.attributes,
|
987
|
+
data.contentType.metadatas,
|
988
|
+
{ configurations: data.components, schemas: components },
|
989
|
+
schemas
|
990
|
+
).reduce((panels, row) => {
|
991
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
992
|
+
panels.push([row]);
|
993
|
+
currentPanelIndex += 2;
|
994
|
+
} else {
|
995
|
+
if (!panels[currentPanelIndex]) {
|
996
|
+
panels.push([row]);
|
997
|
+
} else {
|
998
|
+
panels[currentPanelIndex].push(row);
|
999
|
+
}
|
1000
|
+
}
|
1001
|
+
return panels;
|
1002
|
+
}, []);
|
1003
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
1004
|
+
(acc, [uid, configuration]) => {
|
1005
|
+
acc[uid] = {
|
1006
|
+
layout: convertEditLayoutToFieldLayouts(
|
1007
|
+
configuration.layouts.edit,
|
1008
|
+
components[uid].attributes,
|
1009
|
+
configuration.metadatas,
|
1010
|
+
{ configurations: data.components, schemas: components }
|
1011
|
+
),
|
1012
|
+
settings: {
|
1013
|
+
...configuration.settings,
|
1014
|
+
icon: components[uid].info.icon,
|
1015
|
+
displayName: components[uid].info.displayName
|
1016
|
+
}
|
1017
|
+
};
|
1018
|
+
return acc;
|
1019
|
+
},
|
1020
|
+
{}
|
1021
|
+
);
|
1022
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1023
|
+
(acc, [attribute, metadata]) => {
|
1024
|
+
return {
|
1025
|
+
...acc,
|
1026
|
+
[attribute]: metadata.edit
|
1027
|
+
};
|
1028
|
+
},
|
1029
|
+
{}
|
1030
|
+
);
|
1031
|
+
return {
|
1032
|
+
layout: panelledEditAttributes,
|
1033
|
+
components: componentEditAttributes,
|
1034
|
+
metadatas: editMetadatas,
|
1035
|
+
settings: {
|
1036
|
+
...data.contentType.settings,
|
1037
|
+
displayName: schema?.info.displayName
|
1038
|
+
},
|
1039
|
+
options: {
|
1040
|
+
...schema?.options,
|
1041
|
+
...schema?.pluginOptions,
|
1042
|
+
...data.contentType.options
|
1043
|
+
}
|
1044
|
+
};
|
1045
|
+
};
|
1046
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1047
|
+
return rows.map(
|
1048
|
+
(row) => row.map((field) => {
|
1049
|
+
const attribute = attributes[field.name];
|
1050
|
+
if (!attribute) {
|
1051
|
+
return null;
|
1052
|
+
}
|
1053
|
+
const { edit: metadata } = metadatas[field.name];
|
1054
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1055
|
+
return {
|
1056
|
+
attribute,
|
1057
|
+
disabled: !metadata.editable,
|
1058
|
+
hint: metadata.description,
|
1059
|
+
label: metadata.label ?? "",
|
1060
|
+
name: field.name,
|
1061
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1062
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1063
|
+
schemas,
|
1064
|
+
components: components?.schemas ?? {}
|
1065
|
+
}),
|
1066
|
+
placeholder: metadata.placeholder ?? "",
|
1067
|
+
required: attribute.required ?? false,
|
1068
|
+
size: field.size,
|
1069
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1070
|
+
visible: metadata.visible ?? true,
|
1071
|
+
type: attribute.type
|
1072
|
+
};
|
1073
|
+
}).filter((field) => field !== null)
|
1074
|
+
);
|
1075
|
+
};
|
1076
|
+
const formatListLayout = (data, {
|
1077
|
+
schemas,
|
1078
|
+
schema,
|
1079
|
+
components
|
1080
|
+
}) => {
|
1081
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1082
|
+
(acc, [attribute, metadata]) => {
|
1083
|
+
return {
|
1084
|
+
...acc,
|
1085
|
+
[attribute]: metadata.list
|
1086
|
+
};
|
1087
|
+
},
|
1088
|
+
{}
|
1089
|
+
);
|
1090
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1091
|
+
data.contentType.layouts.list,
|
1092
|
+
schema?.attributes,
|
1093
|
+
listMetadatas,
|
1094
|
+
{ configurations: data.components, schemas: components },
|
1095
|
+
schemas
|
1096
|
+
);
|
1097
|
+
return {
|
1098
|
+
layout: listAttributes,
|
1099
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1100
|
+
metadatas: listMetadatas,
|
1101
|
+
options: {
|
1102
|
+
...schema?.options,
|
1103
|
+
...schema?.pluginOptions,
|
1104
|
+
...data.contentType.options
|
1105
|
+
}
|
1106
|
+
};
|
1107
|
+
};
|
1108
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1109
|
+
return columns.map((name) => {
|
1110
|
+
const attribute = attributes[name];
|
1111
|
+
if (!attribute) {
|
1112
|
+
return null;
|
1113
|
+
}
|
1114
|
+
const metadata = metadatas[name];
|
1115
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1116
|
+
return {
|
1117
|
+
attribute,
|
1118
|
+
label: metadata.label ?? "",
|
1119
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1120
|
+
schemas,
|
1121
|
+
components: components?.schemas ?? {}
|
1122
|
+
}),
|
1123
|
+
name,
|
1124
|
+
searchable: metadata.searchable ?? true,
|
1125
|
+
sortable: metadata.sortable ?? true
|
1126
|
+
};
|
1127
|
+
}).filter((field) => field !== null);
|
1128
|
+
};
|
1129
|
+
const useDocument = (args, opts) => {
|
1130
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1131
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1132
|
+
const {
|
1133
|
+
currentData: data,
|
1134
|
+
isLoading: isLoadingDocument,
|
1135
|
+
isFetching: isFetchingDocument,
|
1136
|
+
error
|
1137
|
+
} = useGetDocumentQuery(args, {
|
1138
|
+
...opts,
|
1139
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1140
|
+
});
|
1141
|
+
const {
|
1142
|
+
components,
|
1143
|
+
schema,
|
1144
|
+
schemas,
|
1145
|
+
isLoading: isLoadingSchema
|
1146
|
+
} = useContentTypeSchema(args.model);
|
1147
|
+
React__namespace.useEffect(() => {
|
1148
|
+
if (error) {
|
1149
|
+
toggleNotification({
|
1150
|
+
type: "danger",
|
1151
|
+
message: formatAPIError(error)
|
1152
|
+
});
|
1153
|
+
}
|
1154
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1155
|
+
const validationSchema = React__namespace.useMemo(() => {
|
1156
|
+
if (!schema) {
|
1157
|
+
return null;
|
1158
|
+
}
|
1159
|
+
return createYupSchema(schema.attributes, components);
|
1160
|
+
}, [schema, components]);
|
1161
|
+
const validate = React__namespace.useCallback(
|
1162
|
+
(document) => {
|
1163
|
+
if (!validationSchema) {
|
1164
|
+
throw new Error(
|
1165
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1166
|
+
);
|
1167
|
+
}
|
1168
|
+
try {
|
1169
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1170
|
+
return null;
|
1171
|
+
} catch (error2) {
|
1172
|
+
if (error2 instanceof yup.ValidationError) {
|
1173
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
1174
|
+
}
|
1175
|
+
throw error2;
|
1176
|
+
}
|
1177
|
+
},
|
1178
|
+
[validationSchema]
|
1179
|
+
);
|
1180
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1181
|
+
const hasError = !!error;
|
1182
|
+
return {
|
1183
|
+
components,
|
1184
|
+
document: data?.data,
|
1185
|
+
meta: data?.meta,
|
1186
|
+
isLoading,
|
1187
|
+
hasError,
|
1188
|
+
schema,
|
1189
|
+
schemas,
|
1190
|
+
validate
|
1191
|
+
};
|
1192
|
+
};
|
1193
|
+
const useDoc = () => {
|
1194
|
+
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
1195
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
1196
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1197
|
+
if (!collectionType) {
|
1198
|
+
throw new Error("Could not find collectionType in url params");
|
839
1199
|
}
|
840
1200
|
if (!slug) {
|
841
1201
|
throw new Error("Could not find model in url params");
|
842
1202
|
}
|
1203
|
+
const document = useDocument(
|
1204
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1205
|
+
{
|
1206
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1207
|
+
}
|
1208
|
+
);
|
1209
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
843
1210
|
return {
|
844
1211
|
collectionType,
|
845
1212
|
model: slug,
|
846
|
-
id:
|
847
|
-
...
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
1213
|
+
id: returnId,
|
1214
|
+
...document
|
1215
|
+
};
|
1216
|
+
};
|
1217
|
+
const useContentManagerContext = () => {
|
1218
|
+
const {
|
1219
|
+
collectionType,
|
1220
|
+
model,
|
1221
|
+
id,
|
1222
|
+
components,
|
1223
|
+
isLoading: isLoadingDoc,
|
1224
|
+
schema,
|
1225
|
+
schemas
|
1226
|
+
} = useDoc();
|
1227
|
+
const layout = useDocumentLayout(model);
|
1228
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1229
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1230
|
+
const slug = model;
|
1231
|
+
const isCreatingEntry = id === "create";
|
1232
|
+
useContentTypeSchema();
|
1233
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1234
|
+
const error = layout.error;
|
1235
|
+
return {
|
1236
|
+
error,
|
1237
|
+
isLoading,
|
1238
|
+
// Base metadata
|
1239
|
+
model,
|
1240
|
+
collectionType,
|
1241
|
+
id,
|
1242
|
+
slug,
|
1243
|
+
isCreatingEntry,
|
1244
|
+
isSingleType,
|
1245
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1246
|
+
// All schema infos
|
1247
|
+
components,
|
1248
|
+
contentType: schema,
|
1249
|
+
contentTypes: schemas,
|
1250
|
+
// Form state
|
1251
|
+
form,
|
1252
|
+
// layout infos
|
1253
|
+
layout
|
853
1254
|
};
|
854
1255
|
};
|
855
1256
|
const prefixPluginTranslations = (trad, pluginId) => {
|
856
|
-
if (!pluginId) {
|
857
|
-
throw new TypeError("pluginId can't be empty");
|
858
|
-
}
|
859
1257
|
return Object.keys(trad).reduce((acc, current) => {
|
860
1258
|
acc[`${pluginId}.${current}`] = trad[current];
|
861
1259
|
return acc;
|
@@ -871,6 +1269,8 @@ const useDocumentActions = () => {
|
|
871
1269
|
const { formatMessage } = reactIntl.useIntl();
|
872
1270
|
const { trackUsage } = strapiAdmin.useTracking();
|
873
1271
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1272
|
+
const navigate = reactRouterDom.useNavigate();
|
1273
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
874
1274
|
const [deleteDocument] = useDeleteDocumentMutation();
|
875
1275
|
const _delete = React__namespace.useCallback(
|
876
1276
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1185,6 +1585,7 @@ const useDocumentActions = () => {
|
|
1185
1585
|
defaultMessage: "Saved document"
|
1186
1586
|
})
|
1187
1587
|
});
|
1588
|
+
setCurrentStep("contentManager.success");
|
1188
1589
|
return res.data;
|
1189
1590
|
} catch (err) {
|
1190
1591
|
toggleNotification({
|
@@ -1206,7 +1607,6 @@ const useDocumentActions = () => {
|
|
1206
1607
|
sourceId
|
1207
1608
|
});
|
1208
1609
|
if ("error" in res) {
|
1209
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1210
1610
|
return { error: res.error };
|
1211
1611
|
}
|
1212
1612
|
toggleNotification({
|
@@ -1225,7 +1625,7 @@ const useDocumentActions = () => {
|
|
1225
1625
|
throw err;
|
1226
1626
|
}
|
1227
1627
|
},
|
1228
|
-
[autoCloneDocument,
|
1628
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1229
1629
|
);
|
1230
1630
|
const [cloneDocument] = useCloneDocumentMutation();
|
1231
1631
|
const clone = React__namespace.useCallback(
|
@@ -1251,6 +1651,7 @@ const useDocumentActions = () => {
|
|
1251
1651
|
defaultMessage: "Cloned document"
|
1252
1652
|
})
|
1253
1653
|
});
|
1654
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1254
1655
|
return res.data;
|
1255
1656
|
} catch (err) {
|
1256
1657
|
toggleNotification({
|
@@ -1261,7 +1662,7 @@ const useDocumentActions = () => {
|
|
1261
1662
|
throw err;
|
1262
1663
|
}
|
1263
1664
|
},
|
1264
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1665
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1265
1666
|
);
|
1266
1667
|
const [getDoc] = useLazyGetDocumentQuery();
|
1267
1668
|
const getDocument = React__namespace.useCallback(
|
@@ -1286,10 +1687,10 @@ const useDocumentActions = () => {
|
|
1286
1687
|
update
|
1287
1688
|
};
|
1288
1689
|
};
|
1289
|
-
const ProtectedHistoryPage =
|
1290
|
-
() => Promise.resolve().then(() => require("./History-
|
1690
|
+
const ProtectedHistoryPage = React__namespace.lazy(
|
1691
|
+
() => Promise.resolve().then(() => require("./History-Cs6XM6EU.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1291
1692
|
);
|
1292
|
-
const routes$
|
1693
|
+
const routes$2 = [
|
1293
1694
|
{
|
1294
1695
|
path: ":collectionType/:slug/:id/history",
|
1295
1696
|
Component: ProtectedHistoryPage
|
@@ -1299,32 +1700,45 @@ const routes$1 = [
|
|
1299
1700
|
Component: ProtectedHistoryPage
|
1300
1701
|
}
|
1301
1702
|
];
|
1703
|
+
const ProtectedPreviewPage = React__namespace.lazy(
|
1704
|
+
() => Promise.resolve().then(() => require("./Preview-DH1h7kJ6.js")).then((mod) => ({ default: mod.ProtectedPreviewPage }))
|
1705
|
+
);
|
1706
|
+
const routes$1 = [
|
1707
|
+
{
|
1708
|
+
path: ":collectionType/:slug/:id/preview",
|
1709
|
+
Component: ProtectedPreviewPage
|
1710
|
+
},
|
1711
|
+
{
|
1712
|
+
path: ":collectionType/:slug/preview",
|
1713
|
+
Component: ProtectedPreviewPage
|
1714
|
+
}
|
1715
|
+
];
|
1302
1716
|
const ProtectedEditViewPage = React.lazy(
|
1303
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1717
|
+
() => Promise.resolve().then(() => require("./EditViewPage-BXoY-ITh.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1304
1718
|
);
|
1305
1719
|
const ProtectedListViewPage = React.lazy(
|
1306
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1720
|
+
() => Promise.resolve().then(() => require("./ListViewPage-CaGBu5H5.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1307
1721
|
);
|
1308
1722
|
const ProtectedListConfiguration = React.lazy(
|
1309
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1723
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-7LeytuFD.js")).then((mod) => ({
|
1310
1724
|
default: mod.ProtectedListConfiguration
|
1311
1725
|
}))
|
1312
1726
|
);
|
1313
1727
|
const ProtectedEditConfigurationPage = React.lazy(
|
1314
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1728
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-q76oeVU1.js")).then((mod) => ({
|
1315
1729
|
default: mod.ProtectedEditConfigurationPage
|
1316
1730
|
}))
|
1317
1731
|
);
|
1318
1732
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1319
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1733
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-DHV8IFbd.js")).then((mod) => ({
|
1320
1734
|
default: mod.ProtectedComponentConfigurationPage
|
1321
1735
|
}))
|
1322
1736
|
);
|
1323
1737
|
const NoPermissions = React.lazy(
|
1324
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1738
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-DQn5cqZz.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1325
1739
|
);
|
1326
1740
|
const NoContentType = React.lazy(
|
1327
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1741
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-BaBE00IO.js")).then((mod) => ({ default: mod.NoContentType }))
|
1328
1742
|
);
|
1329
1743
|
const CollectionTypePages = () => {
|
1330
1744
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1336,7 +1750,7 @@ const CollectionTypePages = () => {
|
|
1336
1750
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1337
1751
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1338
1752
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1339
|
-
const LIST_PATH = `/content-manager
|
1753
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1340
1754
|
const routes = [
|
1341
1755
|
{
|
1342
1756
|
path: LIST_RELATIVE_PATH,
|
@@ -1370,6 +1784,7 @@ const routes = [
|
|
1370
1784
|
path: "no-content-types",
|
1371
1785
|
Component: NoContentType
|
1372
1786
|
},
|
1787
|
+
...routes$2,
|
1373
1788
|
...routes$1
|
1374
1789
|
];
|
1375
1790
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1438,12 +1853,14 @@ const DocumentActionButton = (action) => {
|
|
1438
1853
|
/* @__PURE__ */ jsxRuntime.jsx(
|
1439
1854
|
designSystem.Button,
|
1440
1855
|
{
|
1441
|
-
flex:
|
1856
|
+
flex: "auto",
|
1442
1857
|
startIcon: action.icon,
|
1443
1858
|
disabled: action.disabled,
|
1444
1859
|
onClick: handleClick(action),
|
1445
1860
|
justifyContent: "center",
|
1446
1861
|
variant: action.variant || "default",
|
1862
|
+
paddingTop: "7px",
|
1863
|
+
paddingBottom: "7px",
|
1447
1864
|
children: action.label
|
1448
1865
|
}
|
1449
1866
|
),
|
@@ -1451,7 +1868,7 @@ const DocumentActionButton = (action) => {
|
|
1451
1868
|
DocumentActionConfirmDialog,
|
1452
1869
|
{
|
1453
1870
|
...action.dialog,
|
1454
|
-
variant: action.variant,
|
1871
|
+
variant: action.dialog?.variant ?? action.variant,
|
1455
1872
|
isOpen: dialogId === action.id,
|
1456
1873
|
onClose: handleClose
|
1457
1874
|
}
|
@@ -1466,6 +1883,11 @@ const DocumentActionButton = (action) => {
|
|
1466
1883
|
) : null
|
1467
1884
|
] });
|
1468
1885
|
};
|
1886
|
+
const MenuItem = styledComponents.styled(designSystem.Menu.Item)`
|
1887
|
+
&:hover {
|
1888
|
+
background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
|
1889
|
+
}
|
1890
|
+
`;
|
1469
1891
|
const DocumentActionsMenu = ({
|
1470
1892
|
actions: actions2,
|
1471
1893
|
children,
|
@@ -1508,9 +1930,9 @@ const DocumentActionsMenu = ({
|
|
1508
1930
|
disabled: isDisabled,
|
1509
1931
|
size: "S",
|
1510
1932
|
endIcon: null,
|
1511
|
-
paddingTop: "
|
1512
|
-
paddingLeft: "
|
1513
|
-
paddingRight: "
|
1933
|
+
paddingTop: "4px",
|
1934
|
+
paddingLeft: "7px",
|
1935
|
+
paddingRight: "7px",
|
1514
1936
|
variant,
|
1515
1937
|
children: [
|
1516
1938
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
@@ -1521,36 +1943,35 @@ const DocumentActionsMenu = ({
|
|
1521
1943
|
]
|
1522
1944
|
}
|
1523
1945
|
),
|
1524
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, {
|
1946
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1525
1947
|
actions2.map((action) => {
|
1526
1948
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
1527
|
-
|
1949
|
+
MenuItem,
|
1528
1950
|
{
|
1529
1951
|
disabled: action.disabled,
|
1530
1952
|
onSelect: handleClick(action),
|
1531
1953
|
display: "block",
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
] })
|
1954
|
+
isVariantDanger: action.variant === "danger",
|
1955
|
+
isDisabled: action.disabled,
|
1956
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
1957
|
+
designSystem.Flex,
|
1958
|
+
{
|
1959
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1960
|
+
gap: 2,
|
1961
|
+
tag: "span",
|
1962
|
+
children: [
|
1963
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1964
|
+
designSystem.Flex,
|
1965
|
+
{
|
1966
|
+
tag: "span",
|
1967
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1968
|
+
children: action.icon
|
1969
|
+
}
|
1970
|
+
),
|
1971
|
+
action.label
|
1972
|
+
]
|
1973
|
+
}
|
1974
|
+
) })
|
1554
1975
|
},
|
1555
1976
|
action.id
|
1556
1977
|
);
|
@@ -1630,11 +2051,11 @@ const DocumentActionConfirmDialog = ({
|
|
1630
2051
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
1631
2052
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
1632
2053
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
1633
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
|
2054
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1634
2055
|
id: "app.components.Button.cancel",
|
1635
2056
|
defaultMessage: "Cancel"
|
1636
2057
|
}) }) }),
|
1637
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2058
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1638
2059
|
id: "app.components.Button.confirm",
|
1639
2060
|
defaultMessage: "Confirm"
|
1640
2061
|
}) })
|
@@ -1661,6 +2082,18 @@ const DocumentActionModal = ({
|
|
1661
2082
|
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
1662
2083
|
] }) });
|
1663
2084
|
};
|
2085
|
+
const transformData = (data) => {
|
2086
|
+
if (Array.isArray(data)) {
|
2087
|
+
return data.map(transformData);
|
2088
|
+
}
|
2089
|
+
if (typeof data === "object" && data !== null) {
|
2090
|
+
if ("apiData" in data) {
|
2091
|
+
return data.apiData;
|
2092
|
+
}
|
2093
|
+
return mapValues__default.default(transformData)(data);
|
2094
|
+
}
|
2095
|
+
return data;
|
2096
|
+
};
|
1664
2097
|
const PublishAction$1 = ({
|
1665
2098
|
activeTab,
|
1666
2099
|
documentId,
|
@@ -1673,13 +2106,18 @@ const PublishAction$1 = ({
|
|
1673
2106
|
const navigate = reactRouterDom.useNavigate();
|
1674
2107
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1675
2108
|
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2109
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
1676
2110
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2111
|
+
const { id } = reactRouterDom.useParams();
|
1677
2112
|
const { formatMessage } = reactIntl.useIntl();
|
1678
|
-
const { canPublish
|
1679
|
-
"PublishAction",
|
1680
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1681
|
-
);
|
2113
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1682
2114
|
const { publish } = useDocumentActions();
|
2115
|
+
const [
|
2116
|
+
countDraftRelations,
|
2117
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2118
|
+
] = useLazyGetDraftRelationCountQuery();
|
2119
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
2120
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1683
2121
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1684
2122
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1685
2123
|
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1688,10 +2126,107 @@ const PublishAction$1 = ({
|
|
1688
2126
|
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1689
2127
|
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1690
2128
|
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
2129
|
+
React__namespace.useEffect(() => {
|
2130
|
+
if (isErrorDraftRelations) {
|
2131
|
+
toggleNotification({
|
2132
|
+
type: "danger",
|
2133
|
+
message: formatMessage({
|
2134
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2135
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2136
|
+
})
|
2137
|
+
});
|
2138
|
+
}
|
2139
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2140
|
+
React__namespace.useEffect(() => {
|
2141
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2142
|
+
const extractDraftRelations = (data) => {
|
2143
|
+
const relations = data.connect || [];
|
2144
|
+
relations.forEach((relation) => {
|
2145
|
+
if (relation.status === "draft") {
|
2146
|
+
localDraftRelations.add(relation.id);
|
2147
|
+
}
|
2148
|
+
});
|
2149
|
+
};
|
2150
|
+
const traverseAndExtract = (data) => {
|
2151
|
+
Object.entries(data).forEach(([key, value]) => {
|
2152
|
+
if (key === "connect" && Array.isArray(value)) {
|
2153
|
+
extractDraftRelations({ connect: value });
|
2154
|
+
} else if (typeof value === "object" && value !== null) {
|
2155
|
+
traverseAndExtract(value);
|
2156
|
+
}
|
2157
|
+
});
|
2158
|
+
};
|
2159
|
+
if (!documentId || modified) {
|
2160
|
+
traverseAndExtract(formValues);
|
2161
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2162
|
+
}
|
2163
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2164
|
+
React__namespace.useEffect(() => {
|
2165
|
+
if (!document || !document.documentId || isListView) {
|
2166
|
+
return;
|
2167
|
+
}
|
2168
|
+
const fetchDraftRelationsCount = async () => {
|
2169
|
+
const { data, error } = await countDraftRelations({
|
2170
|
+
collectionType,
|
2171
|
+
model,
|
2172
|
+
documentId,
|
2173
|
+
params
|
2174
|
+
});
|
2175
|
+
if (error) {
|
2176
|
+
throw error;
|
2177
|
+
}
|
2178
|
+
if (data) {
|
2179
|
+
setServerCountOfDraftRelations(data.data);
|
2180
|
+
}
|
2181
|
+
};
|
2182
|
+
fetchDraftRelationsCount();
|
2183
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
1691
2184
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1692
2185
|
if (!schema?.options?.draftAndPublish) {
|
1693
2186
|
return null;
|
1694
2187
|
}
|
2188
|
+
const performPublish = async () => {
|
2189
|
+
setSubmitting(true);
|
2190
|
+
try {
|
2191
|
+
const { errors } = await validate(true, {
|
2192
|
+
status: "published"
|
2193
|
+
});
|
2194
|
+
if (errors) {
|
2195
|
+
toggleNotification({
|
2196
|
+
type: "danger",
|
2197
|
+
message: formatMessage({
|
2198
|
+
id: "content-manager.validation.error",
|
2199
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2200
|
+
})
|
2201
|
+
});
|
2202
|
+
return;
|
2203
|
+
}
|
2204
|
+
const res = await publish(
|
2205
|
+
{
|
2206
|
+
collectionType,
|
2207
|
+
model,
|
2208
|
+
documentId,
|
2209
|
+
params
|
2210
|
+
},
|
2211
|
+
transformData(formValues)
|
2212
|
+
);
|
2213
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2214
|
+
if (id === "create") {
|
2215
|
+
navigate({
|
2216
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2217
|
+
search: rawQuery
|
2218
|
+
});
|
2219
|
+
}
|
2220
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2221
|
+
setErrors(formatValidationErrors(res.error));
|
2222
|
+
}
|
2223
|
+
} finally {
|
2224
|
+
setSubmitting(false);
|
2225
|
+
}
|
2226
|
+
};
|
2227
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2228
|
+
const enableDraftRelationsCount = false;
|
2229
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1695
2230
|
return {
|
1696
2231
|
/**
|
1697
2232
|
* Disabled when:
|
@@ -1701,52 +2236,40 @@ const PublishAction$1 = ({
|
|
1701
2236
|
* - the document is already published & not modified
|
1702
2237
|
* - the document is being created & not modified
|
1703
2238
|
* - 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
2239
|
*/
|
1707
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2240
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1708
2241
|
label: formatMessage({
|
1709
2242
|
id: "app.utils.publish",
|
1710
2243
|
defaultMessage: "Publish"
|
1711
2244
|
}),
|
1712
2245
|
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));
|
2246
|
+
await performPublish();
|
2247
|
+
},
|
2248
|
+
dialog: hasDraftRelations ? {
|
2249
|
+
type: "dialog",
|
2250
|
+
variant: "danger",
|
2251
|
+
footer: null,
|
2252
|
+
title: formatMessage({
|
2253
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2254
|
+
defaultMessage: "Confirmation"
|
2255
|
+
}),
|
2256
|
+
content: formatMessage(
|
2257
|
+
{
|
2258
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2259
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2260
|
+
},
|
2261
|
+
{
|
2262
|
+
count: totalDraftRelations
|
1742
2263
|
}
|
1743
|
-
|
1744
|
-
|
2264
|
+
),
|
2265
|
+
onConfirm: async () => {
|
2266
|
+
await performPublish();
|
1745
2267
|
}
|
1746
|
-
}
|
2268
|
+
} : void 0
|
1747
2269
|
};
|
1748
2270
|
};
|
1749
2271
|
PublishAction$1.type = "publish";
|
2272
|
+
PublishAction$1.position = "panel";
|
1750
2273
|
const UpdateAction = ({
|
1751
2274
|
activeTab,
|
1752
2275
|
documentId,
|
@@ -1759,10 +2282,6 @@ const UpdateAction = ({
|
|
1759
2282
|
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
1760
2283
|
const isCloning = cloneMatch !== null;
|
1761
2284
|
const { formatMessage } = reactIntl.useIntl();
|
1762
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1763
|
-
canCreate: canCreate2,
|
1764
|
-
canUpdate: canUpdate2
|
1765
|
-
}));
|
1766
2285
|
const { create, update, clone } = useDocumentActions();
|
1767
2286
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1768
2287
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
@@ -1779,18 +2298,18 @@ const UpdateAction = ({
|
|
1779
2298
|
* - the form is submitting
|
1780
2299
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1781
2300
|
* - the active tab is the published tab
|
1782
|
-
* - the user doesn't have the permission to create a new document
|
1783
|
-
* - the user doesn't have the permission to update the document
|
1784
2301
|
*/
|
1785
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2302
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1786
2303
|
label: formatMessage({
|
1787
|
-
id: "
|
2304
|
+
id: "global.save",
|
1788
2305
|
defaultMessage: "Save"
|
1789
2306
|
}),
|
1790
2307
|
onClick: async () => {
|
1791
2308
|
setSubmitting(true);
|
1792
2309
|
try {
|
1793
|
-
const { errors } = await validate(
|
2310
|
+
const { errors } = await validate(true, {
|
2311
|
+
status: "draft"
|
2312
|
+
});
|
1794
2313
|
if (errors) {
|
1795
2314
|
toggleNotification({
|
1796
2315
|
type: "danger",
|
@@ -1808,13 +2327,16 @@ const UpdateAction = ({
|
|
1808
2327
|
documentId: cloneMatch.params.origin,
|
1809
2328
|
params
|
1810
2329
|
},
|
1811
|
-
document
|
2330
|
+
transformData(document)
|
1812
2331
|
);
|
1813
2332
|
if ("data" in res) {
|
1814
|
-
navigate(
|
1815
|
-
|
1816
|
-
|
1817
|
-
|
2333
|
+
navigate(
|
2334
|
+
{
|
2335
|
+
pathname: `../${res.data.documentId}`,
|
2336
|
+
search: rawQuery
|
2337
|
+
},
|
2338
|
+
{ relative: "path" }
|
2339
|
+
);
|
1818
2340
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1819
2341
|
setErrors(formatValidationErrors(res.error));
|
1820
2342
|
}
|
@@ -1826,7 +2348,7 @@ const UpdateAction = ({
|
|
1826
2348
|
documentId,
|
1827
2349
|
params
|
1828
2350
|
},
|
1829
|
-
document
|
2351
|
+
transformData(document)
|
1830
2352
|
);
|
1831
2353
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1832
2354
|
setErrors(formatValidationErrors(res.error));
|
@@ -1839,13 +2361,16 @@ const UpdateAction = ({
|
|
1839
2361
|
model,
|
1840
2362
|
params
|
1841
2363
|
},
|
1842
|
-
document
|
2364
|
+
transformData(document)
|
1843
2365
|
);
|
1844
2366
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1845
|
-
navigate(
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
2367
|
+
navigate(
|
2368
|
+
{
|
2369
|
+
pathname: `../${res.data.documentId}`,
|
2370
|
+
search: rawQuery
|
2371
|
+
},
|
2372
|
+
{ replace: true, relative: "path" }
|
2373
|
+
);
|
1849
2374
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1850
2375
|
setErrors(formatValidationErrors(res.error));
|
1851
2376
|
}
|
@@ -1857,6 +2382,7 @@ const UpdateAction = ({
|
|
1857
2382
|
};
|
1858
2383
|
};
|
1859
2384
|
UpdateAction.type = "update";
|
2385
|
+
UpdateAction.position = "panel";
|
1860
2386
|
const UNPUBLISH_DRAFT_OPTIONS = {
|
1861
2387
|
KEEP: "keep",
|
1862
2388
|
DISCARD: "discard"
|
@@ -1889,7 +2415,7 @@ const UnpublishAction$1 = ({
|
|
1889
2415
|
id: "app.utils.unpublish",
|
1890
2416
|
defaultMessage: "Unpublish"
|
1891
2417
|
}),
|
1892
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2418
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1893
2419
|
onClick: async () => {
|
1894
2420
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1895
2421
|
if (!documentId) {
|
@@ -1979,6 +2505,7 @@ const UnpublishAction$1 = ({
|
|
1979
2505
|
};
|
1980
2506
|
};
|
1981
2507
|
UnpublishAction$1.type = "unpublish";
|
2508
|
+
UnpublishAction$1.position = "panel";
|
1982
2509
|
const DiscardAction = ({
|
1983
2510
|
activeTab,
|
1984
2511
|
documentId,
|
@@ -2001,7 +2528,7 @@ const DiscardAction = ({
|
|
2001
2528
|
id: "content-manager.actions.discard.label",
|
2002
2529
|
defaultMessage: "Discard changes"
|
2003
2530
|
}),
|
2004
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2531
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2005
2532
|
position: ["panel", "table-row"],
|
2006
2533
|
variant: "danger",
|
2007
2534
|
dialog: {
|
@@ -2029,11 +2556,7 @@ const DiscardAction = ({
|
|
2029
2556
|
};
|
2030
2557
|
};
|
2031
2558
|
DiscardAction.type = "discard";
|
2032
|
-
|
2033
|
-
path {
|
2034
|
-
fill: currentColor;
|
2035
|
-
}
|
2036
|
-
`;
|
2559
|
+
DiscardAction.position = "panel";
|
2037
2560
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2038
2561
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2039
2562
|
const RelativeTime = React__namespace.forwardRef(
|
@@ -2046,7 +2569,7 @@ const RelativeTime = React__namespace.forwardRef(
|
|
2046
2569
|
});
|
2047
2570
|
const unit = intervals.find((intervalUnit) => {
|
2048
2571
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2049
|
-
});
|
2572
|
+
}) ?? "seconds";
|
2050
2573
|
const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
|
2051
2574
|
const customInterval = customIntervals.find(
|
2052
2575
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2080,34 +2603,34 @@ const getDisplayName = ({
|
|
2080
2603
|
return email ?? "";
|
2081
2604
|
};
|
2082
2605
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2083
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2084
|
-
const statusVariant = status === "draft" ? "
|
2085
|
-
|
2606
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2607
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2608
|
+
const { formatMessage } = reactIntl.useIntl();
|
2609
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2610
|
+
id: `content-manager.containers.List.${status}`,
|
2611
|
+
defaultMessage: capitalise(status)
|
2612
|
+
}) }) });
|
2086
2613
|
};
|
2087
2614
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2088
2615
|
const { formatMessage } = reactIntl.useIntl();
|
2089
2616
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2617
|
+
const params = reactRouterDom.useParams();
|
2090
2618
|
const title = isCreating ? formatMessage({
|
2091
2619
|
id: "content-manager.containers.edit.title.new",
|
2092
2620
|
defaultMessage: "Create an entry"
|
2093
2621
|
}) : documentTitle;
|
2094
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2095
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2096
|
-
|
2097
|
-
designSystem.Flex,
|
2622
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2623
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2624
|
+
strapiAdmin.BackButton,
|
2098
2625
|
{
|
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
|
-
]
|
2626
|
+
fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
|
2108
2627
|
}
|
2109
2628
|
),
|
2110
|
-
|
2629
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2630
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2631
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2632
|
+
] }),
|
2633
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2111
2634
|
] });
|
2112
2635
|
};
|
2113
2636
|
const HeaderToolbar = () => {
|
@@ -2153,7 +2676,7 @@ const HeaderToolbar = () => {
|
|
2153
2676
|
meta: isCloning ? void 0 : meta,
|
2154
2677
|
collectionType
|
2155
2678
|
},
|
2156
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2679
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
|
2157
2680
|
children: (actions2) => {
|
2158
2681
|
const headerActions = actions2.filter((action) => {
|
2159
2682
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -2190,12 +2713,12 @@ const Information = ({ activeTab }) => {
|
|
2190
2713
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2191
2714
|
label: formatMessage({
|
2192
2715
|
id: "content-manager.containers.edit.information.last-published.label",
|
2193
|
-
defaultMessage: "
|
2716
|
+
defaultMessage: "Published"
|
2194
2717
|
}),
|
2195
2718
|
value: formatMessage(
|
2196
2719
|
{
|
2197
2720
|
id: "content-manager.containers.edit.information.last-published.value",
|
2198
|
-
defaultMessage: `
|
2721
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2199
2722
|
},
|
2200
2723
|
{
|
2201
2724
|
time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2208,12 +2731,12 @@ const Information = ({ activeTab }) => {
|
|
2208
2731
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2209
2732
|
label: formatMessage({
|
2210
2733
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2211
|
-
defaultMessage: "
|
2734
|
+
defaultMessage: "Updated"
|
2212
2735
|
}),
|
2213
2736
|
value: formatMessage(
|
2214
2737
|
{
|
2215
2738
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2216
|
-
defaultMessage: `
|
2739
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2217
2740
|
},
|
2218
2741
|
{
|
2219
2742
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2231,12 +2754,12 @@ const Information = ({ activeTab }) => {
|
|
2231
2754
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2232
2755
|
label: formatMessage({
|
2233
2756
|
id: "content-manager.containers.edit.information.document.label",
|
2234
|
-
defaultMessage: "
|
2757
|
+
defaultMessage: "Created"
|
2235
2758
|
}),
|
2236
2759
|
value: formatMessage(
|
2237
2760
|
{
|
2238
2761
|
id: "content-manager.containers.edit.information.document.value",
|
2239
|
-
defaultMessage: `
|
2762
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2240
2763
|
},
|
2241
2764
|
{
|
2242
2765
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2274,25 +2797,77 @@ const Information = ({ activeTab }) => {
|
|
2274
2797
|
);
|
2275
2798
|
};
|
2276
2799
|
const HeaderActions = ({ actions: actions2 }) => {
|
2277
|
-
|
2278
|
-
|
2800
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2801
|
+
const handleClick = (action) => async (e) => {
|
2802
|
+
if (!("options" in action)) {
|
2803
|
+
const { onClick = () => false, dialog, id } = action;
|
2804
|
+
const muteDialog = await onClick(e);
|
2805
|
+
if (dialog && !muteDialog) {
|
2806
|
+
e.preventDefault();
|
2807
|
+
setDialogId(id);
|
2808
|
+
}
|
2809
|
+
}
|
2810
|
+
};
|
2811
|
+
const handleClose = () => {
|
2812
|
+
setDialogId(null);
|
2813
|
+
};
|
2814
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2815
|
+
if (action.options) {
|
2279
2816
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
2280
2817
|
designSystem.SingleSelect,
|
2281
2818
|
{
|
2282
2819
|
size: "S",
|
2283
|
-
disabled: action.disabled,
|
2284
|
-
"aria-label": action.label,
|
2285
2820
|
onChange: action.onSelect,
|
2286
|
-
|
2821
|
+
"aria-label": action.label,
|
2822
|
+
...action,
|
2287
2823
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2288
2824
|
},
|
2289
2825
|
action.id
|
2290
2826
|
);
|
2291
2827
|
} else {
|
2292
|
-
|
2828
|
+
if (action.type === "icon") {
|
2829
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2830
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2831
|
+
designSystem.IconButton,
|
2832
|
+
{
|
2833
|
+
disabled: action.disabled,
|
2834
|
+
label: action.label,
|
2835
|
+
size: "S",
|
2836
|
+
onClick: handleClick(action),
|
2837
|
+
children: action.icon
|
2838
|
+
}
|
2839
|
+
),
|
2840
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2841
|
+
HeaderActionDialog,
|
2842
|
+
{
|
2843
|
+
...action.dialog,
|
2844
|
+
isOpen: dialogId === action.id,
|
2845
|
+
onClose: handleClose
|
2846
|
+
}
|
2847
|
+
) : null
|
2848
|
+
] }, action.id);
|
2849
|
+
}
|
2293
2850
|
}
|
2294
2851
|
}) });
|
2295
2852
|
};
|
2853
|
+
const HeaderActionDialog = ({
|
2854
|
+
onClose,
|
2855
|
+
onCancel,
|
2856
|
+
title,
|
2857
|
+
content: Content,
|
2858
|
+
isOpen
|
2859
|
+
}) => {
|
2860
|
+
const handleClose = async () => {
|
2861
|
+
if (onCancel) {
|
2862
|
+
await onCancel();
|
2863
|
+
}
|
2864
|
+
onClose();
|
2865
|
+
};
|
2866
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2867
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2868
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2869
|
+
] }) });
|
2870
|
+
};
|
2296
2871
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2297
2872
|
const navigate = reactRouterDom.useNavigate();
|
2298
2873
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2309,6 +2884,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2309
2884
|
};
|
2310
2885
|
};
|
2311
2886
|
ConfigureTheViewAction.type = "configure-the-view";
|
2887
|
+
ConfigureTheViewAction.position = "header";
|
2312
2888
|
const EditTheModelAction = ({ model }) => {
|
2313
2889
|
const navigate = reactRouterDom.useNavigate();
|
2314
2890
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2325,6 +2901,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2325
2901
|
};
|
2326
2902
|
};
|
2327
2903
|
EditTheModelAction.type = "edit-the-model";
|
2904
|
+
EditTheModelAction.position = "header";
|
2328
2905
|
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2329
2906
|
const navigate = reactRouterDom.useNavigate();
|
2330
2907
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2333,12 +2910,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2333
2910
|
const { delete: deleteAction } = useDocumentActions();
|
2334
2911
|
const { toggleNotification } = strapiAdmin.useNotification();
|
2335
2912
|
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2913
|
+
const isLocalized = document?.locale != null;
|
2336
2914
|
return {
|
2337
2915
|
disabled: !canDelete || !document,
|
2338
|
-
label: formatMessage(
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2916
|
+
label: formatMessage(
|
2917
|
+
{
|
2918
|
+
id: "content-manager.actions.delete.label",
|
2919
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2920
|
+
},
|
2921
|
+
{ isLocalized }
|
2922
|
+
),
|
2342
2923
|
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2343
2924
|
dialog: {
|
2344
2925
|
type: "dialog",
|
@@ -2394,403 +2975,102 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2394
2975
|
};
|
2395
2976
|
};
|
2396
2977
|
DeleteAction$1.type = "delete";
|
2978
|
+
DeleteAction$1.position = ["header", "table-row"];
|
2397
2979
|
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2398
2980
|
const Panels = () => {
|
2399
2981
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2400
2982
|
const [
|
2401
2983
|
{
|
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
|
2984
|
+
query: { status }
|
2708
2985
|
}
|
2986
|
+
] = strapiAdmin.useQueryParams({
|
2987
|
+
status: "draft"
|
2988
|
+
});
|
2989
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2990
|
+
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2991
|
+
const props = {
|
2992
|
+
activeTab: status,
|
2993
|
+
model,
|
2994
|
+
documentId: id,
|
2995
|
+
document: isCloning ? void 0 : document,
|
2996
|
+
meta: isCloning ? void 0 : meta,
|
2997
|
+
collectionType
|
2709
2998
|
};
|
2999
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3000
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3001
|
+
{
|
3002
|
+
props,
|
3003
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
3004
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
3005
|
+
}
|
3006
|
+
) });
|
2710
3007
|
};
|
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
|
-
);
|
3008
|
+
const ActionsPanel = () => {
|
3009
|
+
const { formatMessage } = reactIntl.useIntl();
|
2762
3010
|
return {
|
2763
|
-
|
2764
|
-
|
2765
|
-
|
2766
|
-
|
2767
|
-
|
2768
|
-
...schema?.pluginOptions,
|
2769
|
-
...data.contentType.options
|
2770
|
-
}
|
3011
|
+
title: formatMessage({
|
3012
|
+
id: "content-manager.containers.edit.panels.default.title",
|
3013
|
+
defaultMessage: "Entry"
|
3014
|
+
}),
|
3015
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2771
3016
|
};
|
2772
3017
|
};
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
3018
|
+
ActionsPanel.type = "actions";
|
3019
|
+
const ActionsPanelContent = () => {
|
3020
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
3021
|
+
const [
|
3022
|
+
{
|
3023
|
+
query: { status = "draft" }
|
2778
3024
|
}
|
2779
|
-
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
3025
|
+
] = strapiAdmin.useQueryParams();
|
3026
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3027
|
+
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
3028
|
+
const props = {
|
3029
|
+
activeTab: status,
|
3030
|
+
model,
|
3031
|
+
documentId: id,
|
3032
|
+
document: isCloning ? void 0 : document,
|
3033
|
+
meta: isCloning ? void 0 : meta,
|
3034
|
+
collectionType
|
3035
|
+
};
|
3036
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3037
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3038
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3039
|
+
{
|
3040
|
+
props,
|
3041
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
|
3042
|
+
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
3043
|
+
}
|
3044
|
+
),
|
3045
|
+
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3046
|
+
] });
|
2793
3047
|
};
|
3048
|
+
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
3049
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
3050
|
+
designSystem.Flex,
|
3051
|
+
{
|
3052
|
+
ref,
|
3053
|
+
tag: "aside",
|
3054
|
+
"aria-labelledby": "additional-information",
|
3055
|
+
background: "neutral0",
|
3056
|
+
borderColor: "neutral150",
|
3057
|
+
hasRadius: true,
|
3058
|
+
paddingBottom: 4,
|
3059
|
+
paddingLeft: 4,
|
3060
|
+
paddingRight: 4,
|
3061
|
+
paddingTop: 4,
|
3062
|
+
shadow: "tableShadow",
|
3063
|
+
gap: 3,
|
3064
|
+
direction: "column",
|
3065
|
+
justifyContent: "stretch",
|
3066
|
+
alignItems: "flex-start",
|
3067
|
+
children: [
|
3068
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3069
|
+
children
|
3070
|
+
]
|
3071
|
+
}
|
3072
|
+
);
|
3073
|
+
});
|
2794
3074
|
const ConfirmBulkActionDialog = ({
|
2795
3075
|
onToggleDialog,
|
2796
3076
|
isOpen = false,
|
@@ -2798,7 +3078,7 @@ const ConfirmBulkActionDialog = ({
|
|
2798
3078
|
endAction
|
2799
3079
|
}) => {
|
2800
3080
|
const { formatMessage } = reactIntl.useIntl();
|
2801
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, {
|
3081
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2802
3082
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
|
2803
3083
|
id: "app.components.ConfirmDialog.title",
|
2804
3084
|
defaultMessage: "Confirmation"
|
@@ -2829,6 +3109,7 @@ const ConfirmDialogPublishAll = ({
|
|
2829
3109
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
2830
3110
|
const { model, schema } = useDoc();
|
2831
3111
|
const [{ query }] = strapiAdmin.useQueryParams();
|
3112
|
+
const enableDraftRelationsCount = false;
|
2832
3113
|
const {
|
2833
3114
|
data: countDraftRelations = 0,
|
2834
3115
|
isLoading,
|
@@ -2840,7 +3121,7 @@ const ConfirmDialogPublishAll = ({
|
|
2840
3121
|
locale: query?.plugins?.i18n?.locale
|
2841
3122
|
},
|
2842
3123
|
{
|
2843
|
-
skip:
|
3124
|
+
skip: !enableDraftRelationsCount
|
2844
3125
|
}
|
2845
3126
|
);
|
2846
3127
|
React__namespace.useEffect(() => {
|
@@ -2919,7 +3200,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
|
2919
3200
|
)
|
2920
3201
|
);
|
2921
3202
|
} else {
|
2922
|
-
messages.push(
|
3203
|
+
messages.push(
|
3204
|
+
...formatErrorMessages(
|
3205
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3206
|
+
value,
|
3207
|
+
currentKey,
|
3208
|
+
formatMessage
|
3209
|
+
)
|
3210
|
+
);
|
2923
3211
|
}
|
2924
3212
|
} else {
|
2925
3213
|
messages.push(
|
@@ -3018,7 +3306,7 @@ const SelectedEntriesTableContent = ({
|
|
3018
3306
|
status: row.status
|
3019
3307
|
}
|
3020
3308
|
) }),
|
3021
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3309
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3022
3310
|
designSystem.IconButton,
|
3023
3311
|
{
|
3024
3312
|
tag: reactRouterDom.Link,
|
@@ -3027,23 +3315,16 @@ const SelectedEntriesTableContent = ({
|
|
3027
3315
|
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3028
3316
|
},
|
3029
3317
|
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
|
-
),
|
3318
|
+
label: formatMessage({
|
3319
|
+
id: "content-manager.bulk-publish.edit",
|
3320
|
+
defaultMessage: "Edit"
|
3321
|
+
}),
|
3042
3322
|
target: "_blank",
|
3043
3323
|
marginLeft: "auto",
|
3044
|
-
|
3324
|
+
variant: "ghost",
|
3325
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3045
3326
|
}
|
3046
|
-
) })
|
3327
|
+
) }) })
|
3047
3328
|
] }, row.id)) })
|
3048
3329
|
] });
|
3049
3330
|
};
|
@@ -3080,7 +3361,13 @@ const SelectedEntriesModalContent = ({
|
|
3080
3361
|
);
|
3081
3362
|
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3082
3363
|
if (data.length > 0 && schema) {
|
3083
|
-
const validate = createYupSchema(
|
3364
|
+
const validate = createYupSchema(
|
3365
|
+
schema.attributes,
|
3366
|
+
components,
|
3367
|
+
// Since this is the "Publish" action, the validation
|
3368
|
+
// schema must enforce the rules for published entities
|
3369
|
+
{ status: "published" }
|
3370
|
+
);
|
3084
3371
|
const validationErrors2 = {};
|
3085
3372
|
const rows2 = data.map((entry) => {
|
3086
3373
|
try {
|
@@ -3205,8 +3492,7 @@ const PublishAction = ({ documents, model }) => {
|
|
3205
3492
|
const refetchList = () => {
|
3206
3493
|
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3207
3494
|
};
|
3208
|
-
if (!showPublishButton)
|
3209
|
-
return null;
|
3495
|
+
if (!showPublishButton) return null;
|
3210
3496
|
return {
|
3211
3497
|
actionType: "publish",
|
3212
3498
|
variant: "tertiary",
|
@@ -3274,8 +3560,7 @@ const DeleteAction = ({ documents, model }) => {
|
|
3274
3560
|
selectRow([]);
|
3275
3561
|
}
|
3276
3562
|
};
|
3277
|
-
if (!hasDeletePermission)
|
3278
|
-
return null;
|
3563
|
+
if (!hasDeletePermission) return null;
|
3279
3564
|
return {
|
3280
3565
|
variant: "danger-light",
|
3281
3566
|
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
@@ -3324,8 +3609,7 @@ const UnpublishAction = ({ documents, model }) => {
|
|
3324
3609
|
}
|
3325
3610
|
};
|
3326
3611
|
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3327
|
-
if (!showUnpublishButton)
|
3328
|
-
return null;
|
3612
|
+
if (!showUnpublishButton) return null;
|
3329
3613
|
return {
|
3330
3614
|
variant: "tertiary",
|
3331
3615
|
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
@@ -3430,7 +3714,7 @@ const TableActions = ({ document }) => {
|
|
3430
3714
|
strapiAdmin.DescriptionComponentRenderer,
|
3431
3715
|
{
|
3432
3716
|
props,
|
3433
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3717
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
|
3434
3718
|
children: (actions2) => {
|
3435
3719
|
const tableRowActions = actions2.filter((action) => {
|
3436
3720
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3489,6 +3773,7 @@ const EditAction = ({ documentId }) => {
|
|
3489
3773
|
};
|
3490
3774
|
};
|
3491
3775
|
EditAction.type = "edit";
|
3776
|
+
EditAction.position = "table-row";
|
3492
3777
|
const StyledPencil = styledComponents.styled(Icons.Pencil)`
|
3493
3778
|
path {
|
3494
3779
|
fill: currentColor;
|
@@ -3541,7 +3826,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3541
3826
|
}),
|
3542
3827
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3543
3828
|
footer: ({ onClose }) => {
|
3544
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3829
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3545
3830
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3546
3831
|
id: "cancel",
|
3547
3832
|
defaultMessage: "Cancel"
|
@@ -3565,6 +3850,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3565
3850
|
};
|
3566
3851
|
};
|
3567
3852
|
CloneAction.type = "clone";
|
3853
|
+
CloneAction.position = "table-row";
|
3568
3854
|
const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
|
3569
3855
|
path {
|
3570
3856
|
fill: currentColor;
|
@@ -3582,8 +3868,7 @@ class ContentManagerPlugin {
|
|
3582
3868
|
documentActions = [
|
3583
3869
|
...DEFAULT_ACTIONS,
|
3584
3870
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3585
|
-
...DEFAULT_HEADER_ACTIONS
|
3586
|
-
HistoryAction
|
3871
|
+
...DEFAULT_HEADER_ACTIONS
|
3587
3872
|
];
|
3588
3873
|
editViewSidePanels = [ActionsPanel];
|
3589
3874
|
headerActions = [];
|
@@ -3652,7 +3937,14 @@ class ContentManagerPlugin {
|
|
3652
3937
|
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3653
3938
|
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3654
3939
|
getBulkActions: () => this.bulkActions,
|
3655
|
-
getDocumentActions: () =>
|
3940
|
+
getDocumentActions: (position) => {
|
3941
|
+
if (position) {
|
3942
|
+
return this.documentActions.filter(
|
3943
|
+
(action) => action.position == void 0 || [action.position].flat().includes(position)
|
3944
|
+
);
|
3945
|
+
}
|
3946
|
+
return this.documentActions;
|
3947
|
+
},
|
3656
3948
|
getEditViewSidePanels: () => this.editViewSidePanels,
|
3657
3949
|
getHeaderActions: () => this.headerActions
|
3658
3950
|
}
|
@@ -3662,16 +3954,71 @@ class ContentManagerPlugin {
|
|
3662
3954
|
const getPrintableType = (value) => {
|
3663
3955
|
const nativeType = typeof value;
|
3664
3956
|
if (nativeType === "object") {
|
3665
|
-
if (value === null)
|
3666
|
-
|
3667
|
-
if (Array.isArray(value))
|
3668
|
-
return "array";
|
3957
|
+
if (value === null) return "null";
|
3958
|
+
if (Array.isArray(value)) return "array";
|
3669
3959
|
if (value instanceof Object && value.constructor.name !== "Object") {
|
3670
3960
|
return value.constructor.name;
|
3671
3961
|
}
|
3672
3962
|
}
|
3673
3963
|
return nativeType;
|
3674
3964
|
};
|
3965
|
+
const HistoryAction = ({ model, document }) => {
|
3966
|
+
const { formatMessage } = reactIntl.useIntl();
|
3967
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3968
|
+
const navigate = reactRouterDom.useNavigate();
|
3969
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
3970
|
+
const { pathname } = reactRouterDom.useLocation();
|
3971
|
+
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
3972
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3973
|
+
return null;
|
3974
|
+
}
|
3975
|
+
const handleOnClick = () => {
|
3976
|
+
const destination = { pathname: "history", search: pluginsQueryParams };
|
3977
|
+
trackUsage("willNavigate", {
|
3978
|
+
from: pathname,
|
3979
|
+
to: `${pathname}/${destination.pathname}`
|
3980
|
+
});
|
3981
|
+
navigate(destination);
|
3982
|
+
};
|
3983
|
+
return {
|
3984
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
3985
|
+
label: formatMessage({
|
3986
|
+
id: "content-manager.history.document-action",
|
3987
|
+
defaultMessage: "Content History"
|
3988
|
+
}),
|
3989
|
+
onClick: handleOnClick,
|
3990
|
+
disabled: (
|
3991
|
+
/**
|
3992
|
+
* The user is creating a new document.
|
3993
|
+
* It hasn't been saved yet, so there's no history to go to
|
3994
|
+
*/
|
3995
|
+
!document || /**
|
3996
|
+
* The document has been created but the current dimension has never been saved.
|
3997
|
+
* For example, the user is creating a new locale in an existing document,
|
3998
|
+
* so there's no history for the document in that locale
|
3999
|
+
*/
|
4000
|
+
!document.id || /**
|
4001
|
+
* History is only available for content types created by the user.
|
4002
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
4003
|
+
* which start with `admin::` or `plugin::`
|
4004
|
+
*/
|
4005
|
+
!model.startsWith("api::")
|
4006
|
+
),
|
4007
|
+
position: "header"
|
4008
|
+
};
|
4009
|
+
};
|
4010
|
+
HistoryAction.type = "history";
|
4011
|
+
HistoryAction.position = "header";
|
4012
|
+
const historyAdmin = {
|
4013
|
+
bootstrap(app) {
|
4014
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
4015
|
+
addDocumentAction((actions2) => {
|
4016
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
4017
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
4018
|
+
return actions2;
|
4019
|
+
});
|
4020
|
+
}
|
4021
|
+
};
|
3675
4022
|
const initialState = {
|
3676
4023
|
collectionTypeLinks: [],
|
3677
4024
|
components: [],
|
@@ -3708,6 +4055,90 @@ const { setInitialData } = actions;
|
|
3708
4055
|
const reducer = toolkit.combineReducers({
|
3709
4056
|
app: reducer$1
|
3710
4057
|
});
|
4058
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4059
|
+
endpoints: (builder) => ({
|
4060
|
+
getPreviewUrl: builder.query({
|
4061
|
+
query({ query, params }) {
|
4062
|
+
return {
|
4063
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4064
|
+
method: "GET",
|
4065
|
+
config: {
|
4066
|
+
params: query
|
4067
|
+
}
|
4068
|
+
};
|
4069
|
+
}
|
4070
|
+
})
|
4071
|
+
})
|
4072
|
+
});
|
4073
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4074
|
+
const ConditionalTooltip = ({ isShown, label, children }) => {
|
4075
|
+
if (isShown) {
|
4076
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { label, children });
|
4077
|
+
}
|
4078
|
+
return children;
|
4079
|
+
};
|
4080
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4081
|
+
const { formatMessage } = reactIntl.useIntl();
|
4082
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
4083
|
+
const { pathname } = reactRouterDom.useLocation();
|
4084
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
4085
|
+
const isModified = strapiAdmin.useForm("PreviewSidePanel", (state) => state.modified);
|
4086
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4087
|
+
params: {
|
4088
|
+
contentType: model
|
4089
|
+
},
|
4090
|
+
query: {
|
4091
|
+
documentId,
|
4092
|
+
locale: document?.locale,
|
4093
|
+
status: document?.status
|
4094
|
+
}
|
4095
|
+
});
|
4096
|
+
if (!data?.data?.url || error) {
|
4097
|
+
return null;
|
4098
|
+
}
|
4099
|
+
const trackNavigation = () => {
|
4100
|
+
const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
|
4101
|
+
trackUsage("willNavigate", { from: pathname, to: destinationPathname });
|
4102
|
+
};
|
4103
|
+
return {
|
4104
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4105
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
|
4106
|
+
ConditionalTooltip,
|
4107
|
+
{
|
4108
|
+
label: formatMessage({
|
4109
|
+
id: "content-manager.preview.panel.button-disabled-tooltip",
|
4110
|
+
defaultMessage: "Please save to open the preview"
|
4111
|
+
}),
|
4112
|
+
isShown: isModified,
|
4113
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
4114
|
+
designSystem.Button,
|
4115
|
+
{
|
4116
|
+
variant: "tertiary",
|
4117
|
+
tag: reactRouterDom.Link,
|
4118
|
+
to: { pathname: "preview", search: qs.stringify(query, { encode: false }) },
|
4119
|
+
onClick: trackNavigation,
|
4120
|
+
flex: "auto",
|
4121
|
+
disabled: isModified,
|
4122
|
+
children: formatMessage({
|
4123
|
+
id: "content-manager.preview.panel.button",
|
4124
|
+
defaultMessage: "Open preview"
|
4125
|
+
})
|
4126
|
+
}
|
4127
|
+
)
|
4128
|
+
}
|
4129
|
+
) })
|
4130
|
+
};
|
4131
|
+
};
|
4132
|
+
const FEATURE_ID = "preview";
|
4133
|
+
const previewAdmin = {
|
4134
|
+
bootstrap(app) {
|
4135
|
+
if (!window.strapi.future.isEnabled(FEATURE_ID)) {
|
4136
|
+
return;
|
4137
|
+
}
|
4138
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4139
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4140
|
+
}
|
4141
|
+
};
|
3711
4142
|
const index = {
|
3712
4143
|
register(app) {
|
3713
4144
|
const cm = new ContentManagerPlugin();
|
@@ -3727,7 +4158,7 @@ const index = {
|
|
3727
4158
|
app.router.addRoute({
|
3728
4159
|
path: "content-manager/*",
|
3729
4160
|
lazy: async () => {
|
3730
|
-
const { Layout } = await Promise.resolve().then(() => require("./layout-
|
4161
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-nBPDlXjr.js"));
|
3731
4162
|
return {
|
3732
4163
|
Component: Layout
|
3733
4164
|
};
|
@@ -3736,10 +4167,18 @@ const index = {
|
|
3736
4167
|
});
|
3737
4168
|
app.registerPlugin(cm.config);
|
3738
4169
|
},
|
4170
|
+
bootstrap(app) {
|
4171
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4172
|
+
historyAdmin.bootstrap(app);
|
4173
|
+
}
|
4174
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4175
|
+
previewAdmin.bootstrap(app);
|
4176
|
+
}
|
4177
|
+
},
|
3739
4178
|
async registerTrads({ locales }) {
|
3740
4179
|
const importedTrads = await Promise.all(
|
3741
4180
|
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-
|
4181
|
+
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
4182
|
return {
|
3744
4183
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3745
4184
|
locale
|
@@ -3757,6 +4196,7 @@ const index = {
|
|
3757
4196
|
};
|
3758
4197
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
3759
4198
|
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4199
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3760
4200
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3761
4201
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3762
4202
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3784,6 +4224,7 @@ exports.getMainField = getMainField;
|
|
3784
4224
|
exports.getTranslation = getTranslation;
|
3785
4225
|
exports.index = index;
|
3786
4226
|
exports.setInitialData = setInitialData;
|
4227
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3787
4228
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3788
4229
|
exports.useDoc = useDoc;
|
3789
4230
|
exports.useDocLayout = useDocLayout;
|
@@ -3795,5 +4236,6 @@ exports.useGetAllContentTypeSettingsQuery = useGetAllContentTypeSettingsQuery;
|
|
3795
4236
|
exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
3796
4237
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3797
4238
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
4239
|
+
exports.useGetPreviewUrlQuery = useGetPreviewUrlQuery;
|
3798
4240
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3799
|
-
//# sourceMappingURL=index-
|
4241
|
+
//# sourceMappingURL=index-BN1pPa5v.js.map
|