@strapi/content-manager 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813 → 0.0.0-experimental.eba25ec571b091c6bde1104eb6c753debdf15462
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-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
- package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
- package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs → ComponentConfigurationPage-BaJMOQyq.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs.map → ComponentConfigurationPage-BaJMOQyq.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js → ComponentConfigurationPage-N-CTtgQa.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js.map → ComponentConfigurationPage-N-CTtgQa.js.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-BXdiCGQp.js} +8 -2
- package/dist/_chunks/ComponentIcon-BXdiCGQp.js.map +1 -0
- package/dist/_chunks/{ComponentIcon-BOFnK76n.mjs → ComponentIcon-u4bIXTFY.mjs} +9 -3
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -0
- package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js → EditConfigurationPage-BHkjAbxH.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js.map → EditConfigurationPage-BHkjAbxH.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs → EditConfigurationPage-CKK-5LfX.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs.map → EditConfigurationPage-CKK-5LfX.mjs.map} +1 -1
- package/dist/_chunks/EditViewPage-B11aeMcf.mjs +254 -0
- package/dist/_chunks/EditViewPage-B11aeMcf.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-DvNpQkam.js → EditViewPage-QPUftxUd.js} +101 -52
- package/dist/_chunks/EditViewPage-QPUftxUd.js.map +1 -0
- package/dist/_chunks/{Field-6gvGdPBV.mjs → Field-Bj_RgtGo.mjs} +1077 -814
- package/dist/_chunks/Field-Bj_RgtGo.mjs.map +1 -0
- package/dist/_chunks/{Field-DmVKIAOo.js → Field-DUK83cfh.js} +1121 -859
- package/dist/_chunks/Field-DUK83cfh.js.map +1 -0
- package/dist/_chunks/{Form-CPZC9vWa.js → Form-DHmBRlHd.js} +66 -46
- package/dist/_chunks/Form-DHmBRlHd.js.map +1 -0
- package/dist/_chunks/{Form-DW6K1IH-.mjs → Form-DLMSoXV7.mjs} +66 -45
- package/dist/_chunks/Form-DLMSoXV7.mjs.map +1 -0
- package/dist/_chunks/{History-Dmr9fmUA.mjs → History-CfCSNlG9.mjs} +181 -144
- package/dist/_chunks/History-CfCSNlG9.mjs.map +1 -0
- package/dist/_chunks/{History-DeAPlvtv.js → History-Di3zm4HT.js} +181 -145
- package/dist/_chunks/History-Di3zm4HT.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DhwvYcNv.mjs → ListConfigurationPage-0mtv_iqk.mjs} +67 -56
- package/dist/_chunks/ListConfigurationPage-0mtv_iqk.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DPCwW5Vr.js → ListConfigurationPage-Cq361KIt.js} +70 -60
- package/dist/_chunks/ListConfigurationPage-Cq361KIt.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BtAwuYLE.mjs → ListViewPage-BxLVROX8.mjs} +175 -159
- package/dist/_chunks/ListViewPage-BxLVROX8.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-5ySZ-VUs.js → ListViewPage-DFDcG8gM.js} +178 -162
- package/dist/_chunks/ListViewPage-DFDcG8gM.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DSPxnxxp.mjs → NoContentTypePage-BRfDd67_.mjs} +3 -3
- package/dist/_chunks/NoContentTypePage-BRfDd67_.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DOC_yWOf.js → NoContentTypePage-BSyvnDZZ.js} +3 -3
- package/dist/_chunks/NoContentTypePage-BSyvnDZZ.js.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs → NoPermissionsPage-CV9V8KWa.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs.map → NoPermissionsPage-CV9V8KWa.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js → NoPermissionsPage-DyLphsn_.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js.map → NoPermissionsPage-DyLphsn_.js.map} +1 -1
- package/dist/_chunks/Preview-C_B1nx3g.mjs +272 -0
- package/dist/_chunks/Preview-C_B1nx3g.mjs.map +1 -0
- package/dist/_chunks/Preview-D_3aO6Ly.js +291 -0
- package/dist/_chunks/Preview-D_3aO6Ly.js.map +1 -0
- package/dist/_chunks/{Relations-J8cscLlR.mjs → Relations-C6pwmDXh.mjs} +135 -89
- package/dist/_chunks/Relations-C6pwmDXh.mjs.map +1 -0
- package/dist/_chunks/{Relations-CgWtgnPe.js → Relations-Cne2AlrL.js} +138 -93
- package/dist/_chunks/Relations-Cne2AlrL.js.map +1 -0
- package/dist/_chunks/{en-MBPul9Su.mjs → en-DhFUjrNW.mjs} +37 -18
- package/dist/_chunks/{en-MBPul9Su.mjs.map → en-DhFUjrNW.mjs.map} +1 -1
- package/dist/_chunks/{en-C-V1_90f.js → en-Ic0kXjxB.js} +37 -18
- package/dist/_chunks/{en-C-V1_90f.js.map → en-Ic0kXjxB.js.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/{index-CwRRo1V9.mjs → index-BpxR3En4.mjs} +1835 -824
- package/dist/_chunks/index-BpxR3En4.mjs.map +1 -0
- package/dist/_chunks/{index-C6AH2hEl.js → index-T-aWjbj2.js} +1788 -777
- package/dist/_chunks/index-T-aWjbj2.js.map +1 -0
- package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
- package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
- package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
- package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
- package/dist/_chunks/{layout-B_SXLhqf.js → layout-BEuNwv-F.js} +45 -29
- package/dist/_chunks/layout-BEuNwv-F.js.map +1 -0
- package/dist/_chunks/{layout-jIDzX0Fp.mjs → layout-DhMZ_lDx.mjs} +45 -27
- package/dist/_chunks/layout-DhMZ_lDx.mjs.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-CuvIgCqI.mjs → relations-BdnxoX6f.mjs} +6 -7
- package/dist/_chunks/relations-BdnxoX6f.mjs.map +1 -0
- package/dist/_chunks/{relations-iBMa_OFG.js → relations-kLcuobLk.js} +6 -7
- package/dist/_chunks/relations-kLcuobLk.js.map +1 -0
- package/dist/_chunks/useDebounce-CtcjDB3L.js +28 -0
- 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-DdHgKsqq.mjs.map +1 -1
- package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
- package/dist/admin/index.js +3 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +9 -7
- package/dist/admin/src/components/ComponentIcon.d.ts +6 -3
- package/dist/admin/src/content-manager.d.ts +3 -3
- package/dist/admin/src/exports.d.ts +2 -1
- package/dist/admin/src/history/components/VersionInputRenderer.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 +37 -9
- package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
- package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
- package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
- package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -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 +11 -4
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +30 -18
- package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.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 +16 -53
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
- package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
- package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
- package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
- 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 +2 -3
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +5 -5
- package/dist/admin/src/services/documents.d.ts +31 -20
- package/dist/admin/src/services/init.d.ts +2 -2
- package/dist/admin/src/services/relations.d.ts +3 -3
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/api.d.ts +4 -18
- package/dist/admin/src/utils/validation.d.ts +5 -7
- package/dist/server/index.js +852 -436
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +859 -443
- 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/single-types.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 +22 -0
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/dimensions.d.ts +11 -0
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/index.d.ts +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 +21 -42
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/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 +13 -12
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +14 -35
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +21 -42
- 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 +8 -1
- 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 +17 -7
- 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/contracts/relations.d.ts +2 -2
- package/dist/shared/contracts/relations.d.ts.map +1 -1
- 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 +19 -20
- package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
- package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
- package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
- package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-DDS6H9HO.mjs +0 -203
- package/dist/_chunks/EditViewPage-DDS6H9HO.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-DvNpQkam.js.map +0 -1
- package/dist/_chunks/Field-6gvGdPBV.mjs.map +0 -1
- package/dist/_chunks/Field-DmVKIAOo.js.map +0 -1
- package/dist/_chunks/Form-CPZC9vWa.js.map +0 -1
- package/dist/_chunks/Form-DW6K1IH-.mjs.map +0 -1
- package/dist/_chunks/History-DeAPlvtv.js.map +0 -1
- package/dist/_chunks/History-Dmr9fmUA.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DPCwW5Vr.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DhwvYcNv.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-5ySZ-VUs.js.map +0 -1
- package/dist/_chunks/ListViewPage-BtAwuYLE.mjs.map +0 -1
- package/dist/_chunks/NoContentTypePage-DOC_yWOf.js.map +0 -1
- package/dist/_chunks/NoContentTypePage-DSPxnxxp.mjs.map +0 -1
- package/dist/_chunks/Relations-CgWtgnPe.js.map +0 -1
- package/dist/_chunks/Relations-J8cscLlR.mjs.map +0 -1
- package/dist/_chunks/index-C6AH2hEl.js.map +0 -1
- package/dist/_chunks/index-CwRRo1V9.mjs.map +0 -1
- package/dist/_chunks/layout-B_SXLhqf.js.map +0 -1
- package/dist/_chunks/layout-jIDzX0Fp.mjs.map +0 -1
- package/dist/_chunks/relations-CuvIgCqI.mjs.map +0 -1
- package/dist/_chunks/relations-iBMa_OFG.js.map +0 -1
- package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
- package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
- package/dist/_chunks/urls-DzZya_gm.js +0 -6
- package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
- package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
- package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
- package/strapi-server.js +0 -3
@@ -2,15 +2,14 @@
|
|
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");
|
10
|
-
const
|
7
|
+
const mapValues = require("lodash/fp/mapValues");
|
8
|
+
const reactIntl = require("react-intl");
|
9
|
+
const reactRouterDom = require("react-router-dom");
|
10
|
+
const styledComponents = require("styled-components");
|
11
11
|
const yup = require("yup");
|
12
|
-
const
|
13
|
-
const axios = require("axios");
|
12
|
+
const qs = require("qs");
|
14
13
|
const pipe = require("lodash/fp/pipe");
|
15
14
|
const dateFns = require("date-fns");
|
16
15
|
const toolkit = require("@reduxjs/toolkit");
|
@@ -34,7 +33,7 @@ function _interopNamespace(e) {
|
|
34
33
|
return Object.freeze(n);
|
35
34
|
}
|
36
35
|
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
37
|
-
const
|
36
|
+
const mapValues__default = /* @__PURE__ */ _interopDefault(mapValues);
|
38
37
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
39
38
|
const pipe__default = /* @__PURE__ */ _interopDefault(pipe);
|
40
39
|
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
@@ -73,42 +72,6 @@ const useInjectionZone = (area) => {
|
|
73
72
|
const [page, position] = area.split(".");
|
74
73
|
return contentManagerPlugin.getInjectedComponents(page, position);
|
75
74
|
};
|
76
|
-
const HistoryAction = ({ model, document }) => {
|
77
|
-
const { formatMessage } = reactIntl.useIntl();
|
78
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
79
|
-
const navigate = reactRouterDom.useNavigate();
|
80
|
-
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
81
|
-
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
82
|
-
return null;
|
83
|
-
}
|
84
|
-
return {
|
85
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
86
|
-
label: formatMessage({
|
87
|
-
id: "content-manager.history.document-action",
|
88
|
-
defaultMessage: "Content History"
|
89
|
-
}),
|
90
|
-
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
91
|
-
disabled: (
|
92
|
-
/**
|
93
|
-
* The user is creating a new document.
|
94
|
-
* It hasn't been saved yet, so there's no history to go to
|
95
|
-
*/
|
96
|
-
!document || /**
|
97
|
-
* The document has been created but the current dimension has never been saved.
|
98
|
-
* For example, the user is creating a new locale in an existing document,
|
99
|
-
* so there's no history for the document in that locale
|
100
|
-
*/
|
101
|
-
!document.id || /**
|
102
|
-
* History is only available for content types created by the user.
|
103
|
-
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
104
|
-
* which start with `admin::` or `plugin::`
|
105
|
-
*/
|
106
|
-
!model.startsWith("api::")
|
107
|
-
),
|
108
|
-
position: "header"
|
109
|
-
};
|
110
|
-
};
|
111
|
-
HistoryAction.type = "history";
|
112
75
|
const ID = "id";
|
113
76
|
const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
|
114
77
|
const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
|
@@ -160,6 +123,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
160
123
|
if (!slug) {
|
161
124
|
throw new Error("Cannot find the slug param in the URL");
|
162
125
|
}
|
126
|
+
const [{ rawQuery }] = strapiAdmin.useQueryParams();
|
163
127
|
const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
|
164
128
|
const contentTypePermissions = React__namespace.useMemo(() => {
|
165
129
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -170,7 +134,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
170
134
|
return { ...acc, [action]: [permission] };
|
171
135
|
}, {});
|
172
136
|
}, [slug, userPermissions]);
|
173
|
-
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
137
|
+
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
138
|
+
contentTypePermissions,
|
139
|
+
permissions ?? void 0,
|
140
|
+
// TODO: useRBAC context should be typed and built differently
|
141
|
+
// We are passing raw query as context to the hook so that it can
|
142
|
+
// rely on the locale provided from DocumentRBAC for its permission calculations.
|
143
|
+
rawQuery
|
144
|
+
);
|
174
145
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
175
146
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
176
147
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -179,9 +150,8 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
179
150
|
const name = removeNumericalStrings(fieldName.split("."));
|
180
151
|
const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
|
181
152
|
if (fieldType === "component") {
|
182
|
-
|
183
|
-
|
184
|
-
return field.includes(fieldName);
|
153
|
+
return componentFieldNames.some((field) => {
|
154
|
+
return field.includes(name.join("."));
|
185
155
|
});
|
186
156
|
}
|
187
157
|
if (name.length > 1) {
|
@@ -211,89 +181,20 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
|
|
211
181
|
(field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
|
212
182
|
);
|
213
183
|
const removeNumericalStrings = (arr) => arr.filter((item) => isNaN(Number(item)));
|
214
|
-
const
|
215
|
-
|
216
|
-
return query;
|
217
|
-
const { plugins: _, ...validQueryParams } = {
|
218
|
-
...query,
|
219
|
-
...Object.values(query?.plugins ?? {}).reduce(
|
220
|
-
(acc, current) => Object.assign(acc, current),
|
221
|
-
{}
|
222
|
-
)
|
223
|
-
};
|
224
|
-
if ("_q" in validQueryParams) {
|
225
|
-
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
226
|
-
}
|
227
|
-
return validQueryParams;
|
228
|
-
};
|
229
|
-
const axiosBaseQuery = () => async (query, { signal }) => {
|
230
|
-
try {
|
231
|
-
const { get, post, del, put } = strapiAdmin.getFetchClient();
|
232
|
-
if (typeof query === "string") {
|
233
|
-
const result = await get(query, { signal });
|
234
|
-
return { data: result.data };
|
235
|
-
} else {
|
236
|
-
const { url, method = "GET", data, config } = query;
|
237
|
-
if (method === "POST") {
|
238
|
-
const result2 = await post(url, data, { ...config, signal });
|
239
|
-
return { data: result2.data };
|
240
|
-
}
|
241
|
-
if (method === "DELETE") {
|
242
|
-
const result2 = await del(url, { ...config, signal });
|
243
|
-
return { data: result2.data };
|
244
|
-
}
|
245
|
-
if (method === "PUT") {
|
246
|
-
const result2 = await put(url, data, { ...config, signal });
|
247
|
-
return { data: result2.data };
|
248
|
-
}
|
249
|
-
const result = await get(url, { ...config, signal });
|
250
|
-
return { data: result.data };
|
251
|
-
}
|
252
|
-
} catch (err) {
|
253
|
-
if (axios.isAxiosError(err)) {
|
254
|
-
if (typeof err.response?.data === "object" && err.response?.data !== null && "error" in err.response?.data) {
|
255
|
-
return { data: void 0, error: err.response?.data.error };
|
256
|
-
} else {
|
257
|
-
return {
|
258
|
-
data: void 0,
|
259
|
-
error: {
|
260
|
-
name: "UnknownError",
|
261
|
-
message: "There was an unknown error response from the API",
|
262
|
-
details: err.response?.data,
|
263
|
-
status: err.response?.status
|
264
|
-
}
|
265
|
-
};
|
266
|
-
}
|
267
|
-
}
|
268
|
-
const error = err;
|
269
|
-
return {
|
270
|
-
data: void 0,
|
271
|
-
error: {
|
272
|
-
name: error.name,
|
273
|
-
message: error.message,
|
274
|
-
stack: error.stack
|
275
|
-
}
|
276
|
-
};
|
277
|
-
}
|
278
|
-
};
|
279
|
-
const isBaseQueryError = (error) => {
|
280
|
-
return error.name !== void 0;
|
281
|
-
};
|
282
|
-
const contentManagerApi = react.createApi({
|
283
|
-
reducerPath: "contentManagerApi",
|
284
|
-
baseQuery: axiosBaseQuery(),
|
285
|
-
tagTypes: [
|
184
|
+
const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
185
|
+
addTagTypes: [
|
286
186
|
"ComponentConfiguration",
|
287
187
|
"ContentTypesConfiguration",
|
288
188
|
"ContentTypeSettings",
|
289
189
|
"Document",
|
290
190
|
"InitialData",
|
291
191
|
"HistoryVersion",
|
292
|
-
"Relations"
|
293
|
-
|
294
|
-
|
192
|
+
"Relations",
|
193
|
+
"UidAvailability"
|
194
|
+
]
|
295
195
|
});
|
296
196
|
const documentApi = contentManagerApi.injectEndpoints({
|
197
|
+
overrideExisting: true,
|
297
198
|
endpoints: (builder) => ({
|
298
199
|
autoCloneDocument: builder.mutation({
|
299
200
|
query: ({ model, sourceId, query }) => ({
|
@@ -303,7 +204,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
303
204
|
params: query
|
304
205
|
}
|
305
206
|
}),
|
306
|
-
invalidatesTags: (_result,
|
207
|
+
invalidatesTags: (_result, error, { model }) => {
|
208
|
+
if (error) {
|
209
|
+
return [];
|
210
|
+
}
|
211
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
212
|
+
}
|
307
213
|
}),
|
308
214
|
cloneDocument: builder.mutation({
|
309
215
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -314,7 +220,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
314
220
|
params
|
315
221
|
}
|
316
222
|
}),
|
317
|
-
invalidatesTags: (_result, _error, { model }) => [
|
223
|
+
invalidatesTags: (_result, _error, { model }) => [
|
224
|
+
{ type: "Document", id: `${model}_LIST` },
|
225
|
+
{ type: "UidAvailability", id: model }
|
226
|
+
]
|
318
227
|
}),
|
319
228
|
/**
|
320
229
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -331,7 +240,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
331
240
|
}),
|
332
241
|
invalidatesTags: (result, _error, { model }) => [
|
333
242
|
{ type: "Document", id: `${model}_LIST` },
|
334
|
-
"Relations"
|
243
|
+
"Relations",
|
244
|
+
{ type: "UidAvailability", id: model }
|
335
245
|
]
|
336
246
|
}),
|
337
247
|
deleteDocument: builder.mutation({
|
@@ -347,12 +257,15 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
347
257
|
]
|
348
258
|
}),
|
349
259
|
deleteManyDocuments: builder.mutation({
|
350
|
-
query: ({ model, ...body }) => ({
|
260
|
+
query: ({ model, params, ...body }) => ({
|
351
261
|
url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
|
352
262
|
method: "POST",
|
353
|
-
data: body
|
263
|
+
data: body,
|
264
|
+
config: {
|
265
|
+
params
|
266
|
+
}
|
354
267
|
}),
|
355
|
-
invalidatesTags: (_res, _error, { model
|
268
|
+
invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
|
356
269
|
}),
|
357
270
|
discardDocument: builder.mutation({
|
358
271
|
query: ({ collectionType, model, documentId, params }) => ({
|
@@ -369,7 +282,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
369
282
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
370
283
|
},
|
371
284
|
{ type: "Document", id: `${model}_LIST` },
|
372
|
-
"Relations"
|
285
|
+
"Relations",
|
286
|
+
{ type: "UidAvailability", id: model }
|
373
287
|
];
|
374
288
|
}
|
375
289
|
}),
|
@@ -382,11 +296,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
382
296
|
url: `/content-manager/collection-types/${model}`,
|
383
297
|
method: "GET",
|
384
298
|
config: {
|
385
|
-
params
|
299
|
+
params: qs.stringify(params, { encode: true })
|
386
300
|
}
|
387
301
|
}),
|
388
302
|
providesTags: (result, _error, arg) => {
|
389
303
|
return [
|
304
|
+
{ type: "Document", id: `ALL_LIST` },
|
390
305
|
{ type: "Document", id: `${arg.model}_LIST` },
|
391
306
|
...result?.results.map(({ documentId }) => ({
|
392
307
|
type: "Document",
|
@@ -425,6 +340,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
425
340
|
{
|
426
341
|
type: "Document",
|
427
342
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
343
|
+
},
|
344
|
+
// Make it easy to invalidate all individual documents queries for a model
|
345
|
+
{
|
346
|
+
type: "Document",
|
347
|
+
id: `${model}_ALL_ITEMS`
|
428
348
|
}
|
429
349
|
];
|
430
350
|
}
|
@@ -463,10 +383,13 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
463
383
|
}
|
464
384
|
}),
|
465
385
|
publishManyDocuments: builder.mutation({
|
466
|
-
query: ({ model, ...body }) => ({
|
386
|
+
query: ({ model, params, ...body }) => ({
|
467
387
|
url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
|
468
388
|
method: "POST",
|
469
|
-
data: body
|
389
|
+
data: body,
|
390
|
+
config: {
|
391
|
+
params
|
392
|
+
}
|
470
393
|
}),
|
471
394
|
invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
|
472
395
|
}),
|
@@ -485,8 +408,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
485
408
|
type: "Document",
|
486
409
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
487
410
|
},
|
488
|
-
"Relations"
|
411
|
+
"Relations",
|
412
|
+
{ type: "UidAvailability", id: model }
|
489
413
|
];
|
414
|
+
},
|
415
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
416
|
+
const patchResult = dispatch(
|
417
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
418
|
+
Object.assign(draft.data, data);
|
419
|
+
})
|
420
|
+
);
|
421
|
+
try {
|
422
|
+
await queryFulfilled;
|
423
|
+
} catch {
|
424
|
+
patchResult.undo();
|
425
|
+
}
|
490
426
|
}
|
491
427
|
}),
|
492
428
|
unpublishDocument: builder.mutation({
|
@@ -508,10 +444,13 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
508
444
|
}
|
509
445
|
}),
|
510
446
|
unpublishManyDocuments: builder.mutation({
|
511
|
-
query: ({ model, ...body }) => ({
|
447
|
+
query: ({ model, params, ...body }) => ({
|
512
448
|
url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
|
513
449
|
method: "POST",
|
514
|
-
data: body
|
450
|
+
data: body,
|
451
|
+
config: {
|
452
|
+
params
|
453
|
+
}
|
515
454
|
}),
|
516
455
|
invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
|
517
456
|
})
|
@@ -535,20 +474,54 @@ const {
|
|
535
474
|
useUnpublishDocumentMutation,
|
536
475
|
useUnpublishManyDocumentsMutation
|
537
476
|
} = documentApi;
|
538
|
-
const
|
477
|
+
const buildValidParams = (query) => {
|
478
|
+
if (!query)
|
479
|
+
return query;
|
480
|
+
const { plugins: _, ...validQueryParams } = {
|
481
|
+
...query,
|
482
|
+
...Object.values(query?.plugins ?? {}).reduce(
|
483
|
+
(acc, current) => Object.assign(acc, current),
|
484
|
+
{}
|
485
|
+
)
|
486
|
+
};
|
487
|
+
return validQueryParams;
|
488
|
+
};
|
489
|
+
const isBaseQueryError = (error) => {
|
490
|
+
return error.name !== void 0;
|
491
|
+
};
|
492
|
+
const arrayValidator = (attribute, options) => ({
|
493
|
+
message: strapiAdmin.translatedErrors.required,
|
494
|
+
test(value) {
|
495
|
+
if (options.status === "draft") {
|
496
|
+
return true;
|
497
|
+
}
|
498
|
+
if (!attribute.required) {
|
499
|
+
return true;
|
500
|
+
}
|
501
|
+
if (!value) {
|
502
|
+
return false;
|
503
|
+
}
|
504
|
+
if (Array.isArray(value) && value.length === 0) {
|
505
|
+
return false;
|
506
|
+
}
|
507
|
+
return true;
|
508
|
+
}
|
509
|
+
});
|
510
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
539
511
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
540
512
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
541
513
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
542
514
|
return acc;
|
543
515
|
}
|
544
516
|
const validations = [
|
517
|
+
addNullableValidation,
|
545
518
|
addRequiredValidation,
|
546
519
|
addMinLengthValidation,
|
547
520
|
addMaxLengthValidation,
|
548
521
|
addMinValidation,
|
549
522
|
addMaxValidation,
|
550
523
|
addRegexValidation
|
551
|
-
].map((fn) => fn(attribute));
|
524
|
+
].map((fn) => fn(attribute, options));
|
552
525
|
const transformSchema = pipe__default.default(...validations);
|
553
526
|
switch (attribute.type) {
|
554
527
|
case "component": {
|
@@ -558,12 +531,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
558
531
|
...acc,
|
559
532
|
[name]: transformSchema(
|
560
533
|
yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
|
561
|
-
)
|
534
|
+
).test(arrayValidator(attribute, options))
|
562
535
|
};
|
563
536
|
} else {
|
564
537
|
return {
|
565
538
|
...acc,
|
566
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
539
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
567
540
|
};
|
568
541
|
}
|
569
542
|
}
|
@@ -574,24 +547,42 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
574
547
|
yup__namespace.array().of(
|
575
548
|
yup__namespace.lazy(
|
576
549
|
(data) => {
|
577
|
-
const
|
578
|
-
|
550
|
+
const attributes3 = components?.[data?.__component]?.attributes;
|
551
|
+
const validation = yup__namespace.object().shape({
|
579
552
|
__component: yup__namespace.string().required().oneOf(Object.keys(components))
|
580
|
-
}).nullable(false)
|
553
|
+
}).nullable(false);
|
554
|
+
if (!attributes3) {
|
555
|
+
return validation;
|
556
|
+
}
|
557
|
+
return validation.concat(createModelSchema(attributes3));
|
581
558
|
}
|
582
559
|
)
|
583
560
|
)
|
584
|
-
)
|
561
|
+
).test(arrayValidator(attribute, options))
|
585
562
|
};
|
586
563
|
case "relation":
|
587
564
|
return {
|
588
565
|
...acc,
|
589
566
|
[name]: transformSchema(
|
590
|
-
yup__namespace.
|
591
|
-
|
592
|
-
|
593
|
-
})
|
594
|
-
|
567
|
+
yup__namespace.lazy((value) => {
|
568
|
+
if (!value) {
|
569
|
+
return yup__namespace.mixed().nullable(true);
|
570
|
+
} else if (Array.isArray(value)) {
|
571
|
+
return yup__namespace.array().of(
|
572
|
+
yup__namespace.object().shape({
|
573
|
+
id: yup__namespace.number().required()
|
574
|
+
})
|
575
|
+
);
|
576
|
+
} else if (typeof value === "object") {
|
577
|
+
return yup__namespace.object();
|
578
|
+
} else {
|
579
|
+
return yup__namespace.mixed().test(
|
580
|
+
"type-error",
|
581
|
+
"Relation values must be either null, an array of objects with {id} or an object.",
|
582
|
+
() => false
|
583
|
+
);
|
584
|
+
}
|
585
|
+
})
|
595
586
|
)
|
596
587
|
};
|
597
588
|
default:
|
@@ -631,6 +622,14 @@ const createAttributeSchema = (attribute) => {
|
|
631
622
|
if (!value || typeof value === "string" && value.length === 0) {
|
632
623
|
return true;
|
633
624
|
}
|
625
|
+
if (typeof value === "object") {
|
626
|
+
try {
|
627
|
+
JSON.stringify(value);
|
628
|
+
return true;
|
629
|
+
} catch (err) {
|
630
|
+
return false;
|
631
|
+
}
|
632
|
+
}
|
634
633
|
try {
|
635
634
|
JSON.parse(value);
|
636
635
|
return true;
|
@@ -649,16 +648,30 @@ const createAttributeSchema = (attribute) => {
|
|
649
648
|
return yup__namespace.mixed();
|
650
649
|
}
|
651
650
|
};
|
652
|
-
const
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
651
|
+
const nullableSchema = (schema) => {
|
652
|
+
return schema?.nullable ? schema.nullable() : (
|
653
|
+
// In some cases '.nullable' will not be available on the schema.
|
654
|
+
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
655
|
+
// In these cases we should just return the schema as it is.
|
656
|
+
schema
|
657
|
+
);
|
658
|
+
};
|
659
|
+
const addNullableValidation = () => (schema) => {
|
660
|
+
return nullableSchema(schema);
|
661
|
+
};
|
662
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
663
|
+
if (options.status === "draft" || !attribute.required) {
|
664
|
+
return schema;
|
665
|
+
}
|
666
|
+
if (attribute.required && "required" in schema) {
|
667
|
+
return schema.required(strapiAdmin.translatedErrors.required);
|
658
668
|
}
|
659
|
-
return schema
|
669
|
+
return schema;
|
660
670
|
};
|
661
|
-
const addMinLengthValidation = (attribute) => (schema) => {
|
671
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
672
|
+
if (options.status === "draft") {
|
673
|
+
return schema;
|
674
|
+
}
|
662
675
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
663
676
|
return schema.min(attribute.minLength, {
|
664
677
|
...strapiAdmin.translatedErrors.minLength,
|
@@ -680,10 +693,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
680
693
|
}
|
681
694
|
return schema;
|
682
695
|
};
|
683
|
-
const addMinValidation = (attribute) => (schema) => {
|
684
|
-
if ("
|
696
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
697
|
+
if (options.status === "draft") {
|
698
|
+
return schema;
|
699
|
+
}
|
700
|
+
if ("min" in attribute && "min" in schema) {
|
685
701
|
const min = toInteger(attribute.min);
|
686
|
-
if (
|
702
|
+
if (min) {
|
687
703
|
return schema.min(min, {
|
688
704
|
...strapiAdmin.translatedErrors.min,
|
689
705
|
values: {
|
@@ -728,24 +744,6 @@ const addRegexValidation = (attribute) => (schema) => {
|
|
728
744
|
}
|
729
745
|
return schema;
|
730
746
|
};
|
731
|
-
const extractValuesFromYupError = (errorType, errorParams) => {
|
732
|
-
if (!errorType || !errorParams) {
|
733
|
-
return {};
|
734
|
-
}
|
735
|
-
return {
|
736
|
-
[errorType]: errorParams[errorType]
|
737
|
-
};
|
738
|
-
};
|
739
|
-
const getInnerErrors = (error) => (error?.inner || []).reduce((acc, currentError) => {
|
740
|
-
if (currentError.path) {
|
741
|
-
acc[currentError.path.split("[").join(".").split("]").join("")] = {
|
742
|
-
id: currentError.message,
|
743
|
-
defaultMessage: currentError.message,
|
744
|
-
values: extractValuesFromYupError(currentError?.type, currentError?.params)
|
745
|
-
};
|
746
|
-
}
|
747
|
-
return acc;
|
748
|
-
}, {});
|
749
747
|
const initApi = contentManagerApi.injectEndpoints({
|
750
748
|
endpoints: (builder) => ({
|
751
749
|
getInitialData: builder.query({
|
@@ -759,27 +757,20 @@ const { useGetInitialDataQuery } = initApi;
|
|
759
757
|
const useContentTypeSchema = (model) => {
|
760
758
|
const { toggleNotification } = strapiAdmin.useNotification();
|
761
759
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
762
|
-
const {
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
)
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
error: res.error,
|
777
|
-
components: Object.keys(components2).length === 0 ? void 0 : components2,
|
778
|
-
contentType: contentType2,
|
779
|
-
contentTypes: res.data?.contentTypes ?? []
|
780
|
-
};
|
781
|
-
}
|
782
|
-
});
|
760
|
+
const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
|
761
|
+
const { components, contentType, contentTypes } = React__namespace.useMemo(() => {
|
762
|
+
const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
|
763
|
+
const componentsByKey = data?.components.reduce((acc, component) => {
|
764
|
+
acc[component.uid] = component;
|
765
|
+
return acc;
|
766
|
+
}, {});
|
767
|
+
const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
|
768
|
+
return {
|
769
|
+
components: Object.keys(components2).length === 0 ? void 0 : components2,
|
770
|
+
contentType: contentType2,
|
771
|
+
contentTypes: data?.contentTypes ?? []
|
772
|
+
};
|
773
|
+
}, [model, data]);
|
783
774
|
React__namespace.useEffect(() => {
|
784
775
|
if (error) {
|
785
776
|
toggleNotification({
|
@@ -826,16 +817,328 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
826
817
|
}, {});
|
827
818
|
return componentsByKey;
|
828
819
|
};
|
829
|
-
const
|
820
|
+
const HOOKS = {
|
821
|
+
/**
|
822
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
823
|
+
* @constant
|
824
|
+
* @type {string}
|
825
|
+
*/
|
826
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
827
|
+
/**
|
828
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
829
|
+
* @constant
|
830
|
+
* @type {string}
|
831
|
+
*/
|
832
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
833
|
+
/**
|
834
|
+
* Hook that allows to mutate the CM's edit view layout
|
835
|
+
* @constant
|
836
|
+
* @type {string}
|
837
|
+
*/
|
838
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
839
|
+
/**
|
840
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
841
|
+
* @constant
|
842
|
+
* @type {string}
|
843
|
+
*/
|
844
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
845
|
+
};
|
846
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
847
|
+
endpoints: (builder) => ({
|
848
|
+
getContentTypeConfiguration: builder.query({
|
849
|
+
query: (uid) => ({
|
850
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
851
|
+
method: "GET"
|
852
|
+
}),
|
853
|
+
transformResponse: (response) => response.data,
|
854
|
+
providesTags: (_result, _error, uid) => [
|
855
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
856
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
857
|
+
]
|
858
|
+
}),
|
859
|
+
getAllContentTypeSettings: builder.query({
|
860
|
+
query: () => "/content-manager/content-types-settings",
|
861
|
+
transformResponse: (response) => response.data,
|
862
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
863
|
+
}),
|
864
|
+
updateContentTypeConfiguration: builder.mutation({
|
865
|
+
query: ({ uid, ...body }) => ({
|
866
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
867
|
+
method: "PUT",
|
868
|
+
data: body
|
869
|
+
}),
|
870
|
+
transformResponse: (response) => response.data,
|
871
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
872
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
873
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
874
|
+
// Is this necessary?
|
875
|
+
{ type: "InitialData" }
|
876
|
+
]
|
877
|
+
})
|
878
|
+
})
|
879
|
+
});
|
880
|
+
const {
|
881
|
+
useGetContentTypeConfigurationQuery,
|
882
|
+
useGetAllContentTypeSettingsQuery,
|
883
|
+
useUpdateContentTypeConfigurationMutation
|
884
|
+
} = contentTypesApi;
|
885
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
886
|
+
const { type } = attribute;
|
887
|
+
if (type === "relation") {
|
888
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
889
|
+
}
|
890
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
891
|
+
};
|
892
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
893
|
+
if (!mainFieldName) {
|
894
|
+
return void 0;
|
895
|
+
}
|
896
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
897
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
898
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
899
|
+
);
|
900
|
+
return {
|
901
|
+
name: mainFieldName,
|
902
|
+
type: mainFieldType ?? "string"
|
903
|
+
};
|
904
|
+
};
|
905
|
+
const DEFAULT_SETTINGS = {
|
906
|
+
bulkable: false,
|
907
|
+
filterable: false,
|
908
|
+
searchable: false,
|
909
|
+
pagination: false,
|
910
|
+
defaultSortBy: "",
|
911
|
+
defaultSortOrder: "asc",
|
912
|
+
mainField: "id",
|
913
|
+
pageSize: 10
|
914
|
+
};
|
915
|
+
const useDocumentLayout = (model) => {
|
916
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
917
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
918
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
830
919
|
const { toggleNotification } = strapiAdmin.useNotification();
|
831
920
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
921
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
832
922
|
const {
|
833
|
-
|
834
|
-
isLoading:
|
923
|
+
data,
|
924
|
+
isLoading: isLoadingConfigs,
|
925
|
+
error,
|
926
|
+
isFetching: isFetchingConfigs
|
927
|
+
} = useGetContentTypeConfigurationQuery(model);
|
928
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
929
|
+
React__namespace.useEffect(() => {
|
930
|
+
if (error) {
|
931
|
+
toggleNotification({
|
932
|
+
type: "danger",
|
933
|
+
message: formatAPIError(error)
|
934
|
+
});
|
935
|
+
}
|
936
|
+
}, [error, formatAPIError, toggleNotification]);
|
937
|
+
const editLayout = React__namespace.useMemo(
|
938
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
939
|
+
layout: [],
|
940
|
+
components: {},
|
941
|
+
metadatas: {},
|
942
|
+
options: {},
|
943
|
+
settings: DEFAULT_SETTINGS
|
944
|
+
},
|
945
|
+
[data, isLoading, schemas, schema, components]
|
946
|
+
);
|
947
|
+
const listLayout = React__namespace.useMemo(() => {
|
948
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
949
|
+
layout: [],
|
950
|
+
metadatas: {},
|
951
|
+
options: {},
|
952
|
+
settings: DEFAULT_SETTINGS
|
953
|
+
};
|
954
|
+
}, [data, isLoading, schemas, schema, components]);
|
955
|
+
const { layout: edit } = React__namespace.useMemo(
|
956
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
957
|
+
layout: editLayout,
|
958
|
+
query
|
959
|
+
}),
|
960
|
+
[editLayout, query, runHookWaterfall]
|
961
|
+
);
|
962
|
+
return {
|
963
|
+
error,
|
964
|
+
isLoading,
|
965
|
+
edit,
|
966
|
+
list: listLayout
|
967
|
+
};
|
968
|
+
};
|
969
|
+
const useDocLayout = () => {
|
970
|
+
const { model } = useDoc();
|
971
|
+
return useDocumentLayout(model);
|
972
|
+
};
|
973
|
+
const formatEditLayout = (data, {
|
974
|
+
schemas,
|
975
|
+
schema,
|
976
|
+
components
|
977
|
+
}) => {
|
978
|
+
let currentPanelIndex = 0;
|
979
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
980
|
+
data.contentType.layouts.edit,
|
981
|
+
schema?.attributes,
|
982
|
+
data.contentType.metadatas,
|
983
|
+
{ configurations: data.components, schemas: components },
|
984
|
+
schemas
|
985
|
+
).reduce((panels, row) => {
|
986
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
987
|
+
panels.push([row]);
|
988
|
+
currentPanelIndex += 2;
|
989
|
+
} else {
|
990
|
+
if (!panels[currentPanelIndex]) {
|
991
|
+
panels.push([row]);
|
992
|
+
} else {
|
993
|
+
panels[currentPanelIndex].push(row);
|
994
|
+
}
|
995
|
+
}
|
996
|
+
return panels;
|
997
|
+
}, []);
|
998
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
999
|
+
(acc, [uid, configuration]) => {
|
1000
|
+
acc[uid] = {
|
1001
|
+
layout: convertEditLayoutToFieldLayouts(
|
1002
|
+
configuration.layouts.edit,
|
1003
|
+
components[uid].attributes,
|
1004
|
+
configuration.metadatas,
|
1005
|
+
{ configurations: data.components, schemas: components }
|
1006
|
+
),
|
1007
|
+
settings: {
|
1008
|
+
...configuration.settings,
|
1009
|
+
icon: components[uid].info.icon,
|
1010
|
+
displayName: components[uid].info.displayName
|
1011
|
+
}
|
1012
|
+
};
|
1013
|
+
return acc;
|
1014
|
+
},
|
1015
|
+
{}
|
1016
|
+
);
|
1017
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1018
|
+
(acc, [attribute, metadata]) => {
|
1019
|
+
return {
|
1020
|
+
...acc,
|
1021
|
+
[attribute]: metadata.edit
|
1022
|
+
};
|
1023
|
+
},
|
1024
|
+
{}
|
1025
|
+
);
|
1026
|
+
return {
|
1027
|
+
layout: panelledEditAttributes,
|
1028
|
+
components: componentEditAttributes,
|
1029
|
+
metadatas: editMetadatas,
|
1030
|
+
settings: {
|
1031
|
+
...data.contentType.settings,
|
1032
|
+
displayName: schema?.info.displayName
|
1033
|
+
},
|
1034
|
+
options: {
|
1035
|
+
...schema?.options,
|
1036
|
+
...schema?.pluginOptions,
|
1037
|
+
...data.contentType.options
|
1038
|
+
}
|
1039
|
+
};
|
1040
|
+
};
|
1041
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1042
|
+
return rows.map(
|
1043
|
+
(row) => row.map((field) => {
|
1044
|
+
const attribute = attributes[field.name];
|
1045
|
+
if (!attribute) {
|
1046
|
+
return null;
|
1047
|
+
}
|
1048
|
+
const { edit: metadata } = metadatas[field.name];
|
1049
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1050
|
+
return {
|
1051
|
+
attribute,
|
1052
|
+
disabled: !metadata.editable,
|
1053
|
+
hint: metadata.description,
|
1054
|
+
label: metadata.label ?? "",
|
1055
|
+
name: field.name,
|
1056
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1057
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1058
|
+
schemas,
|
1059
|
+
components: components?.schemas ?? {}
|
1060
|
+
}),
|
1061
|
+
placeholder: metadata.placeholder ?? "",
|
1062
|
+
required: attribute.required ?? false,
|
1063
|
+
size: field.size,
|
1064
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1065
|
+
visible: metadata.visible ?? true,
|
1066
|
+
type: attribute.type
|
1067
|
+
};
|
1068
|
+
}).filter((field) => field !== null)
|
1069
|
+
);
|
1070
|
+
};
|
1071
|
+
const formatListLayout = (data, {
|
1072
|
+
schemas,
|
1073
|
+
schema,
|
1074
|
+
components
|
1075
|
+
}) => {
|
1076
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1077
|
+
(acc, [attribute, metadata]) => {
|
1078
|
+
return {
|
1079
|
+
...acc,
|
1080
|
+
[attribute]: metadata.list
|
1081
|
+
};
|
1082
|
+
},
|
1083
|
+
{}
|
1084
|
+
);
|
1085
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1086
|
+
data.contentType.layouts.list,
|
1087
|
+
schema?.attributes,
|
1088
|
+
listMetadatas,
|
1089
|
+
{ configurations: data.components, schemas: components },
|
1090
|
+
schemas
|
1091
|
+
);
|
1092
|
+
return {
|
1093
|
+
layout: listAttributes,
|
1094
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1095
|
+
metadatas: listMetadatas,
|
1096
|
+
options: {
|
1097
|
+
...schema?.options,
|
1098
|
+
...schema?.pluginOptions,
|
1099
|
+
...data.contentType.options
|
1100
|
+
}
|
1101
|
+
};
|
1102
|
+
};
|
1103
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1104
|
+
return columns.map((name) => {
|
1105
|
+
const attribute = attributes[name];
|
1106
|
+
if (!attribute) {
|
1107
|
+
return null;
|
1108
|
+
}
|
1109
|
+
const metadata = metadatas[name];
|
1110
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1111
|
+
return {
|
1112
|
+
attribute,
|
1113
|
+
label: metadata.label ?? "",
|
1114
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1115
|
+
schemas,
|
1116
|
+
components: components?.schemas ?? {}
|
1117
|
+
}),
|
1118
|
+
name,
|
1119
|
+
searchable: metadata.searchable ?? true,
|
1120
|
+
sortable: metadata.sortable ?? true
|
1121
|
+
};
|
1122
|
+
}).filter((field) => field !== null);
|
1123
|
+
};
|
1124
|
+
const useDocument = (args, opts) => {
|
1125
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1126
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1127
|
+
const {
|
1128
|
+
currentData: data,
|
1129
|
+
isLoading: isLoadingDocument,
|
835
1130
|
isFetching: isFetchingDocument,
|
836
1131
|
error
|
837
|
-
} = useGetDocumentQuery(args,
|
838
|
-
|
1132
|
+
} = useGetDocumentQuery(args, {
|
1133
|
+
...opts,
|
1134
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1135
|
+
});
|
1136
|
+
const {
|
1137
|
+
components,
|
1138
|
+
schema,
|
1139
|
+
schemas,
|
1140
|
+
isLoading: isLoadingSchema
|
1141
|
+
} = useContentTypeSchema(args.model);
|
839
1142
|
React__namespace.useEffect(() => {
|
840
1143
|
if (error) {
|
841
1144
|
toggleNotification({
|
@@ -862,7 +1165,7 @@ const useDocument = (args, opts) => {
|
|
862
1165
|
return null;
|
863
1166
|
} catch (error2) {
|
864
1167
|
if (error2 instanceof yup.ValidationError) {
|
865
|
-
return
|
1168
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
866
1169
|
}
|
867
1170
|
throw error2;
|
868
1171
|
}
|
@@ -870,12 +1173,15 @@ const useDocument = (args, opts) => {
|
|
870
1173
|
[validationSchema]
|
871
1174
|
);
|
872
1175
|
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1176
|
+
const hasError = !!error;
|
873
1177
|
return {
|
874
1178
|
components,
|
875
1179
|
document: data?.data,
|
876
1180
|
meta: data?.meta,
|
877
1181
|
isLoading,
|
1182
|
+
hasError,
|
878
1183
|
schema,
|
1184
|
+
schemas,
|
879
1185
|
validate
|
880
1186
|
};
|
881
1187
|
};
|
@@ -889,22 +1195,60 @@ const useDoc = () => {
|
|
889
1195
|
if (!slug) {
|
890
1196
|
throw new Error("Could not find model in url params");
|
891
1197
|
}
|
1198
|
+
const document = useDocument(
|
1199
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1200
|
+
{
|
1201
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1202
|
+
}
|
1203
|
+
);
|
1204
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
892
1205
|
return {
|
893
1206
|
collectionType,
|
894
1207
|
model: slug,
|
895
|
-
id:
|
896
|
-
...
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
1208
|
+
id: returnId,
|
1209
|
+
...document
|
1210
|
+
};
|
1211
|
+
};
|
1212
|
+
const useContentManagerContext = () => {
|
1213
|
+
const {
|
1214
|
+
collectionType,
|
1215
|
+
model,
|
1216
|
+
id,
|
1217
|
+
components,
|
1218
|
+
isLoading: isLoadingDoc,
|
1219
|
+
schema,
|
1220
|
+
schemas
|
1221
|
+
} = useDoc();
|
1222
|
+
const layout = useDocumentLayout(model);
|
1223
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1224
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1225
|
+
const slug = model;
|
1226
|
+
const isCreatingEntry = id === "create";
|
1227
|
+
useContentTypeSchema();
|
1228
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1229
|
+
const error = layout.error;
|
1230
|
+
return {
|
1231
|
+
error,
|
1232
|
+
isLoading,
|
1233
|
+
// Base metadata
|
1234
|
+
model,
|
1235
|
+
collectionType,
|
1236
|
+
id,
|
1237
|
+
slug,
|
1238
|
+
isCreatingEntry,
|
1239
|
+
isSingleType,
|
1240
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1241
|
+
// All schema infos
|
1242
|
+
components,
|
1243
|
+
contentType: schema,
|
1244
|
+
contentTypes: schemas,
|
1245
|
+
// Form state
|
1246
|
+
form,
|
1247
|
+
// layout infos
|
1248
|
+
layout
|
902
1249
|
};
|
903
1250
|
};
|
904
1251
|
const prefixPluginTranslations = (trad, pluginId) => {
|
905
|
-
if (!pluginId) {
|
906
|
-
throw new TypeError("pluginId can't be empty");
|
907
|
-
}
|
908
1252
|
return Object.keys(trad).reduce((acc, current) => {
|
909
1253
|
acc[`${pluginId}.${current}`] = trad[current];
|
910
1254
|
return acc;
|
@@ -920,6 +1264,8 @@ const useDocumentActions = () => {
|
|
920
1264
|
const { formatMessage } = reactIntl.useIntl();
|
921
1265
|
const { trackUsage } = strapiAdmin.useTracking();
|
922
1266
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1267
|
+
const navigate = reactRouterDom.useNavigate();
|
1268
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
923
1269
|
const [deleteDocument] = useDeleteDocumentMutation();
|
924
1270
|
const _delete = React__namespace.useCallback(
|
925
1271
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -958,14 +1304,53 @@ const useDocumentActions = () => {
|
|
958
1304
|
},
|
959
1305
|
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
960
1306
|
);
|
1307
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1308
|
+
const deleteMany = React__namespace.useCallback(
|
1309
|
+
async ({ model, documentIds, params }) => {
|
1310
|
+
try {
|
1311
|
+
trackUsage("willBulkDeleteEntries");
|
1312
|
+
const res = await deleteManyDocuments({
|
1313
|
+
model,
|
1314
|
+
documentIds,
|
1315
|
+
params
|
1316
|
+
});
|
1317
|
+
if ("error" in res) {
|
1318
|
+
toggleNotification({
|
1319
|
+
type: "danger",
|
1320
|
+
message: formatAPIError(res.error)
|
1321
|
+
});
|
1322
|
+
return { error: res.error };
|
1323
|
+
}
|
1324
|
+
toggleNotification({
|
1325
|
+
type: "success",
|
1326
|
+
title: formatMessage({
|
1327
|
+
id: getTranslation("success.records.delete"),
|
1328
|
+
defaultMessage: "Successfully deleted."
|
1329
|
+
}),
|
1330
|
+
message: ""
|
1331
|
+
});
|
1332
|
+
trackUsage("didBulkDeleteEntries");
|
1333
|
+
return res.data;
|
1334
|
+
} catch (err) {
|
1335
|
+
toggleNotification({
|
1336
|
+
type: "danger",
|
1337
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1338
|
+
});
|
1339
|
+
trackUsage("didNotBulkDeleteEntries");
|
1340
|
+
throw err;
|
1341
|
+
}
|
1342
|
+
},
|
1343
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1344
|
+
);
|
961
1345
|
const [discardDocument] = useDiscardDocumentMutation();
|
962
1346
|
const discard = React__namespace.useCallback(
|
963
|
-
async ({ collectionType, model, documentId }) => {
|
1347
|
+
async ({ collectionType, model, documentId, params }) => {
|
964
1348
|
try {
|
965
1349
|
const res = await discardDocument({
|
966
1350
|
collectionType,
|
967
1351
|
model,
|
968
|
-
documentId
|
1352
|
+
documentId,
|
1353
|
+
params
|
969
1354
|
});
|
970
1355
|
if ("error" in res) {
|
971
1356
|
toggleNotification({
|
@@ -1027,6 +1412,43 @@ const useDocumentActions = () => {
|
|
1027
1412
|
},
|
1028
1413
|
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1029
1414
|
);
|
1415
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1416
|
+
const publishMany = React__namespace.useCallback(
|
1417
|
+
async ({ model, documentIds, params }) => {
|
1418
|
+
try {
|
1419
|
+
const res = await publishManyDocuments({
|
1420
|
+
model,
|
1421
|
+
documentIds,
|
1422
|
+
params
|
1423
|
+
});
|
1424
|
+
if ("error" in res) {
|
1425
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1426
|
+
return { error: res.error };
|
1427
|
+
}
|
1428
|
+
toggleNotification({
|
1429
|
+
type: "success",
|
1430
|
+
message: formatMessage({
|
1431
|
+
id: getTranslation("success.record.publish"),
|
1432
|
+
defaultMessage: "Published document"
|
1433
|
+
})
|
1434
|
+
});
|
1435
|
+
return res.data;
|
1436
|
+
} catch (err) {
|
1437
|
+
toggleNotification({
|
1438
|
+
type: "danger",
|
1439
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1440
|
+
});
|
1441
|
+
throw err;
|
1442
|
+
}
|
1443
|
+
},
|
1444
|
+
[
|
1445
|
+
// trackUsage,
|
1446
|
+
publishManyDocuments,
|
1447
|
+
toggleNotification,
|
1448
|
+
formatMessage,
|
1449
|
+
formatAPIError
|
1450
|
+
]
|
1451
|
+
);
|
1030
1452
|
const [updateDocument] = useUpdateDocumentMutation();
|
1031
1453
|
const update = React__namespace.useCallback(
|
1032
1454
|
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
@@ -1101,6 +1523,41 @@ const useDocumentActions = () => {
|
|
1101
1523
|
},
|
1102
1524
|
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1103
1525
|
);
|
1526
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1527
|
+
const unpublishMany = React__namespace.useCallback(
|
1528
|
+
async ({ model, documentIds, params }) => {
|
1529
|
+
try {
|
1530
|
+
trackUsage("willBulkUnpublishEntries");
|
1531
|
+
const res = await unpublishManyDocuments({
|
1532
|
+
model,
|
1533
|
+
documentIds,
|
1534
|
+
params
|
1535
|
+
});
|
1536
|
+
if ("error" in res) {
|
1537
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1538
|
+
return { error: res.error };
|
1539
|
+
}
|
1540
|
+
trackUsage("didBulkUnpublishEntries");
|
1541
|
+
toggleNotification({
|
1542
|
+
type: "success",
|
1543
|
+
title: formatMessage({
|
1544
|
+
id: getTranslation("success.records.unpublish"),
|
1545
|
+
defaultMessage: "Successfully unpublished."
|
1546
|
+
}),
|
1547
|
+
message: ""
|
1548
|
+
});
|
1549
|
+
return res.data;
|
1550
|
+
} catch (err) {
|
1551
|
+
toggleNotification({
|
1552
|
+
type: "danger",
|
1553
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1554
|
+
});
|
1555
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1556
|
+
throw err;
|
1557
|
+
}
|
1558
|
+
},
|
1559
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1560
|
+
);
|
1104
1561
|
const [createDocument] = useCreateDocumentMutation();
|
1105
1562
|
const create = React__namespace.useCallback(
|
1106
1563
|
async ({ model, params }, data, trackerProperty) => {
|
@@ -1123,6 +1580,7 @@ const useDocumentActions = () => {
|
|
1123
1580
|
defaultMessage: "Saved document"
|
1124
1581
|
})
|
1125
1582
|
});
|
1583
|
+
setCurrentStep("contentManager.success");
|
1126
1584
|
return res.data;
|
1127
1585
|
} catch (err) {
|
1128
1586
|
toggleNotification({
|
@@ -1144,7 +1602,6 @@ const useDocumentActions = () => {
|
|
1144
1602
|
sourceId
|
1145
1603
|
});
|
1146
1604
|
if ("error" in res) {
|
1147
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1148
1605
|
return { error: res.error };
|
1149
1606
|
}
|
1150
1607
|
toggleNotification({
|
@@ -1163,7 +1620,7 @@ const useDocumentActions = () => {
|
|
1163
1620
|
throw err;
|
1164
1621
|
}
|
1165
1622
|
},
|
1166
|
-
[autoCloneDocument,
|
1623
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1167
1624
|
);
|
1168
1625
|
const [cloneDocument] = useCloneDocumentMutation();
|
1169
1626
|
const clone = React__namespace.useCallback(
|
@@ -1189,6 +1646,7 @@ const useDocumentActions = () => {
|
|
1189
1646
|
defaultMessage: "Cloned document"
|
1190
1647
|
})
|
1191
1648
|
});
|
1649
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1192
1650
|
return res.data;
|
1193
1651
|
} catch (err) {
|
1194
1652
|
toggleNotification({
|
@@ -1199,7 +1657,7 @@ const useDocumentActions = () => {
|
|
1199
1657
|
throw err;
|
1200
1658
|
}
|
1201
1659
|
},
|
1202
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1660
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1203
1661
|
);
|
1204
1662
|
const [getDoc] = useLazyGetDocumentQuery();
|
1205
1663
|
const getDocument = React__namespace.useCallback(
|
@@ -1214,17 +1672,20 @@ const useDocumentActions = () => {
|
|
1214
1672
|
clone,
|
1215
1673
|
create,
|
1216
1674
|
delete: _delete,
|
1675
|
+
deleteMany,
|
1217
1676
|
discard,
|
1218
1677
|
getDocument,
|
1219
1678
|
publish,
|
1679
|
+
publishMany,
|
1220
1680
|
unpublish,
|
1681
|
+
unpublishMany,
|
1221
1682
|
update
|
1222
1683
|
};
|
1223
1684
|
};
|
1224
|
-
const ProtectedHistoryPage =
|
1225
|
-
() => Promise.resolve().then(() => require("./History-
|
1685
|
+
const ProtectedHistoryPage = React__namespace.lazy(
|
1686
|
+
() => Promise.resolve().then(() => require("./History-Di3zm4HT.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1226
1687
|
);
|
1227
|
-
const routes$
|
1688
|
+
const routes$2 = [
|
1228
1689
|
{
|
1229
1690
|
path: ":collectionType/:slug/:id/history",
|
1230
1691
|
Component: ProtectedHistoryPage
|
@@ -1234,32 +1695,45 @@ const routes$1 = [
|
|
1234
1695
|
Component: ProtectedHistoryPage
|
1235
1696
|
}
|
1236
1697
|
];
|
1698
|
+
const ProtectedPreviewPage = React__namespace.lazy(
|
1699
|
+
() => Promise.resolve().then(() => require("./Preview-D_3aO6Ly.js")).then((mod) => ({ default: mod.ProtectedPreviewPage }))
|
1700
|
+
);
|
1701
|
+
const routes$1 = [
|
1702
|
+
{
|
1703
|
+
path: ":collectionType/:slug/:id/preview",
|
1704
|
+
Component: ProtectedPreviewPage
|
1705
|
+
},
|
1706
|
+
{
|
1707
|
+
path: ":collectionType/:slug/preview",
|
1708
|
+
Component: ProtectedPreviewPage
|
1709
|
+
}
|
1710
|
+
];
|
1237
1711
|
const ProtectedEditViewPage = React.lazy(
|
1238
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1712
|
+
() => Promise.resolve().then(() => require("./EditViewPage-QPUftxUd.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1239
1713
|
);
|
1240
1714
|
const ProtectedListViewPage = React.lazy(
|
1241
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1715
|
+
() => Promise.resolve().then(() => require("./ListViewPage-DFDcG8gM.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1242
1716
|
);
|
1243
1717
|
const ProtectedListConfiguration = React.lazy(
|
1244
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1718
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-Cq361KIt.js")).then((mod) => ({
|
1245
1719
|
default: mod.ProtectedListConfiguration
|
1246
1720
|
}))
|
1247
1721
|
);
|
1248
1722
|
const ProtectedEditConfigurationPage = React.lazy(
|
1249
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1723
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-BHkjAbxH.js")).then((mod) => ({
|
1250
1724
|
default: mod.ProtectedEditConfigurationPage
|
1251
1725
|
}))
|
1252
1726
|
);
|
1253
1727
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1254
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1728
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-N-CTtgQa.js")).then((mod) => ({
|
1255
1729
|
default: mod.ProtectedComponentConfigurationPage
|
1256
1730
|
}))
|
1257
1731
|
);
|
1258
1732
|
const NoPermissions = React.lazy(
|
1259
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1733
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-DyLphsn_.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1260
1734
|
);
|
1261
1735
|
const NoContentType = React.lazy(
|
1262
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1736
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-BSyvnDZZ.js")).then((mod) => ({ default: mod.NoContentType }))
|
1263
1737
|
);
|
1264
1738
|
const CollectionTypePages = () => {
|
1265
1739
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1271,7 +1745,7 @@ const CollectionTypePages = () => {
|
|
1271
1745
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1272
1746
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1273
1747
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1274
|
-
const LIST_PATH = `/content-manager
|
1748
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1275
1749
|
const routes = [
|
1276
1750
|
{
|
1277
1751
|
path: LIST_RELATIVE_PATH,
|
@@ -1305,6 +1779,7 @@ const routes = [
|
|
1305
1779
|
path: "no-content-types",
|
1306
1780
|
Component: NoContentType
|
1307
1781
|
},
|
1782
|
+
...routes$2,
|
1308
1783
|
...routes$1
|
1309
1784
|
];
|
1310
1785
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1373,12 +1848,14 @@ const DocumentActionButton = (action) => {
|
|
1373
1848
|
/* @__PURE__ */ jsxRuntime.jsx(
|
1374
1849
|
designSystem.Button,
|
1375
1850
|
{
|
1376
|
-
flex:
|
1851
|
+
flex: "auto",
|
1377
1852
|
startIcon: action.icon,
|
1378
1853
|
disabled: action.disabled,
|
1379
1854
|
onClick: handleClick(action),
|
1380
1855
|
justifyContent: "center",
|
1381
1856
|
variant: action.variant || "default",
|
1857
|
+
paddingTop: "7px",
|
1858
|
+
paddingBottom: "7px",
|
1382
1859
|
children: action.label
|
1383
1860
|
}
|
1384
1861
|
),
|
@@ -1386,7 +1863,7 @@ const DocumentActionButton = (action) => {
|
|
1386
1863
|
DocumentActionConfirmDialog,
|
1387
1864
|
{
|
1388
1865
|
...action.dialog,
|
1389
|
-
variant: action.variant,
|
1866
|
+
variant: action.dialog?.variant ?? action.variant,
|
1390
1867
|
isOpen: dialogId === action.id,
|
1391
1868
|
onClose: handleClose
|
1392
1869
|
}
|
@@ -1401,6 +1878,11 @@ const DocumentActionButton = (action) => {
|
|
1401
1878
|
) : null
|
1402
1879
|
] });
|
1403
1880
|
};
|
1881
|
+
const MenuItem = styledComponents.styled(designSystem.Menu.Item)`
|
1882
|
+
&:hover {
|
1883
|
+
background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
|
1884
|
+
}
|
1885
|
+
`;
|
1404
1886
|
const DocumentActionsMenu = ({
|
1405
1887
|
actions: actions2,
|
1406
1888
|
children,
|
@@ -1443,49 +1925,48 @@ const DocumentActionsMenu = ({
|
|
1443
1925
|
disabled: isDisabled,
|
1444
1926
|
size: "S",
|
1445
1927
|
endIcon: null,
|
1446
|
-
paddingTop: "
|
1447
|
-
paddingLeft: "
|
1448
|
-
paddingRight: "
|
1928
|
+
paddingTop: "4px",
|
1929
|
+
paddingLeft: "7px",
|
1930
|
+
paddingRight: "7px",
|
1449
1931
|
variant,
|
1450
1932
|
children: [
|
1451
1933
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
1452
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, {
|
1934
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1453
1935
|
id: "content-manager.containers.edit.panels.default.more-actions",
|
1454
1936
|
defaultMessage: "More document actions"
|
1455
1937
|
}) })
|
1456
1938
|
]
|
1457
1939
|
}
|
1458
1940
|
),
|
1459
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, {
|
1941
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1460
1942
|
actions2.map((action) => {
|
1461
1943
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
1462
|
-
|
1944
|
+
MenuItem,
|
1463
1945
|
{
|
1464
1946
|
disabled: action.disabled,
|
1465
1947
|
onSelect: handleClick(action),
|
1466
1948
|
display: "block",
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
] })
|
1949
|
+
isVariantDanger: action.variant === "danger",
|
1950
|
+
isDisabled: action.disabled,
|
1951
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
1952
|
+
designSystem.Flex,
|
1953
|
+
{
|
1954
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1955
|
+
gap: 2,
|
1956
|
+
tag: "span",
|
1957
|
+
children: [
|
1958
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1959
|
+
designSystem.Flex,
|
1960
|
+
{
|
1961
|
+
tag: "span",
|
1962
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1963
|
+
children: action.icon
|
1964
|
+
}
|
1965
|
+
),
|
1966
|
+
action.label
|
1967
|
+
]
|
1968
|
+
}
|
1969
|
+
) })
|
1489
1970
|
},
|
1490
1971
|
action.id
|
1491
1972
|
);
|
@@ -1527,6 +2008,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
|
|
1527
2008
|
return "primary600";
|
1528
2009
|
}
|
1529
2010
|
};
|
2011
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
2012
|
+
switch (variant) {
|
2013
|
+
case "danger":
|
2014
|
+
return "danger600";
|
2015
|
+
case "secondary":
|
2016
|
+
return "neutral500";
|
2017
|
+
case "success":
|
2018
|
+
return "success600";
|
2019
|
+
default:
|
2020
|
+
return "primary600";
|
2021
|
+
}
|
2022
|
+
};
|
1530
2023
|
const DocumentActionConfirmDialog = ({
|
1531
2024
|
onClose,
|
1532
2025
|
onCancel,
|
@@ -1549,61 +2042,54 @@ const DocumentActionConfirmDialog = ({
|
|
1549
2042
|
}
|
1550
2043
|
onClose();
|
1551
2044
|
};
|
1552
|
-
return /* @__PURE__ */ jsxRuntime.
|
1553
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
1554
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1555
|
-
|
1556
|
-
{
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
)
|
1567
|
-
] });
|
2045
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2046
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2047
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
2048
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
2049
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
2050
|
+
id: "app.components.Button.cancel",
|
2051
|
+
defaultMessage: "Cancel"
|
2052
|
+
}) }) }),
|
2053
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
2054
|
+
id: "app.components.Button.confirm",
|
2055
|
+
defaultMessage: "Confirm"
|
2056
|
+
}) })
|
2057
|
+
] })
|
2058
|
+
] }) });
|
1568
2059
|
};
|
1569
2060
|
const DocumentActionModal = ({
|
1570
2061
|
isOpen,
|
1571
2062
|
title,
|
1572
2063
|
onClose,
|
1573
2064
|
footer: Footer,
|
1574
|
-
content,
|
2065
|
+
content: Content,
|
1575
2066
|
onModalClose
|
1576
2067
|
}) => {
|
1577
|
-
const id = React__namespace.useId();
|
1578
|
-
if (!isOpen) {
|
1579
|
-
return null;
|
1580
|
-
}
|
1581
2068
|
const handleClose = () => {
|
1582
2069
|
if (onClose) {
|
1583
2070
|
onClose();
|
1584
2071
|
}
|
1585
2072
|
onModalClose();
|
1586
2073
|
};
|
1587
|
-
return /* @__PURE__ */ jsxRuntime.
|
1588
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
1589
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
1590
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1598
|
-
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
] });
|
2074
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
|
2075
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
|
2076
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
|
2077
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
2078
|
+
] }) });
|
2079
|
+
};
|
2080
|
+
const transformData = (data) => {
|
2081
|
+
if (Array.isArray(data)) {
|
2082
|
+
return data.map(transformData);
|
2083
|
+
}
|
2084
|
+
if (typeof data === "object" && data !== null) {
|
2085
|
+
if ("apiData" in data) {
|
2086
|
+
return data.apiData;
|
2087
|
+
}
|
2088
|
+
return mapValues__default.default(transformData)(data);
|
2089
|
+
}
|
2090
|
+
return data;
|
1605
2091
|
};
|
1606
|
-
const PublishAction = ({
|
2092
|
+
const PublishAction$1 = ({
|
1607
2093
|
activeTab,
|
1608
2094
|
documentId,
|
1609
2095
|
model,
|
@@ -1615,13 +2101,18 @@ const PublishAction = ({
|
|
1615
2101
|
const navigate = reactRouterDom.useNavigate();
|
1616
2102
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1617
2103
|
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2104
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
1618
2105
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2106
|
+
const { id } = reactRouterDom.useParams();
|
1619
2107
|
const { formatMessage } = reactIntl.useIntl();
|
1620
|
-
const { canPublish
|
1621
|
-
"PublishAction",
|
1622
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1623
|
-
);
|
2108
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1624
2109
|
const { publish } = useDocumentActions();
|
2110
|
+
const [
|
2111
|
+
countDraftRelations,
|
2112
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2113
|
+
] = useLazyGetDraftRelationCountQuery();
|
2114
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
2115
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1625
2116
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1626
2117
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1627
2118
|
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1630,10 +2121,107 @@ const PublishAction = ({
|
|
1630
2121
|
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1631
2122
|
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1632
2123
|
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
2124
|
+
React__namespace.useEffect(() => {
|
2125
|
+
if (isErrorDraftRelations) {
|
2126
|
+
toggleNotification({
|
2127
|
+
type: "danger",
|
2128
|
+
message: formatMessage({
|
2129
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2130
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2131
|
+
})
|
2132
|
+
});
|
2133
|
+
}
|
2134
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2135
|
+
React__namespace.useEffect(() => {
|
2136
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2137
|
+
const extractDraftRelations = (data) => {
|
2138
|
+
const relations = data.connect || [];
|
2139
|
+
relations.forEach((relation) => {
|
2140
|
+
if (relation.status === "draft") {
|
2141
|
+
localDraftRelations.add(relation.id);
|
2142
|
+
}
|
2143
|
+
});
|
2144
|
+
};
|
2145
|
+
const traverseAndExtract = (data) => {
|
2146
|
+
Object.entries(data).forEach(([key, value]) => {
|
2147
|
+
if (key === "connect" && Array.isArray(value)) {
|
2148
|
+
extractDraftRelations({ connect: value });
|
2149
|
+
} else if (typeof value === "object" && value !== null) {
|
2150
|
+
traverseAndExtract(value);
|
2151
|
+
}
|
2152
|
+
});
|
2153
|
+
};
|
2154
|
+
if (!documentId || modified) {
|
2155
|
+
traverseAndExtract(formValues);
|
2156
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2157
|
+
}
|
2158
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2159
|
+
React__namespace.useEffect(() => {
|
2160
|
+
if (!document || !document.documentId || isListView) {
|
2161
|
+
return;
|
2162
|
+
}
|
2163
|
+
const fetchDraftRelationsCount = async () => {
|
2164
|
+
const { data, error } = await countDraftRelations({
|
2165
|
+
collectionType,
|
2166
|
+
model,
|
2167
|
+
documentId,
|
2168
|
+
params
|
2169
|
+
});
|
2170
|
+
if (error) {
|
2171
|
+
throw error;
|
2172
|
+
}
|
2173
|
+
if (data) {
|
2174
|
+
setServerCountOfDraftRelations(data.data);
|
2175
|
+
}
|
2176
|
+
};
|
2177
|
+
fetchDraftRelationsCount();
|
2178
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
1633
2179
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1634
2180
|
if (!schema?.options?.draftAndPublish) {
|
1635
2181
|
return null;
|
1636
2182
|
}
|
2183
|
+
const performPublish = async () => {
|
2184
|
+
setSubmitting(true);
|
2185
|
+
try {
|
2186
|
+
const { errors } = await validate(true, {
|
2187
|
+
status: "published"
|
2188
|
+
});
|
2189
|
+
if (errors) {
|
2190
|
+
toggleNotification({
|
2191
|
+
type: "danger",
|
2192
|
+
message: formatMessage({
|
2193
|
+
id: "content-manager.validation.error",
|
2194
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2195
|
+
})
|
2196
|
+
});
|
2197
|
+
return;
|
2198
|
+
}
|
2199
|
+
const res = await publish(
|
2200
|
+
{
|
2201
|
+
collectionType,
|
2202
|
+
model,
|
2203
|
+
documentId,
|
2204
|
+
params
|
2205
|
+
},
|
2206
|
+
transformData(formValues)
|
2207
|
+
);
|
2208
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2209
|
+
if (id === "create") {
|
2210
|
+
navigate({
|
2211
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2212
|
+
search: rawQuery
|
2213
|
+
});
|
2214
|
+
}
|
2215
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2216
|
+
setErrors(formatValidationErrors(res.error));
|
2217
|
+
}
|
2218
|
+
} finally {
|
2219
|
+
setSubmitting(false);
|
2220
|
+
}
|
2221
|
+
};
|
2222
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2223
|
+
const enableDraftRelationsCount = false;
|
2224
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1637
2225
|
return {
|
1638
2226
|
/**
|
1639
2227
|
* Disabled when:
|
@@ -1643,52 +2231,39 @@ const PublishAction = ({
|
|
1643
2231
|
* - the document is already published & not modified
|
1644
2232
|
* - the document is being created & not modified
|
1645
2233
|
* - the user doesn't have the permission to publish
|
1646
|
-
* - the user doesn't have the permission to create a new document
|
1647
|
-
* - the user doesn't have the permission to update the document
|
1648
2234
|
*/
|
1649
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2235
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1650
2236
|
label: formatMessage({
|
1651
2237
|
id: "app.utils.publish",
|
1652
2238
|
defaultMessage: "Publish"
|
1653
2239
|
}),
|
1654
2240
|
onClick: async () => {
|
1655
|
-
|
1656
|
-
|
1657
|
-
|
1658
|
-
|
1659
|
-
|
1660
|
-
|
1661
|
-
|
1662
|
-
|
1663
|
-
|
1664
|
-
|
1665
|
-
|
1666
|
-
|
1667
|
-
|
1668
|
-
|
1669
|
-
|
1670
|
-
|
1671
|
-
|
1672
|
-
documentId,
|
1673
|
-
params
|
1674
|
-
},
|
1675
|
-
formValues
|
1676
|
-
);
|
1677
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1678
|
-
navigate({
|
1679
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1680
|
-
search: rawQuery
|
1681
|
-
});
|
1682
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1683
|
-
setErrors(formatValidationErrors(res.error));
|
2241
|
+
await performPublish();
|
2242
|
+
},
|
2243
|
+
dialog: hasDraftRelations ? {
|
2244
|
+
type: "dialog",
|
2245
|
+
variant: "danger",
|
2246
|
+
footer: null,
|
2247
|
+
title: formatMessage({
|
2248
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2249
|
+
defaultMessage: "Confirmation"
|
2250
|
+
}),
|
2251
|
+
content: formatMessage(
|
2252
|
+
{
|
2253
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2254
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2255
|
+
},
|
2256
|
+
{
|
2257
|
+
count: totalDraftRelations
|
1684
2258
|
}
|
1685
|
-
|
1686
|
-
|
2259
|
+
),
|
2260
|
+
onConfirm: async () => {
|
2261
|
+
await performPublish();
|
1687
2262
|
}
|
1688
|
-
}
|
2263
|
+
} : void 0
|
1689
2264
|
};
|
1690
2265
|
};
|
1691
|
-
PublishAction.type = "publish";
|
2266
|
+
PublishAction$1.type = "publish";
|
1692
2267
|
const UpdateAction = ({
|
1693
2268
|
activeTab,
|
1694
2269
|
documentId,
|
@@ -1701,10 +2276,6 @@ const UpdateAction = ({
|
|
1701
2276
|
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
1702
2277
|
const isCloning = cloneMatch !== null;
|
1703
2278
|
const { formatMessage } = reactIntl.useIntl();
|
1704
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1705
|
-
canCreate: canCreate2,
|
1706
|
-
canUpdate: canUpdate2
|
1707
|
-
}));
|
1708
2279
|
const { create, update, clone } = useDocumentActions();
|
1709
2280
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1710
2281
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
@@ -1721,18 +2292,18 @@ const UpdateAction = ({
|
|
1721
2292
|
* - the form is submitting
|
1722
2293
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1723
2294
|
* - the active tab is the published tab
|
1724
|
-
* - the user doesn't have the permission to create a new document
|
1725
|
-
* - the user doesn't have the permission to update the document
|
1726
2295
|
*/
|
1727
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2296
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1728
2297
|
label: formatMessage({
|
1729
|
-
id: "
|
2298
|
+
id: "global.save",
|
1730
2299
|
defaultMessage: "Save"
|
1731
2300
|
}),
|
1732
2301
|
onClick: async () => {
|
1733
2302
|
setSubmitting(true);
|
1734
2303
|
try {
|
1735
|
-
const { errors } = await validate(
|
2304
|
+
const { errors } = await validate(true, {
|
2305
|
+
status: "draft"
|
2306
|
+
});
|
1736
2307
|
if (errors) {
|
1737
2308
|
toggleNotification({
|
1738
2309
|
type: "danger",
|
@@ -1750,13 +2321,16 @@ const UpdateAction = ({
|
|
1750
2321
|
documentId: cloneMatch.params.origin,
|
1751
2322
|
params
|
1752
2323
|
},
|
1753
|
-
document
|
2324
|
+
transformData(document)
|
1754
2325
|
);
|
1755
2326
|
if ("data" in res) {
|
1756
|
-
navigate(
|
1757
|
-
|
1758
|
-
|
1759
|
-
|
2327
|
+
navigate(
|
2328
|
+
{
|
2329
|
+
pathname: `../${res.data.documentId}`,
|
2330
|
+
search: rawQuery
|
2331
|
+
},
|
2332
|
+
{ relative: "path" }
|
2333
|
+
);
|
1760
2334
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1761
2335
|
setErrors(formatValidationErrors(res.error));
|
1762
2336
|
}
|
@@ -1768,7 +2342,7 @@ const UpdateAction = ({
|
|
1768
2342
|
documentId,
|
1769
2343
|
params
|
1770
2344
|
},
|
1771
|
-
document
|
2345
|
+
transformData(document)
|
1772
2346
|
);
|
1773
2347
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1774
2348
|
setErrors(formatValidationErrors(res.error));
|
@@ -1781,13 +2355,16 @@ const UpdateAction = ({
|
|
1781
2355
|
model,
|
1782
2356
|
params
|
1783
2357
|
},
|
1784
|
-
document
|
2358
|
+
transformData(document)
|
1785
2359
|
);
|
1786
2360
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1787
|
-
navigate(
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
2361
|
+
navigate(
|
2362
|
+
{
|
2363
|
+
pathname: `../${res.data.documentId}`,
|
2364
|
+
search: rawQuery
|
2365
|
+
},
|
2366
|
+
{ replace: true, relative: "path" }
|
2367
|
+
);
|
1791
2368
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1792
2369
|
setErrors(formatValidationErrors(res.error));
|
1793
2370
|
}
|
@@ -1803,7 +2380,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
|
|
1803
2380
|
KEEP: "keep",
|
1804
2381
|
DISCARD: "discard"
|
1805
2382
|
};
|
1806
|
-
const UnpublishAction = ({
|
2383
|
+
const UnpublishAction$1 = ({
|
1807
2384
|
activeTab,
|
1808
2385
|
documentId,
|
1809
2386
|
model,
|
@@ -1819,10 +2396,8 @@ const UnpublishAction = ({
|
|
1819
2396
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1820
2397
|
const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
|
1821
2398
|
const isDocumentModified = document?.status === "modified";
|
1822
|
-
const handleChange = (
|
1823
|
-
|
1824
|
-
setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1825
|
-
}
|
2399
|
+
const handleChange = (value) => {
|
2400
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1826
2401
|
};
|
1827
2402
|
if (!schema?.options?.draftAndPublish) {
|
1828
2403
|
return null;
|
@@ -1833,7 +2408,7 @@ const UnpublishAction = ({
|
|
1833
2408
|
id: "app.utils.unpublish",
|
1834
2409
|
defaultMessage: "Unpublish"
|
1835
2410
|
}),
|
1836
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2411
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1837
2412
|
onClick: async () => {
|
1838
2413
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1839
2414
|
if (!documentId) {
|
@@ -1866,45 +2441,30 @@ const UnpublishAction = ({
|
|
1866
2441
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
|
1867
2442
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
|
1868
2443
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
1869
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2444
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
1870
2445
|
id: "content-manager.actions.unpublish.dialog.body",
|
1871
2446
|
defaultMessage: "Are you sure?"
|
1872
2447
|
}) })
|
1873
2448
|
] }),
|
1874
2449
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
1875
|
-
designSystem.
|
2450
|
+
designSystem.Radio.Group,
|
1876
2451
|
{
|
1877
|
-
|
1878
|
-
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
2452
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2453
|
+
name: "discard-options",
|
2454
|
+
"aria-label": formatMessage({
|
2455
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2456
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2457
|
+
}),
|
2458
|
+
onValueChange: handleChange,
|
1882
2459
|
children: [
|
1883
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
1889
|
-
|
1890
|
-
|
1891
|
-
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
1892
|
-
defaultMessage: "Keep draft"
|
1893
|
-
})
|
1894
|
-
}
|
1895
|
-
),
|
1896
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1897
|
-
designSystem.Radio,
|
1898
|
-
{
|
1899
|
-
checked: !shouldKeepDraft,
|
1900
|
-
value: UNPUBLISH_DRAFT_OPTIONS.DISCARD,
|
1901
|
-
name: "discard-options",
|
1902
|
-
children: formatMessage({
|
1903
|
-
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
1904
|
-
defaultMessage: "Replace draft"
|
1905
|
-
})
|
1906
|
-
}
|
1907
|
-
)
|
2460
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2461
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2462
|
+
defaultMessage: "Keep draft"
|
2463
|
+
}) }),
|
2464
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2465
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2466
|
+
defaultMessage: "Replace draft"
|
2467
|
+
}) })
|
1908
2468
|
]
|
1909
2469
|
}
|
1910
2470
|
)
|
@@ -1937,7 +2497,7 @@ const UnpublishAction = ({
|
|
1937
2497
|
position: ["panel", "table-row"]
|
1938
2498
|
};
|
1939
2499
|
};
|
1940
|
-
UnpublishAction.type = "unpublish";
|
2500
|
+
UnpublishAction$1.type = "unpublish";
|
1941
2501
|
const DiscardAction = ({
|
1942
2502
|
activeTab,
|
1943
2503
|
documentId,
|
@@ -1960,7 +2520,7 @@ const DiscardAction = ({
|
|
1960
2520
|
id: "content-manager.actions.discard.label",
|
1961
2521
|
defaultMessage: "Discard changes"
|
1962
2522
|
}),
|
1963
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2523
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1964
2524
|
position: ["panel", "table-row"],
|
1965
2525
|
variant: "danger",
|
1966
2526
|
dialog: {
|
@@ -1971,7 +2531,7 @@ const DiscardAction = ({
|
|
1971
2531
|
}),
|
1972
2532
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
1973
2533
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
1974
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2534
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
1975
2535
|
id: "content-manager.actions.discard.dialog.body",
|
1976
2536
|
defaultMessage: "Are you sure?"
|
1977
2537
|
}) })
|
@@ -1988,12 +2548,7 @@ const DiscardAction = ({
|
|
1988
2548
|
};
|
1989
2549
|
};
|
1990
2550
|
DiscardAction.type = "discard";
|
1991
|
-
const
|
1992
|
-
path {
|
1993
|
-
fill: currentColor;
|
1994
|
-
}
|
1995
|
-
`;
|
1996
|
-
const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
|
2551
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
1997
2552
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
1998
2553
|
const RelativeTime = React__namespace.forwardRef(
|
1999
2554
|
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
@@ -2005,7 +2560,7 @@ const RelativeTime = React__namespace.forwardRef(
|
|
2005
2560
|
});
|
2006
2561
|
const unit = intervals.find((intervalUnit) => {
|
2007
2562
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2008
|
-
});
|
2563
|
+
}) ?? "seconds";
|
2009
2564
|
const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
|
2010
2565
|
const customInterval = customIntervals.find(
|
2011
2566
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2039,34 +2594,34 @@ const getDisplayName = ({
|
|
2039
2594
|
return email ?? "";
|
2040
2595
|
};
|
2041
2596
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2042
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2043
|
-
const statusVariant = status === "draft" ? "
|
2044
|
-
|
2597
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2598
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2599
|
+
const { formatMessage } = reactIntl.useIntl();
|
2600
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2601
|
+
id: `content-manager.containers.List.${status}`,
|
2602
|
+
defaultMessage: capitalise(status)
|
2603
|
+
}) }) });
|
2045
2604
|
};
|
2046
2605
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2047
2606
|
const { formatMessage } = reactIntl.useIntl();
|
2048
2607
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2608
|
+
const params = reactRouterDom.useParams();
|
2049
2609
|
const title = isCreating ? formatMessage({
|
2050
2610
|
id: "content-manager.containers.edit.title.new",
|
2051
2611
|
defaultMessage: "Create an entry"
|
2052
2612
|
}) : documentTitle;
|
2053
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2054
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2055
|
-
|
2056
|
-
designSystem.Flex,
|
2613
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2614
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2615
|
+
strapiAdmin.BackButton,
|
2057
2616
|
{
|
2058
|
-
|
2059
|
-
justifyContent: "space-between",
|
2060
|
-
paddingTop: 1,
|
2061
|
-
gap: "80px",
|
2062
|
-
alignItems: "flex-start",
|
2063
|
-
children: [
|
2064
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", children: title }),
|
2065
|
-
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2066
|
-
]
|
2617
|
+
fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
|
2067
2618
|
}
|
2068
2619
|
),
|
2069
|
-
|
2620
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2621
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2622
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2623
|
+
] }),
|
2624
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2070
2625
|
] });
|
2071
2626
|
};
|
2072
2627
|
const HeaderToolbar = () => {
|
@@ -2149,12 +2704,12 @@ const Information = ({ activeTab }) => {
|
|
2149
2704
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2150
2705
|
label: formatMessage({
|
2151
2706
|
id: "content-manager.containers.edit.information.last-published.label",
|
2152
|
-
defaultMessage: "
|
2707
|
+
defaultMessage: "Published"
|
2153
2708
|
}),
|
2154
2709
|
value: formatMessage(
|
2155
2710
|
{
|
2156
2711
|
id: "content-manager.containers.edit.information.last-published.value",
|
2157
|
-
defaultMessage: `
|
2712
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2158
2713
|
},
|
2159
2714
|
{
|
2160
2715
|
time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2167,12 +2722,12 @@ const Information = ({ activeTab }) => {
|
|
2167
2722
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2168
2723
|
label: formatMessage({
|
2169
2724
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2170
|
-
defaultMessage: "
|
2725
|
+
defaultMessage: "Updated"
|
2171
2726
|
}),
|
2172
2727
|
value: formatMessage(
|
2173
2728
|
{
|
2174
2729
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2175
|
-
defaultMessage: `
|
2730
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2176
2731
|
},
|
2177
2732
|
{
|
2178
2733
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2190,12 +2745,12 @@ const Information = ({ activeTab }) => {
|
|
2190
2745
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2191
2746
|
label: formatMessage({
|
2192
2747
|
id: "content-manager.containers.edit.information.document.label",
|
2193
|
-
defaultMessage: "
|
2748
|
+
defaultMessage: "Created"
|
2194
2749
|
}),
|
2195
2750
|
value: formatMessage(
|
2196
2751
|
{
|
2197
2752
|
id: "content-manager.containers.edit.information.document.value",
|
2198
|
-
defaultMessage: `
|
2753
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2199
2754
|
},
|
2200
2755
|
{
|
2201
2756
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2218,7 +2773,7 @@ const Information = ({ activeTab }) => {
|
|
2218
2773
|
borderColor: "neutral150",
|
2219
2774
|
direction: "column",
|
2220
2775
|
marginTop: 2,
|
2221
|
-
|
2776
|
+
tag: "dl",
|
2222
2777
|
padding: 5,
|
2223
2778
|
gap: 3,
|
2224
2779
|
alignItems: "flex-start",
|
@@ -2226,32 +2781,84 @@ const Information = ({ activeTab }) => {
|
|
2226
2781
|
marginRight: "-0.4rem",
|
2227
2782
|
width: "calc(100% + 8px)",
|
2228
2783
|
children: information.map((info) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
|
2229
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2230
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2784
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
|
2785
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
|
2231
2786
|
] }, info.label))
|
2232
2787
|
}
|
2233
2788
|
);
|
2234
2789
|
};
|
2235
2790
|
const HeaderActions = ({ actions: actions2 }) => {
|
2236
|
-
|
2237
|
-
|
2791
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2792
|
+
const handleClick = (action) => async (e) => {
|
2793
|
+
if (!("options" in action)) {
|
2794
|
+
const { onClick = () => false, dialog, id } = action;
|
2795
|
+
const muteDialog = await onClick(e);
|
2796
|
+
if (dialog && !muteDialog) {
|
2797
|
+
e.preventDefault();
|
2798
|
+
setDialogId(id);
|
2799
|
+
}
|
2800
|
+
}
|
2801
|
+
};
|
2802
|
+
const handleClose = () => {
|
2803
|
+
setDialogId(null);
|
2804
|
+
};
|
2805
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2806
|
+
if (action.options) {
|
2238
2807
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
2239
2808
|
designSystem.SingleSelect,
|
2240
2809
|
{
|
2241
2810
|
size: "S",
|
2242
|
-
disabled: action.disabled,
|
2243
|
-
"aria-label": action.label,
|
2244
2811
|
onChange: action.onSelect,
|
2245
|
-
|
2812
|
+
"aria-label": action.label,
|
2813
|
+
...action,
|
2246
2814
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2247
2815
|
},
|
2248
2816
|
action.id
|
2249
2817
|
);
|
2250
2818
|
} else {
|
2251
|
-
|
2819
|
+
if (action.type === "icon") {
|
2820
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2821
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2822
|
+
designSystem.IconButton,
|
2823
|
+
{
|
2824
|
+
disabled: action.disabled,
|
2825
|
+
label: action.label,
|
2826
|
+
size: "S",
|
2827
|
+
onClick: handleClick(action),
|
2828
|
+
children: action.icon
|
2829
|
+
}
|
2830
|
+
),
|
2831
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2832
|
+
HeaderActionDialog,
|
2833
|
+
{
|
2834
|
+
...action.dialog,
|
2835
|
+
isOpen: dialogId === action.id,
|
2836
|
+
onClose: handleClose
|
2837
|
+
}
|
2838
|
+
) : null
|
2839
|
+
] }, action.id);
|
2840
|
+
}
|
2252
2841
|
}
|
2253
2842
|
}) });
|
2254
2843
|
};
|
2844
|
+
const HeaderActionDialog = ({
|
2845
|
+
onClose,
|
2846
|
+
onCancel,
|
2847
|
+
title,
|
2848
|
+
content: Content,
|
2849
|
+
isOpen
|
2850
|
+
}) => {
|
2851
|
+
const handleClose = async () => {
|
2852
|
+
if (onCancel) {
|
2853
|
+
await onCancel();
|
2854
|
+
}
|
2855
|
+
onClose();
|
2856
|
+
};
|
2857
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2858
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2859
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2860
|
+
] }) });
|
2861
|
+
};
|
2255
2862
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2256
2863
|
const navigate = reactRouterDom.useNavigate();
|
2257
2864
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2260,7 +2867,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2260
2867
|
id: "app.links.configure-view",
|
2261
2868
|
defaultMessage: "Configure the view"
|
2262
2869
|
}),
|
2263
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2870
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
|
2264
2871
|
onClick: () => {
|
2265
2872
|
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2266
2873
|
},
|
@@ -2268,11 +2875,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2268
2875
|
};
|
2269
2876
|
};
|
2270
2877
|
ConfigureTheViewAction.type = "configure-the-view";
|
2271
|
-
const StyledCog = styled__default.default(Icons.Cog)`
|
2272
|
-
path {
|
2273
|
-
fill: currentColor;
|
2274
|
-
}
|
2275
|
-
`;
|
2276
2878
|
const EditTheModelAction = ({ model }) => {
|
2277
2879
|
const navigate = reactRouterDom.useNavigate();
|
2278
2880
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2281,7 +2883,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2281
2883
|
id: "content-manager.link-to-ctb",
|
2282
2884
|
defaultMessage: "Edit the model"
|
2283
2885
|
}),
|
2284
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2886
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
|
2285
2887
|
onClick: () => {
|
2286
2888
|
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2287
2889
|
},
|
@@ -2289,12 +2891,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2289
2891
|
};
|
2290
2892
|
};
|
2291
2893
|
EditTheModelAction.type = "edit-the-model";
|
2292
|
-
const
|
2293
|
-
path {
|
2294
|
-
fill: currentColor;
|
2295
|
-
}
|
2296
|
-
`;
|
2297
|
-
const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
2894
|
+
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2298
2895
|
const navigate = reactRouterDom.useNavigate();
|
2299
2896
|
const { formatMessage } = reactIntl.useIntl();
|
2300
2897
|
const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
|
@@ -2302,13 +2899,17 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2302
2899
|
const { delete: deleteAction } = useDocumentActions();
|
2303
2900
|
const { toggleNotification } = strapiAdmin.useNotification();
|
2304
2901
|
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2902
|
+
const isLocalized = document?.locale != null;
|
2305
2903
|
return {
|
2306
2904
|
disabled: !canDelete || !document,
|
2307
|
-
label: formatMessage(
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2905
|
+
label: formatMessage(
|
2906
|
+
{
|
2907
|
+
id: "content-manager.actions.delete.label",
|
2908
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2909
|
+
},
|
2910
|
+
{ isLocalized }
|
2911
|
+
),
|
2912
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2312
2913
|
dialog: {
|
2313
2914
|
type: "dialog",
|
2314
2915
|
title: formatMessage({
|
@@ -2317,7 +2918,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2317
2918
|
}),
|
2318
2919
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2319
2920
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2320
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2921
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2321
2922
|
id: "content-manager.actions.delete.dialog.body",
|
2322
2923
|
defaultMessage: "Are you sure?"
|
2323
2924
|
}) })
|
@@ -2362,13 +2963,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2362
2963
|
position: ["header", "table-row"]
|
2363
2964
|
};
|
2364
2965
|
};
|
2365
|
-
DeleteAction.type = "delete";
|
2366
|
-
const
|
2367
|
-
path {
|
2368
|
-
fill: currentColor;
|
2369
|
-
}
|
2370
|
-
`;
|
2371
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction];
|
2966
|
+
DeleteAction$1.type = "delete";
|
2967
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2372
2968
|
const Panels = () => {
|
2373
2969
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2374
2970
|
const [
|
@@ -2402,7 +2998,7 @@ const ActionsPanel = () => {
|
|
2402
2998
|
return {
|
2403
2999
|
title: formatMessage({
|
2404
3000
|
id: "content-manager.containers.edit.panels.default.title",
|
2405
|
-
defaultMessage: "
|
3001
|
+
defaultMessage: "Entry"
|
2406
3002
|
}),
|
2407
3003
|
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2408
3004
|
};
|
@@ -2442,7 +3038,7 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
|
2442
3038
|
designSystem.Flex,
|
2443
3039
|
{
|
2444
3040
|
ref,
|
2445
|
-
|
3041
|
+
tag: "aside",
|
2446
3042
|
"aria-labelledby": "additional-information",
|
2447
3043
|
background: "neutral0",
|
2448
3044
|
borderColor: "neutral150",
|
@@ -2457,17 +3053,594 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
|
2457
3053
|
justifyContent: "stretch",
|
2458
3054
|
alignItems: "flex-start",
|
2459
3055
|
children: [
|
2460
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
3056
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
2461
3057
|
children
|
2462
3058
|
]
|
2463
3059
|
}
|
2464
3060
|
);
|
2465
3061
|
});
|
2466
|
-
const
|
2467
|
-
|
3062
|
+
const ConfirmBulkActionDialog = ({
|
3063
|
+
onToggleDialog,
|
3064
|
+
isOpen = false,
|
3065
|
+
dialogBody,
|
3066
|
+
endAction
|
3067
|
+
}) => {
|
2468
3068
|
const { formatMessage } = reactIntl.useIntl();
|
2469
|
-
|
2470
|
-
|
3069
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
3070
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
|
3071
|
+
id: "app.components.ConfirmDialog.title",
|
3072
|
+
defaultMessage: "Confirmation"
|
3073
|
+
}) }),
|
3074
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3075
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3076
|
+
dialogBody
|
3077
|
+
] }) }),
|
3078
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
3079
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
|
3080
|
+
id: "app.components.Button.cancel",
|
3081
|
+
defaultMessage: "Cancel"
|
3082
|
+
}) }) }),
|
3083
|
+
endAction
|
3084
|
+
] })
|
3085
|
+
] }) });
|
3086
|
+
};
|
3087
|
+
const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
|
3088
|
+
const ConfirmDialogPublishAll = ({
|
3089
|
+
isOpen,
|
3090
|
+
onToggleDialog,
|
3091
|
+
isConfirmButtonLoading = false,
|
3092
|
+
onConfirm
|
3093
|
+
}) => {
|
3094
|
+
const { formatMessage } = reactIntl.useIntl();
|
3095
|
+
const selectedEntries = strapiAdmin.useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
|
3096
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
3097
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
3098
|
+
const { model, schema } = useDoc();
|
3099
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3100
|
+
const enableDraftRelationsCount = false;
|
3101
|
+
const {
|
3102
|
+
data: countDraftRelations = 0,
|
3103
|
+
isLoading,
|
3104
|
+
error
|
3105
|
+
} = useGetManyDraftRelationCountQuery(
|
3106
|
+
{
|
3107
|
+
model,
|
3108
|
+
documentIds: selectedEntries.map((entry) => entry.documentId),
|
3109
|
+
locale: query?.plugins?.i18n?.locale
|
3110
|
+
},
|
3111
|
+
{
|
3112
|
+
skip: !enableDraftRelationsCount
|
3113
|
+
}
|
3114
|
+
);
|
3115
|
+
React__namespace.useEffect(() => {
|
3116
|
+
if (error) {
|
3117
|
+
toggleNotification({ type: "danger", message: formatAPIError(error) });
|
3118
|
+
}
|
3119
|
+
}, [error, formatAPIError, toggleNotification]);
|
3120
|
+
if (error) {
|
3121
|
+
return null;
|
3122
|
+
}
|
3123
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
3124
|
+
ConfirmBulkActionDialog,
|
3125
|
+
{
|
3126
|
+
isOpen: isOpen && !isLoading,
|
3127
|
+
onToggleDialog,
|
3128
|
+
dialogBody: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
3129
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: [
|
3130
|
+
countDraftRelations > 0 && formatMessage(
|
3131
|
+
{
|
3132
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
3133
|
+
defaultMessage: "<b>{count} {count, plural, one { relation } other { relations } } out of {entities} { entities, plural, one { entry } other { entries } } {count, plural, one { is } other { are } }</b> not published yet and might lead to unexpected behavior. "
|
3134
|
+
},
|
3135
|
+
{
|
3136
|
+
b: BoldChunk$1,
|
3137
|
+
count: countDraftRelations,
|
3138
|
+
entities: selectedEntries.length
|
3139
|
+
}
|
3140
|
+
),
|
3141
|
+
formatMessage({
|
3142
|
+
id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
|
3143
|
+
defaultMessage: "Are you sure you want to publish these entries?"
|
3144
|
+
})
|
3145
|
+
] }),
|
3146
|
+
schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
|
3147
|
+
{
|
3148
|
+
id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
|
3149
|
+
defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
|
3150
|
+
},
|
3151
|
+
{
|
3152
|
+
em: Emphasis
|
3153
|
+
}
|
3154
|
+
) })
|
3155
|
+
] }),
|
3156
|
+
endAction: /* @__PURE__ */ jsxRuntime.jsx(
|
3157
|
+
designSystem.Button,
|
3158
|
+
{
|
3159
|
+
onClick: onConfirm,
|
3160
|
+
variant: "secondary",
|
3161
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
|
3162
|
+
loading: isConfirmButtonLoading,
|
3163
|
+
children: formatMessage({
|
3164
|
+
id: "app.utils.publish",
|
3165
|
+
defaultMessage: "Publish"
|
3166
|
+
})
|
3167
|
+
}
|
3168
|
+
)
|
3169
|
+
}
|
3170
|
+
);
|
3171
|
+
};
|
3172
|
+
const TypographyMaxWidth = styledComponents.styled(designSystem.Typography)`
|
3173
|
+
max-width: 300px;
|
3174
|
+
`;
|
3175
|
+
const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
3176
|
+
const messages = [];
|
3177
|
+
Object.entries(errors).forEach(([key, value]) => {
|
3178
|
+
const currentKey = parentKey ? `${parentKey}.${key}` : key;
|
3179
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
3180
|
+
if ("id" in value && "defaultMessage" in value) {
|
3181
|
+
messages.push(
|
3182
|
+
formatMessage(
|
3183
|
+
{
|
3184
|
+
id: `${value.id}.withField`,
|
3185
|
+
defaultMessage: value.defaultMessage
|
3186
|
+
},
|
3187
|
+
{ field: currentKey }
|
3188
|
+
)
|
3189
|
+
);
|
3190
|
+
} else {
|
3191
|
+
messages.push(
|
3192
|
+
...formatErrorMessages(
|
3193
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3194
|
+
value,
|
3195
|
+
currentKey,
|
3196
|
+
formatMessage
|
3197
|
+
)
|
3198
|
+
);
|
3199
|
+
}
|
3200
|
+
} else {
|
3201
|
+
messages.push(
|
3202
|
+
formatMessage(
|
3203
|
+
{
|
3204
|
+
id: `${value}.withField`,
|
3205
|
+
defaultMessage: value
|
3206
|
+
},
|
3207
|
+
{ field: currentKey }
|
3208
|
+
)
|
3209
|
+
);
|
3210
|
+
}
|
3211
|
+
});
|
3212
|
+
return messages;
|
3213
|
+
};
|
3214
|
+
const EntryValidationText = ({ validationErrors, status }) => {
|
3215
|
+
const { formatMessage } = reactIntl.useIntl();
|
3216
|
+
if (validationErrors) {
|
3217
|
+
const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
|
3218
|
+
" "
|
3219
|
+
);
|
3220
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3221
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CrossCircle, { fill: "danger600" }),
|
3222
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
|
3223
|
+
] });
|
3224
|
+
}
|
3225
|
+
if (status === "published") {
|
3226
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3227
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
|
3228
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
|
3229
|
+
id: "content-manager.bulk-publish.already-published",
|
3230
|
+
defaultMessage: "Already Published"
|
3231
|
+
}) })
|
3232
|
+
] });
|
3233
|
+
}
|
3234
|
+
if (status === "modified") {
|
3235
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3236
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.ArrowsCounterClockwise, { fill: "alternative600" }),
|
3237
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3238
|
+
id: "content-manager.bulk-publish.modified",
|
3239
|
+
defaultMessage: "Ready to publish changes"
|
3240
|
+
}) })
|
3241
|
+
] });
|
3242
|
+
}
|
3243
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3244
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
|
3245
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3246
|
+
id: "app.utils.ready-to-publish",
|
3247
|
+
defaultMessage: "Ready to publish"
|
3248
|
+
}) })
|
3249
|
+
] });
|
3250
|
+
};
|
3251
|
+
const TABLE_HEADERS = [
|
3252
|
+
{ name: "id", label: "id" },
|
3253
|
+
{ name: "name", label: "name" },
|
3254
|
+
{ name: "status", label: "status" },
|
3255
|
+
{ name: "publicationStatus", label: "Publication status" }
|
3256
|
+
];
|
3257
|
+
const SelectedEntriesTableContent = ({
|
3258
|
+
isPublishing,
|
3259
|
+
rowsToDisplay = [],
|
3260
|
+
entriesToPublish = [],
|
3261
|
+
validationErrors = {}
|
3262
|
+
}) => {
|
3263
|
+
const { pathname } = reactRouterDom.useLocation();
|
3264
|
+
const { formatMessage } = reactIntl.useIntl();
|
3265
|
+
const {
|
3266
|
+
list: {
|
3267
|
+
settings: { mainField }
|
3268
|
+
}
|
3269
|
+
} = useDocLayout();
|
3270
|
+
const shouldDisplayMainField = mainField != null && mainField !== "id";
|
3271
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Content, { children: [
|
3272
|
+
/* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Head, { children: [
|
3273
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCheckboxCell, {}),
|
3274
|
+
TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
|
3275
|
+
(head) => /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCell, { ...head }, head.name)
|
3276
|
+
)
|
3277
|
+
] }),
|
3278
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Loading, {}),
|
3279
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
|
3280
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, { id: row.id }),
|
3281
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row.id }) }),
|
3282
|
+
shouldDisplayMainField && /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row[mainField] }) }),
|
3283
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
|
3284
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3285
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3286
|
+
id: "content-manager.success.record.publishing",
|
3287
|
+
defaultMessage: "Publishing..."
|
3288
|
+
}) }),
|
3289
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true })
|
3290
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
3291
|
+
EntryValidationText,
|
3292
|
+
{
|
3293
|
+
validationErrors: validationErrors[row.documentId],
|
3294
|
+
status: row.status
|
3295
|
+
}
|
3296
|
+
) }),
|
3297
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3298
|
+
designSystem.IconButton,
|
3299
|
+
{
|
3300
|
+
tag: reactRouterDom.Link,
|
3301
|
+
to: {
|
3302
|
+
pathname: `${pathname}/${row.documentId}`,
|
3303
|
+
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3304
|
+
},
|
3305
|
+
state: { from: pathname },
|
3306
|
+
label: formatMessage({
|
3307
|
+
id: "content-manager.bulk-publish.edit",
|
3308
|
+
defaultMessage: "Edit"
|
3309
|
+
}),
|
3310
|
+
target: "_blank",
|
3311
|
+
marginLeft: "auto",
|
3312
|
+
variant: "ghost",
|
3313
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3314
|
+
}
|
3315
|
+
) }) })
|
3316
|
+
] }, row.id)) })
|
3317
|
+
] });
|
3318
|
+
};
|
3319
|
+
const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
|
3320
|
+
const SelectedEntriesModalContent = ({
|
3321
|
+
listViewSelectedEntries,
|
3322
|
+
toggleModal,
|
3323
|
+
setListViewSelectedDocuments,
|
3324
|
+
model
|
3325
|
+
}) => {
|
3326
|
+
const { formatMessage } = reactIntl.useIntl();
|
3327
|
+
const { schema, components } = useContentTypeSchema(model);
|
3328
|
+
const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
|
3329
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3330
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3331
|
+
const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
|
3332
|
+
{
|
3333
|
+
model,
|
3334
|
+
params: {
|
3335
|
+
page: "1",
|
3336
|
+
pageSize: documentIds.length.toString(),
|
3337
|
+
sort: query.sort,
|
3338
|
+
filters: {
|
3339
|
+
documentId: {
|
3340
|
+
$in: documentIds
|
3341
|
+
}
|
3342
|
+
},
|
3343
|
+
locale: query.plugins?.i18n?.locale
|
3344
|
+
}
|
3345
|
+
},
|
3346
|
+
{
|
3347
|
+
selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
|
3348
|
+
}
|
3349
|
+
);
|
3350
|
+
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3351
|
+
if (data.length > 0 && schema) {
|
3352
|
+
const validate = createYupSchema(
|
3353
|
+
schema.attributes,
|
3354
|
+
components,
|
3355
|
+
// Since this is the "Publish" action, the validation
|
3356
|
+
// schema must enforce the rules for published entities
|
3357
|
+
{ status: "published" }
|
3358
|
+
);
|
3359
|
+
const validationErrors2 = {};
|
3360
|
+
const rows2 = data.map((entry) => {
|
3361
|
+
try {
|
3362
|
+
validate.validateSync(entry, { abortEarly: false });
|
3363
|
+
return entry;
|
3364
|
+
} catch (e) {
|
3365
|
+
if (e instanceof yup.ValidationError) {
|
3366
|
+
validationErrors2[entry.documentId] = strapiAdmin.getYupValidationErrors(e);
|
3367
|
+
}
|
3368
|
+
return entry;
|
3369
|
+
}
|
3370
|
+
});
|
3371
|
+
return { rows: rows2, validationErrors: validationErrors2 };
|
3372
|
+
}
|
3373
|
+
return {
|
3374
|
+
rows: [],
|
3375
|
+
validationErrors: {}
|
3376
|
+
};
|
3377
|
+
}, [components, data, schema]);
|
3378
|
+
const [publishedCount, setPublishedCount] = React__namespace.useState(0);
|
3379
|
+
const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
|
3380
|
+
const { publishMany: bulkPublishAction } = useDocumentActions();
|
3381
|
+
const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
|
3382
|
+
const selectedRows = strapiAdmin.useTable("publishAction", (state) => state.selectedRows);
|
3383
|
+
const selectedEntries = rows.filter(
|
3384
|
+
(entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
|
3385
|
+
);
|
3386
|
+
const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
|
3387
|
+
const selectedEntriesWithErrorsCount = selectedEntries.filter(
|
3388
|
+
({ documentId }) => validationErrors[documentId]
|
3389
|
+
).length;
|
3390
|
+
const selectedEntriesPublished = selectedEntries.filter(
|
3391
|
+
({ status }) => status === "published"
|
3392
|
+
).length;
|
3393
|
+
const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
|
3394
|
+
const toggleDialog = () => setIsDialogOpen((prev) => !prev);
|
3395
|
+
const handleConfirmBulkPublish = async () => {
|
3396
|
+
toggleDialog();
|
3397
|
+
const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
|
3398
|
+
if (!("error" in res)) {
|
3399
|
+
setPublishedCount(res.count);
|
3400
|
+
const unpublishedEntries = rows.filter((row) => {
|
3401
|
+
return !entriesToPublish.includes(row.documentId);
|
3402
|
+
});
|
3403
|
+
setListViewSelectedDocuments(unpublishedEntries);
|
3404
|
+
}
|
3405
|
+
};
|
3406
|
+
const getFormattedCountMessage = () => {
|
3407
|
+
if (publishedCount) {
|
3408
|
+
return formatMessage(
|
3409
|
+
{
|
3410
|
+
id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
|
3411
|
+
defaultMessage: "<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} published. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
|
3412
|
+
},
|
3413
|
+
{
|
3414
|
+
publishedCount,
|
3415
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3416
|
+
b: BoldChunk
|
3417
|
+
}
|
3418
|
+
);
|
3419
|
+
}
|
3420
|
+
return formatMessage(
|
3421
|
+
{
|
3422
|
+
id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
|
3423
|
+
defaultMessage: "<b>{alreadyPublishedCount}</b> {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
|
3424
|
+
},
|
3425
|
+
{
|
3426
|
+
readyToPublishCount: selectedEntriesWithNoErrorsCount,
|
3427
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3428
|
+
alreadyPublishedCount: selectedEntriesPublished,
|
3429
|
+
b: BoldChunk
|
3430
|
+
}
|
3431
|
+
);
|
3432
|
+
};
|
3433
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
3434
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
|
3435
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
|
3436
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3437
|
+
SelectedEntriesTableContent,
|
3438
|
+
{
|
3439
|
+
isPublishing: isSubmittingForm,
|
3440
|
+
rowsToDisplay: rows,
|
3441
|
+
entriesToPublish,
|
3442
|
+
validationErrors
|
3443
|
+
}
|
3444
|
+
) })
|
3445
|
+
] }),
|
3446
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3447
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
|
3448
|
+
id: "app.components.Button.cancel",
|
3449
|
+
defaultMessage: "Cancel"
|
3450
|
+
}) }),
|
3451
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3452
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
|
3453
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3454
|
+
designSystem.Button,
|
3455
|
+
{
|
3456
|
+
onClick: toggleDialog,
|
3457
|
+
disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
|
3458
|
+
loading: isSubmittingForm,
|
3459
|
+
children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
|
3460
|
+
}
|
3461
|
+
)
|
3462
|
+
] })
|
3463
|
+
] }),
|
3464
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3465
|
+
ConfirmDialogPublishAll,
|
3466
|
+
{
|
3467
|
+
isOpen: isDialogOpen,
|
3468
|
+
onToggleDialog: toggleDialog,
|
3469
|
+
isConfirmButtonLoading: isSubmittingForm,
|
3470
|
+
onConfirm: handleConfirmBulkPublish
|
3471
|
+
}
|
3472
|
+
)
|
3473
|
+
] });
|
3474
|
+
};
|
3475
|
+
const PublishAction = ({ documents, model }) => {
|
3476
|
+
const { formatMessage } = reactIntl.useIntl();
|
3477
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3478
|
+
const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
|
3479
|
+
const setListViewSelectedDocuments = strapiAdmin.useTable("publishAction", (state) => state.selectRow);
|
3480
|
+
const refetchList = () => {
|
3481
|
+
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3482
|
+
};
|
3483
|
+
if (!showPublishButton)
|
3484
|
+
return null;
|
3485
|
+
return {
|
3486
|
+
actionType: "publish",
|
3487
|
+
variant: "tertiary",
|
3488
|
+
label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
|
3489
|
+
dialog: {
|
3490
|
+
type: "modal",
|
3491
|
+
title: formatMessage({
|
3492
|
+
id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
|
3493
|
+
defaultMessage: "Publish entries"
|
3494
|
+
}),
|
3495
|
+
content: ({ onClose }) => {
|
3496
|
+
return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3497
|
+
SelectedEntriesModalContent,
|
3498
|
+
{
|
3499
|
+
listViewSelectedEntries: documents,
|
3500
|
+
toggleModal: () => {
|
3501
|
+
onClose();
|
3502
|
+
refetchList();
|
3503
|
+
},
|
3504
|
+
setListViewSelectedDocuments,
|
3505
|
+
model
|
3506
|
+
}
|
3507
|
+
) });
|
3508
|
+
},
|
3509
|
+
onClose: () => {
|
3510
|
+
refetchList();
|
3511
|
+
}
|
3512
|
+
}
|
3513
|
+
};
|
3514
|
+
};
|
3515
|
+
const BulkActionsRenderer = () => {
|
3516
|
+
const plugins = strapiAdmin.useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
|
3517
|
+
const { model, collectionType } = useDoc();
|
3518
|
+
const { selectedRows } = strapiAdmin.useTable("BulkActionsRenderer", (state) => state);
|
3519
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3520
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3521
|
+
{
|
3522
|
+
props: {
|
3523
|
+
model,
|
3524
|
+
collectionType,
|
3525
|
+
documents: selectedRows
|
3526
|
+
},
|
3527
|
+
descriptions: plugins["content-manager"].apis.getBulkActions(),
|
3528
|
+
children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...action }, action.id))
|
3529
|
+
}
|
3530
|
+
) });
|
3531
|
+
};
|
3532
|
+
const DeleteAction = ({ documents, model }) => {
|
3533
|
+
const { formatMessage } = reactIntl.useIntl();
|
3534
|
+
const { schema: contentType } = useDoc();
|
3535
|
+
const selectRow = strapiAdmin.useTable("DeleteAction", (state) => state.selectRow);
|
3536
|
+
const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
|
3537
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3538
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3539
|
+
const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
|
3540
|
+
const { deleteMany: bulkDeleteAction } = useDocumentActions();
|
3541
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3542
|
+
const handleConfirmBulkDelete = async () => {
|
3543
|
+
const res = await bulkDeleteAction({
|
3544
|
+
documentIds,
|
3545
|
+
model,
|
3546
|
+
params
|
3547
|
+
});
|
3548
|
+
if (!("error" in res)) {
|
3549
|
+
selectRow([]);
|
3550
|
+
}
|
3551
|
+
};
|
3552
|
+
if (!hasDeletePermission)
|
3553
|
+
return null;
|
3554
|
+
return {
|
3555
|
+
variant: "danger-light",
|
3556
|
+
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
3557
|
+
dialog: {
|
3558
|
+
type: "dialog",
|
3559
|
+
title: formatMessage({
|
3560
|
+
id: "app.components.ConfirmDialog.title",
|
3561
|
+
defaultMessage: "Confirmation"
|
3562
|
+
}),
|
3563
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3564
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3565
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3566
|
+
id: "popUpWarning.bodyMessage.contentType.delete.all",
|
3567
|
+
defaultMessage: "Are you sure you want to delete these entries?"
|
3568
|
+
}) }),
|
3569
|
+
hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
|
3570
|
+
{
|
3571
|
+
id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
|
3572
|
+
defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
|
3573
|
+
},
|
3574
|
+
{
|
3575
|
+
em: Emphasis
|
3576
|
+
}
|
3577
|
+
) }) })
|
3578
|
+
] }),
|
3579
|
+
onConfirm: handleConfirmBulkDelete
|
3580
|
+
}
|
3581
|
+
};
|
3582
|
+
};
|
3583
|
+
DeleteAction.type = "delete";
|
3584
|
+
const UnpublishAction = ({ documents, model }) => {
|
3585
|
+
const { formatMessage } = reactIntl.useIntl();
|
3586
|
+
const { schema } = useDoc();
|
3587
|
+
const selectRow = strapiAdmin.useTable("UnpublishAction", (state) => state.selectRow);
|
3588
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3589
|
+
const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
|
3590
|
+
const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
|
3591
|
+
const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
|
3592
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3593
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3594
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3595
|
+
const handleConfirmBulkUnpublish = async () => {
|
3596
|
+
const data = await bulkUnpublishAction({ documentIds, model, params });
|
3597
|
+
if (!("error" in data)) {
|
3598
|
+
selectRow([]);
|
3599
|
+
}
|
3600
|
+
};
|
3601
|
+
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3602
|
+
if (!showUnpublishButton)
|
3603
|
+
return null;
|
3604
|
+
return {
|
3605
|
+
variant: "tertiary",
|
3606
|
+
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
3607
|
+
dialog: {
|
3608
|
+
type: "dialog",
|
3609
|
+
title: formatMessage({
|
3610
|
+
id: "app.components.ConfirmDialog.title",
|
3611
|
+
defaultMessage: "Confirmation"
|
3612
|
+
}),
|
3613
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3614
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3615
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3616
|
+
id: "popUpWarning.bodyMessage.contentType.unpublish.all",
|
3617
|
+
defaultMessage: "Are you sure you want to unpublish these entries?"
|
3618
|
+
}) }),
|
3619
|
+
hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
|
3620
|
+
{
|
3621
|
+
id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
|
3622
|
+
defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
|
3623
|
+
},
|
3624
|
+
{
|
3625
|
+
em: Emphasis
|
3626
|
+
}
|
3627
|
+
) }) })
|
3628
|
+
] }),
|
3629
|
+
confirmButton: formatMessage({
|
3630
|
+
id: "app.utils.unpublish",
|
3631
|
+
defaultMessage: "Unpublish"
|
3632
|
+
}),
|
3633
|
+
onConfirm: handleConfirmBulkUnpublish
|
3634
|
+
}
|
3635
|
+
};
|
3636
|
+
};
|
3637
|
+
UnpublishAction.type = "unpublish";
|
3638
|
+
const Emphasis = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
|
3639
|
+
const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
|
3640
|
+
const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
3641
|
+
const { formatMessage } = reactIntl.useIntl();
|
3642
|
+
const getDefaultErrorMessage = (reason) => {
|
3643
|
+
switch (reason) {
|
2471
3644
|
case "relation":
|
2472
3645
|
return "Duplicating the relation could remove it from the original entry.";
|
2473
3646
|
case "unique":
|
@@ -2495,7 +3668,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
|
2495
3668
|
hasRadius: true,
|
2496
3669
|
padding: 6,
|
2497
3670
|
children: [
|
2498
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row",
|
3671
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", tag: "li", children: [
|
2499
3672
|
pathSegment,
|
2500
3673
|
index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
2501
3674
|
Icons.ChevronRight,
|
@@ -2507,7 +3680,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
|
2507
3680
|
}
|
2508
3681
|
)
|
2509
3682
|
] }, index2)) }),
|
2510
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
3683
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
|
2511
3684
|
id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
|
2512
3685
|
defaultMessage: getDefaultErrorMessage(reason)
|
2513
3686
|
}) })
|
@@ -2532,7 +3705,7 @@ const TableActions = ({ document }) => {
|
|
2532
3705
|
strapiAdmin.DescriptionComponentRenderer,
|
2533
3706
|
{
|
2534
3707
|
props,
|
2535
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3708
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
2536
3709
|
children: (actions2) => {
|
2537
3710
|
const tableRowActions = actions2.filter((action) => {
|
2538
3711
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -2591,7 +3764,7 @@ const EditAction = ({ documentId }) => {
|
|
2591
3764
|
};
|
2592
3765
|
};
|
2593
3766
|
EditAction.type = "edit";
|
2594
|
-
const StyledPencil =
|
3767
|
+
const StyledPencil = styledComponents.styled(Icons.Pencil)`
|
2595
3768
|
path {
|
2596
3769
|
fill: currentColor;
|
2597
3770
|
}
|
@@ -2643,7 +3816,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
2643
3816
|
}),
|
2644
3817
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
2645
3818
|
footer: ({ onClose }) => {
|
2646
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3819
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
2647
3820
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
2648
3821
|
id: "cancel",
|
2649
3822
|
defaultMessage: "Cancel"
|
@@ -2651,7 +3824,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
2651
3824
|
/* @__PURE__ */ jsxRuntime.jsx(
|
2652
3825
|
designSystem.LinkButton,
|
2653
3826
|
{
|
2654
|
-
|
3827
|
+
tag: reactRouterDom.NavLink,
|
2655
3828
|
to: {
|
2656
3829
|
pathname: `clone/${documentId}`
|
2657
3830
|
},
|
@@ -2667,7 +3840,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
2667
3840
|
};
|
2668
3841
|
};
|
2669
3842
|
CloneAction.type = "clone";
|
2670
|
-
const StyledDuplicate =
|
3843
|
+
const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
|
2671
3844
|
path {
|
2672
3845
|
fill: currentColor;
|
2673
3846
|
}
|
@@ -2684,8 +3857,7 @@ class ContentManagerPlugin {
|
|
2684
3857
|
documentActions = [
|
2685
3858
|
...DEFAULT_ACTIONS,
|
2686
3859
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
2687
|
-
...DEFAULT_HEADER_ACTIONS
|
2688
|
-
HistoryAction
|
3860
|
+
...DEFAULT_HEADER_ACTIONS
|
2689
3861
|
];
|
2690
3862
|
editViewSidePanels = [ActionsPanel];
|
2691
3863
|
headerActions = [];
|
@@ -2774,6 +3946,62 @@ const getPrintableType = (value) => {
|
|
2774
3946
|
}
|
2775
3947
|
return nativeType;
|
2776
3948
|
};
|
3949
|
+
const HistoryAction = ({ model, document }) => {
|
3950
|
+
const { formatMessage } = reactIntl.useIntl();
|
3951
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3952
|
+
const navigate = reactRouterDom.useNavigate();
|
3953
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
3954
|
+
const { pathname } = reactRouterDom.useLocation();
|
3955
|
+
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
3956
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3957
|
+
return null;
|
3958
|
+
}
|
3959
|
+
const handleOnClick = () => {
|
3960
|
+
const destination = { pathname: "history", search: pluginsQueryParams };
|
3961
|
+
trackUsage("willNavigate", {
|
3962
|
+
from: pathname,
|
3963
|
+
to: `${pathname}/${destination.pathname}`
|
3964
|
+
});
|
3965
|
+
navigate(destination);
|
3966
|
+
};
|
3967
|
+
return {
|
3968
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
3969
|
+
label: formatMessage({
|
3970
|
+
id: "content-manager.history.document-action",
|
3971
|
+
defaultMessage: "Content History"
|
3972
|
+
}),
|
3973
|
+
onClick: handleOnClick,
|
3974
|
+
disabled: (
|
3975
|
+
/**
|
3976
|
+
* The user is creating a new document.
|
3977
|
+
* It hasn't been saved yet, so there's no history to go to
|
3978
|
+
*/
|
3979
|
+
!document || /**
|
3980
|
+
* The document has been created but the current dimension has never been saved.
|
3981
|
+
* For example, the user is creating a new locale in an existing document,
|
3982
|
+
* so there's no history for the document in that locale
|
3983
|
+
*/
|
3984
|
+
!document.id || /**
|
3985
|
+
* History is only available for content types created by the user.
|
3986
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3987
|
+
* which start with `admin::` or `plugin::`
|
3988
|
+
*/
|
3989
|
+
!model.startsWith("api::")
|
3990
|
+
),
|
3991
|
+
position: "header"
|
3992
|
+
};
|
3993
|
+
};
|
3994
|
+
HistoryAction.type = "history";
|
3995
|
+
const historyAdmin = {
|
3996
|
+
bootstrap(app) {
|
3997
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3998
|
+
addDocumentAction((actions2) => {
|
3999
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
4000
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
4001
|
+
return actions2;
|
4002
|
+
});
|
4003
|
+
}
|
4004
|
+
};
|
2777
4005
|
const initialState = {
|
2778
4006
|
collectionTypeLinks: [],
|
2779
4007
|
components: [],
|
@@ -2810,316 +4038,78 @@ const { setInitialData } = actions;
|
|
2810
4038
|
const reducer = toolkit.combineReducers({
|
2811
4039
|
app: reducer$1
|
2812
4040
|
});
|
2813
|
-
const
|
2814
|
-
/**
|
2815
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2816
|
-
* @constant
|
2817
|
-
* @type {string}
|
2818
|
-
*/
|
2819
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2820
|
-
/**
|
2821
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2822
|
-
* @constant
|
2823
|
-
* @type {string}
|
2824
|
-
*/
|
2825
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2826
|
-
/**
|
2827
|
-
* Hook that allows to mutate the CM's edit view layout
|
2828
|
-
* @constant
|
2829
|
-
* @type {string}
|
2830
|
-
*/
|
2831
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2832
|
-
/**
|
2833
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2834
|
-
* @constant
|
2835
|
-
* @type {string}
|
2836
|
-
*/
|
2837
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2838
|
-
};
|
2839
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
4041
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
2840
4042
|
endpoints: (builder) => ({
|
2841
|
-
|
2842
|
-
query
|
2843
|
-
|
2844
|
-
|
2845
|
-
|
2846
|
-
|
2847
|
-
|
2848
|
-
|
2849
|
-
|
2850
|
-
|
2851
|
-
}),
|
2852
|
-
getAllContentTypeSettings: builder.query({
|
2853
|
-
query: () => "/content-manager/content-types-settings",
|
2854
|
-
transformResponse: (response) => response.data,
|
2855
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2856
|
-
}),
|
2857
|
-
updateContentTypeConfiguration: builder.mutation({
|
2858
|
-
query: ({ uid, ...body }) => ({
|
2859
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2860
|
-
method: "PUT",
|
2861
|
-
data: body
|
2862
|
-
}),
|
2863
|
-
transformResponse: (response) => response.data,
|
2864
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2865
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2866
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2867
|
-
// Is this necessary?
|
2868
|
-
{ type: "InitialData" }
|
2869
|
-
]
|
4043
|
+
getPreviewUrl: builder.query({
|
4044
|
+
query({ query, params }) {
|
4045
|
+
return {
|
4046
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4047
|
+
method: "GET",
|
4048
|
+
config: {
|
4049
|
+
params: query
|
4050
|
+
}
|
4051
|
+
};
|
4052
|
+
}
|
2870
4053
|
})
|
2871
4054
|
})
|
2872
4055
|
});
|
2873
|
-
const {
|
2874
|
-
|
2875
|
-
|
2876
|
-
|
2877
|
-
} =
|
2878
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2879
|
-
const { type } = attribute;
|
2880
|
-
if (type === "relation") {
|
2881
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2882
|
-
}
|
2883
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2884
|
-
};
|
2885
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2886
|
-
if (!mainFieldName) {
|
2887
|
-
return void 0;
|
2888
|
-
}
|
2889
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2890
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2891
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2892
|
-
);
|
2893
|
-
return {
|
2894
|
-
name: mainFieldName,
|
2895
|
-
type: mainFieldType ?? "string"
|
2896
|
-
};
|
2897
|
-
};
|
2898
|
-
const DEFAULT_SETTINGS = {
|
2899
|
-
bulkable: false,
|
2900
|
-
filterable: false,
|
2901
|
-
searchable: false,
|
2902
|
-
pagination: false,
|
2903
|
-
defaultSortBy: "",
|
2904
|
-
defaultSortOrder: "asc",
|
2905
|
-
mainField: "id",
|
2906
|
-
pageSize: 10
|
2907
|
-
};
|
2908
|
-
const useDocumentLayout = (model) => {
|
2909
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
4056
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4057
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4058
|
+
const { formatMessage } = reactIntl.useIntl();
|
4059
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
4060
|
+
const { pathname } = reactRouterDom.useLocation();
|
2910
4061
|
const [{ query }] = strapiAdmin.useQueryParams();
|
2911
|
-
const
|
2912
|
-
|
2913
|
-
|
2914
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2915
|
-
const {
|
2916
|
-
data,
|
2917
|
-
isLoading: isLoadingConfigs,
|
2918
|
-
error,
|
2919
|
-
isFetching: isFetchingConfigs
|
2920
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2921
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2922
|
-
React__namespace.useEffect(() => {
|
2923
|
-
if (error) {
|
2924
|
-
toggleNotification({
|
2925
|
-
type: "danger",
|
2926
|
-
message: formatAPIError(error)
|
2927
|
-
});
|
2928
|
-
}
|
2929
|
-
}, [error, formatAPIError, toggleNotification]);
|
2930
|
-
const editLayout = React__namespace.useMemo(
|
2931
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2932
|
-
layout: [],
|
2933
|
-
components: {},
|
2934
|
-
metadatas: {},
|
2935
|
-
options: {},
|
2936
|
-
settings: DEFAULT_SETTINGS
|
4062
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4063
|
+
params: {
|
4064
|
+
contentType: model
|
2937
4065
|
},
|
2938
|
-
|
2939
|
-
|
2940
|
-
|
2941
|
-
|
2942
|
-
layout: [],
|
2943
|
-
metadatas: {},
|
2944
|
-
options: {},
|
2945
|
-
settings: DEFAULT_SETTINGS
|
2946
|
-
};
|
2947
|
-
}, [data, isLoading, schemas, schema, components]);
|
2948
|
-
const { layout: edit } = React__namespace.useMemo(
|
2949
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2950
|
-
layout: editLayout,
|
2951
|
-
query
|
2952
|
-
}),
|
2953
|
-
[editLayout, query, runHookWaterfall]
|
2954
|
-
);
|
2955
|
-
return {
|
2956
|
-
error,
|
2957
|
-
isLoading,
|
2958
|
-
edit,
|
2959
|
-
list: listLayout
|
2960
|
-
};
|
2961
|
-
};
|
2962
|
-
const useDocLayout = () => {
|
2963
|
-
const { model } = useDoc();
|
2964
|
-
return useDocumentLayout(model);
|
2965
|
-
};
|
2966
|
-
const formatEditLayout = (data, {
|
2967
|
-
schemas,
|
2968
|
-
schema,
|
2969
|
-
components
|
2970
|
-
}) => {
|
2971
|
-
let currentPanelIndex = 0;
|
2972
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2973
|
-
data.contentType.layouts.edit,
|
2974
|
-
schema?.attributes,
|
2975
|
-
data.contentType.metadatas,
|
2976
|
-
{ configurations: data.components, schemas: components },
|
2977
|
-
schemas
|
2978
|
-
).reduce((panels, row) => {
|
2979
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2980
|
-
panels.push([row]);
|
2981
|
-
currentPanelIndex += 2;
|
2982
|
-
} else {
|
2983
|
-
if (!panels[currentPanelIndex]) {
|
2984
|
-
panels.push([]);
|
2985
|
-
}
|
2986
|
-
panels[currentPanelIndex].push(row);
|
2987
|
-
}
|
2988
|
-
return panels;
|
2989
|
-
}, []);
|
2990
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2991
|
-
(acc, [uid, configuration]) => {
|
2992
|
-
acc[uid] = {
|
2993
|
-
layout: convertEditLayoutToFieldLayouts(
|
2994
|
-
configuration.layouts.edit,
|
2995
|
-
components[uid].attributes,
|
2996
|
-
configuration.metadatas
|
2997
|
-
),
|
2998
|
-
settings: {
|
2999
|
-
...configuration.settings,
|
3000
|
-
icon: components[uid].info.icon,
|
3001
|
-
displayName: components[uid].info.displayName
|
3002
|
-
}
|
3003
|
-
};
|
3004
|
-
return acc;
|
3005
|
-
},
|
3006
|
-
{}
|
3007
|
-
);
|
3008
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
3009
|
-
(acc, [attribute, metadata]) => {
|
3010
|
-
return {
|
3011
|
-
...acc,
|
3012
|
-
[attribute]: metadata.edit
|
3013
|
-
};
|
3014
|
-
},
|
3015
|
-
{}
|
3016
|
-
);
|
3017
|
-
return {
|
3018
|
-
layout: panelledEditAttributes,
|
3019
|
-
components: componentEditAttributes,
|
3020
|
-
metadatas: editMetadatas,
|
3021
|
-
settings: {
|
3022
|
-
...data.contentType.settings,
|
3023
|
-
displayName: schema?.info.displayName
|
3024
|
-
},
|
3025
|
-
options: {
|
3026
|
-
...schema?.options,
|
3027
|
-
...schema?.pluginOptions,
|
3028
|
-
...data.contentType.options
|
4066
|
+
query: {
|
4067
|
+
documentId,
|
4068
|
+
locale: document?.locale,
|
4069
|
+
status: document?.status
|
3029
4070
|
}
|
4071
|
+
});
|
4072
|
+
if (!data?.data?.url || error) {
|
4073
|
+
return null;
|
4074
|
+
}
|
4075
|
+
const trackNavigation = () => {
|
4076
|
+
const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
|
4077
|
+
trackUsage("willNavigate", { from: pathname, to: destinationPathname });
|
3030
4078
|
};
|
3031
|
-
};
|
3032
|
-
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
3033
|
-
return rows.map(
|
3034
|
-
(row) => row.map((field) => {
|
3035
|
-
const attribute = attributes[field.name];
|
3036
|
-
if (!attribute) {
|
3037
|
-
return null;
|
3038
|
-
}
|
3039
|
-
const { edit: metadata } = metadatas[field.name];
|
3040
|
-
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
3041
|
-
return {
|
3042
|
-
attribute,
|
3043
|
-
disabled: !metadata.editable,
|
3044
|
-
hint: metadata.description,
|
3045
|
-
label: metadata.label ?? "",
|
3046
|
-
name: field.name,
|
3047
|
-
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
3048
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
3049
|
-
schemas,
|
3050
|
-
components: components?.schemas ?? {}
|
3051
|
-
}),
|
3052
|
-
placeholder: metadata.placeholder ?? "",
|
3053
|
-
required: attribute.required ?? false,
|
3054
|
-
size: field.size,
|
3055
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
3056
|
-
visible: metadata.visible ?? true,
|
3057
|
-
type: attribute.type
|
3058
|
-
};
|
3059
|
-
}).filter((field) => field !== null)
|
3060
|
-
);
|
3061
|
-
};
|
3062
|
-
const formatListLayout = (data, {
|
3063
|
-
schemas,
|
3064
|
-
schema,
|
3065
|
-
components
|
3066
|
-
}) => {
|
3067
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
3068
|
-
(acc, [attribute, metadata]) => {
|
3069
|
-
return {
|
3070
|
-
...acc,
|
3071
|
-
[attribute]: metadata.list
|
3072
|
-
};
|
3073
|
-
},
|
3074
|
-
{}
|
3075
|
-
);
|
3076
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
3077
|
-
data.contentType.layouts.list,
|
3078
|
-
schema?.attributes,
|
3079
|
-
listMetadatas,
|
3080
|
-
{ configurations: data.components, schemas: components },
|
3081
|
-
schemas
|
3082
|
-
);
|
3083
4079
|
return {
|
3084
|
-
|
3085
|
-
|
3086
|
-
|
3087
|
-
|
3088
|
-
|
3089
|
-
|
3090
|
-
|
3091
|
-
|
4080
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4081
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
|
4082
|
+
designSystem.Button,
|
4083
|
+
{
|
4084
|
+
variant: "tertiary",
|
4085
|
+
tag: reactRouterDom.Link,
|
4086
|
+
to: { pathname: "preview", search: qs.stringify(query, { encode: false }) },
|
4087
|
+
onClick: trackNavigation,
|
4088
|
+
flex: "auto",
|
4089
|
+
children: formatMessage({
|
4090
|
+
id: "content-manager.preview.panel.button",
|
4091
|
+
defaultMessage: "Open preview"
|
4092
|
+
})
|
4093
|
+
}
|
4094
|
+
) })
|
3092
4095
|
};
|
3093
4096
|
};
|
3094
|
-
const
|
3095
|
-
|
3096
|
-
|
3097
|
-
if (!
|
3098
|
-
return
|
4097
|
+
const FEATURE_ID = "preview";
|
4098
|
+
const previewAdmin = {
|
4099
|
+
bootstrap(app) {
|
4100
|
+
if (!window.strapi.future.isEnabled(FEATURE_ID)) {
|
4101
|
+
return;
|
3099
4102
|
}
|
3100
|
-
const
|
3101
|
-
|
3102
|
-
|
3103
|
-
attribute,
|
3104
|
-
label: metadata.label ?? "",
|
3105
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
3106
|
-
schemas,
|
3107
|
-
components: components?.schemas ?? {}
|
3108
|
-
}),
|
3109
|
-
name,
|
3110
|
-
searchable: metadata.searchable ?? true,
|
3111
|
-
sortable: metadata.sortable ?? true
|
3112
|
-
};
|
3113
|
-
}).filter((field) => field !== null);
|
4103
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4104
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4105
|
+
}
|
3114
4106
|
};
|
3115
4107
|
const index = {
|
3116
4108
|
register(app) {
|
3117
4109
|
const cm = new ContentManagerPlugin();
|
3118
4110
|
app.addReducers({
|
3119
|
-
[contentManagerApi.reducerPath]: contentManagerApi.reducer,
|
3120
4111
|
[PLUGIN_ID]: reducer
|
3121
4112
|
});
|
3122
|
-
app.addMiddlewares([() => contentManagerApi.middleware]);
|
3123
4113
|
app.addMenuLink({
|
3124
4114
|
to: PLUGIN_ID,
|
3125
4115
|
icon: Icons.Feather,
|
@@ -3128,14 +4118,32 @@ const index = {
|
|
3128
4118
|
defaultMessage: "Content Manager"
|
3129
4119
|
},
|
3130
4120
|
permissions: [],
|
3131
|
-
|
4121
|
+
position: 1
|
4122
|
+
});
|
4123
|
+
app.router.addRoute({
|
4124
|
+
path: "content-manager/*",
|
4125
|
+
lazy: async () => {
|
4126
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-BEuNwv-F.js"));
|
4127
|
+
return {
|
4128
|
+
Component: Layout
|
4129
|
+
};
|
4130
|
+
},
|
4131
|
+
children: routes
|
3132
4132
|
});
|
3133
4133
|
app.registerPlugin(cm.config);
|
3134
4134
|
},
|
4135
|
+
bootstrap(app) {
|
4136
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4137
|
+
historyAdmin.bootstrap(app);
|
4138
|
+
}
|
4139
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4140
|
+
previewAdmin.bootstrap(app);
|
4141
|
+
}
|
4142
|
+
},
|
3135
4143
|
async registerTrads({ locales }) {
|
3136
4144
|
const importedTrads = await Promise.all(
|
3137
4145
|
locales.map((locale) => {
|
3138
|
-
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-
|
4146
|
+
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-Ic0kXjxB.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`).then(({ default: data }) => {
|
3139
4147
|
return {
|
3140
4148
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3141
4149
|
locale
|
@@ -3152,6 +4160,8 @@ const index = {
|
|
3152
4160
|
}
|
3153
4161
|
};
|
3154
4162
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
4163
|
+
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4164
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3155
4165
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3156
4166
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3157
4167
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3178,8 +4188,8 @@ exports.getDisplayName = getDisplayName;
|
|
3178
4188
|
exports.getMainField = getMainField;
|
3179
4189
|
exports.getTranslation = getTranslation;
|
3180
4190
|
exports.index = index;
|
3181
|
-
exports.routes = routes;
|
3182
4191
|
exports.setInitialData = setInitialData;
|
4192
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3183
4193
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3184
4194
|
exports.useDoc = useDoc;
|
3185
4195
|
exports.useDocLayout = useDocLayout;
|
@@ -3191,5 +4201,6 @@ exports.useGetAllContentTypeSettingsQuery = useGetAllContentTypeSettingsQuery;
|
|
3191
4201
|
exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
3192
4202
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3193
4203
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
4204
|
+
exports.useGetPreviewUrlQuery = useGetPreviewUrlQuery;
|
3194
4205
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3195
|
-
//# sourceMappingURL=index-
|
4206
|
+
//# sourceMappingURL=index-T-aWjbj2.js.map
|