@strapi/content-manager 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813 → 0.0.0-experimental.e8d8fc824d0f6a695b2a9ebaa4680ed21c3645ca
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-DjWJdz6Y.js → ComponentConfigurationPage-BlzvDpbX.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js.map → ComponentConfigurationPage-BlzvDpbX.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs → ComponentConfigurationPage-DaPOlQaD.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs.map → ComponentConfigurationPage-DaPOlQaD.mjs.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-CRbtQEUV.js} +9 -4
- package/dist/_chunks/ComponentIcon-CRbtQEUV.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-DacbqQ_f.mjs → EditConfigurationPage-BZPXItXo.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs.map → EditConfigurationPage-BZPXItXo.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js → EditConfigurationPage-uy-v43AR.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js.map → EditConfigurationPage-uy-v43AR.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-DvNpQkam.js → EditViewPage-DT6A4ayX.js} +102 -54
- package/dist/_chunks/EditViewPage-DT6A4ayX.js.map +1 -0
- package/dist/_chunks/EditViewPage-oOLeTySr.mjs +254 -0
- package/dist/_chunks/EditViewPage-oOLeTySr.mjs.map +1 -0
- package/dist/_chunks/{Field-6gvGdPBV.mjs → Field-D7dv2aUX.mjs} +1192 -896
- package/dist/_chunks/Field-D7dv2aUX.mjs.map +1 -0
- package/dist/_chunks/{Field-DmVKIAOo.js → Field-kYFVIGiP.js} +1238 -943
- package/dist/_chunks/Field-kYFVIGiP.js.map +1 -0
- package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
- package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
- package/dist/_chunks/{Form-DW6K1IH-.mjs → Form-BxR6sc29.mjs} +67 -46
- package/dist/_chunks/Form-BxR6sc29.mjs.map +1 -0
- package/dist/_chunks/{Form-CPZC9vWa.js → Form-CCijSg3V.js} +68 -49
- package/dist/_chunks/Form-CCijSg3V.js.map +1 -0
- package/dist/_chunks/{History-DeAPlvtv.js → History-BMndx49M.js} +182 -147
- package/dist/_chunks/History-BMndx49M.js.map +1 -0
- package/dist/_chunks/{History-Dmr9fmUA.mjs → History-D8F7aYQU.mjs} +181 -144
- package/dist/_chunks/History-D8F7aYQU.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DPCwW5Vr.js → ListConfigurationPage-DouY1EWM.js} +72 -63
- package/dist/_chunks/ListConfigurationPage-DouY1EWM.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DhwvYcNv.mjs → ListConfigurationPage-DqAdSPwC.mjs} +68 -57
- package/dist/_chunks/ListConfigurationPage-DqAdSPwC.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-5ySZ-VUs.js → ListViewPage-BPVmh9pq.js} +179 -164
- package/dist/_chunks/ListViewPage-BPVmh9pq.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BtAwuYLE.mjs → ListViewPage-C73F0jPh.mjs} +175 -159
- package/dist/_chunks/ListViewPage-C73F0jPh.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DSPxnxxp.mjs → NoContentTypePage-B5w7iJOF.mjs} +3 -3
- package/dist/_chunks/NoContentTypePage-B5w7iJOF.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DOC_yWOf.js → NoContentTypePage-BwcL--4H.js} +3 -3
- package/dist/_chunks/NoContentTypePage-BwcL--4H.js.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js → NoPermissionsPage-BMFKVcwJ.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js.map → NoPermissionsPage-BMFKVcwJ.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs → NoPermissionsPage-UnEgMGK4.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs.map → NoPermissionsPage-UnEgMGK4.mjs.map} +1 -1
- package/dist/_chunks/Preview-B7PR3Ok_.js +312 -0
- package/dist/_chunks/Preview-B7PR3Ok_.js.map +1 -0
- package/dist/_chunks/Preview-DECOhK0D.mjs +294 -0
- package/dist/_chunks/Preview-DECOhK0D.mjs.map +1 -0
- package/dist/_chunks/{Relations-J8cscLlR.mjs → Relations-DinMQJ4B.mjs} +138 -94
- package/dist/_chunks/Relations-DinMQJ4B.mjs.map +1 -0
- package/dist/_chunks/{Relations-CgWtgnPe.js → Relations-lndx3aQk.js} +142 -100
- package/dist/_chunks/Relations-lndx3aQk.js.map +1 -0
- package/dist/_chunks/{en-C-V1_90f.js → en-BK8Xyl5I.js} +38 -18
- package/dist/_chunks/{en-C-V1_90f.js.map → en-BK8Xyl5I.js.map} +1 -1
- package/dist/_chunks/{en-MBPul9Su.mjs → en-Dtk_ot79.mjs} +38 -18
- package/dist/_chunks/{en-MBPul9Su.mjs.map → en-Dtk_ot79.mjs.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
- package/dist/_chunks/{index-CwRRo1V9.mjs → index-C2SagWVW.mjs} +2070 -988
- package/dist/_chunks/index-C2SagWVW.mjs.map +1 -0
- package/dist/_chunks/{index-C6AH2hEl.js → index-Cnw4gqee.js} +2047 -966
- package/dist/_chunks/index-Cnw4gqee.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-jIDzX0Fp.mjs → layout-DY_D9MGA.mjs} +46 -28
- package/dist/_chunks/layout-DY_D9MGA.mjs.map +1 -0
- package/dist/_chunks/{layout-B_SXLhqf.js → layout-ivwIVPnV.js} +47 -32
- package/dist/_chunks/layout-ivwIVPnV.js.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-iBMa_OFG.js → relations-B7C7O_Pv.js} +6 -7
- package/dist/_chunks/relations-B7C7O_Pv.js.map +1 -0
- package/dist/_chunks/{relations-CuvIgCqI.mjs → relations-Boc5Y9kX.mjs} +6 -7
- package/dist/_chunks/relations-Boc5Y9kX.mjs.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-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
- package/dist/_chunks/useDragAndDrop-BMtgCYzL.js.map +1 -0
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
- package/dist/_chunks/useDragAndDrop-DJ6jqvZN.mjs.map +1 -0
- 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 +6 -5
- 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 +12 -5
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +5 -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/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 +886 -480
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +892 -485
- 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 +23 -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 +22 -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/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 +16 -35
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +22 -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/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 +22 -21
- 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/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +0 -1
- package/dist/_chunks/useDragAndDrop-J0TUUbR6.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,22 +2,20 @@
|
|
2
2
|
const Icons = require("@strapi/icons");
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
4
4
|
const strapiAdmin = require("@strapi/admin/strapi-admin");
|
5
|
-
const qs = require("qs");
|
6
|
-
const reactIntl = require("react-intl");
|
7
|
-
const reactRouterDom = require("react-router-dom");
|
8
5
|
const React = require("react");
|
9
6
|
const designSystem = require("@strapi/design-system");
|
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");
|
17
16
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
18
17
|
function _interopNamespace(e) {
|
19
|
-
if (e && e.__esModule)
|
20
|
-
return e;
|
18
|
+
if (e && e.__esModule) return e;
|
21
19
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
22
20
|
if (e) {
|
23
21
|
for (const k in e) {
|
@@ -34,16 +32,23 @@ function _interopNamespace(e) {
|
|
34
32
|
return Object.freeze(n);
|
35
33
|
}
|
36
34
|
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
37
|
-
const
|
35
|
+
const mapValues__default = /* @__PURE__ */ _interopDefault(mapValues);
|
38
36
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
39
37
|
const pipe__default = /* @__PURE__ */ _interopDefault(pipe);
|
40
|
-
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
38
|
+
const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
|
41
39
|
const v = glob[path];
|
42
40
|
if (v) {
|
43
41
|
return typeof v === "function" ? v() : Promise.resolve(v);
|
44
42
|
}
|
45
43
|
return new Promise((_, reject) => {
|
46
|
-
(typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
|
44
|
+
(typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
|
45
|
+
reject.bind(
|
46
|
+
null,
|
47
|
+
new Error(
|
48
|
+
"Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
|
49
|
+
)
|
50
|
+
)
|
51
|
+
);
|
47
52
|
});
|
48
53
|
};
|
49
54
|
const PLUGIN_ID = "content-manager";
|
@@ -73,42 +78,6 @@ const useInjectionZone = (area) => {
|
|
73
78
|
const [page, position] = area.split(".");
|
74
79
|
return contentManagerPlugin.getInjectedComponents(page, position);
|
75
80
|
};
|
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
81
|
const ID = "id";
|
113
82
|
const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
|
114
83
|
const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
|
@@ -160,6 +129,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
160
129
|
if (!slug) {
|
161
130
|
throw new Error("Cannot find the slug param in the URL");
|
162
131
|
}
|
132
|
+
const [{ rawQuery }] = strapiAdmin.useQueryParams();
|
163
133
|
const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
|
164
134
|
const contentTypePermissions = React__namespace.useMemo(() => {
|
165
135
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -170,7 +140,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
170
140
|
return { ...acc, [action]: [permission] };
|
171
141
|
}, {});
|
172
142
|
}, [slug, userPermissions]);
|
173
|
-
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
143
|
+
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
144
|
+
contentTypePermissions,
|
145
|
+
permissions ?? void 0,
|
146
|
+
// TODO: useRBAC context should be typed and built differently
|
147
|
+
// We are passing raw query as context to the hook so that it can
|
148
|
+
// rely on the locale provided from DocumentRBAC for its permission calculations.
|
149
|
+
rawQuery
|
150
|
+
);
|
174
151
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
175
152
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
176
153
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -179,9 +156,8 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
179
156
|
const name = removeNumericalStrings(fieldName.split("."));
|
180
157
|
const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
|
181
158
|
if (fieldType === "component") {
|
182
|
-
|
183
|
-
|
184
|
-
return field.includes(fieldName);
|
159
|
+
return componentFieldNames.some((field) => {
|
160
|
+
return field.includes(name.join("."));
|
185
161
|
});
|
186
162
|
}
|
187
163
|
if (name.length > 1) {
|
@@ -211,89 +187,20 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
|
|
211
187
|
(field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
|
212
188
|
);
|
213
189
|
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: [
|
190
|
+
const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
191
|
+
addTagTypes: [
|
286
192
|
"ComponentConfiguration",
|
287
193
|
"ContentTypesConfiguration",
|
288
194
|
"ContentTypeSettings",
|
289
195
|
"Document",
|
290
196
|
"InitialData",
|
291
197
|
"HistoryVersion",
|
292
|
-
"Relations"
|
293
|
-
|
294
|
-
|
198
|
+
"Relations",
|
199
|
+
"UidAvailability"
|
200
|
+
]
|
295
201
|
});
|
296
202
|
const documentApi = contentManagerApi.injectEndpoints({
|
203
|
+
overrideExisting: true,
|
297
204
|
endpoints: (builder) => ({
|
298
205
|
autoCloneDocument: builder.mutation({
|
299
206
|
query: ({ model, sourceId, query }) => ({
|
@@ -303,7 +210,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
303
210
|
params: query
|
304
211
|
}
|
305
212
|
}),
|
306
|
-
invalidatesTags: (_result,
|
213
|
+
invalidatesTags: (_result, error, { model }) => {
|
214
|
+
if (error) {
|
215
|
+
return [];
|
216
|
+
}
|
217
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
218
|
+
}
|
307
219
|
}),
|
308
220
|
cloneDocument: builder.mutation({
|
309
221
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -314,7 +226,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
314
226
|
params
|
315
227
|
}
|
316
228
|
}),
|
317
|
-
invalidatesTags: (_result, _error, { model }) => [
|
229
|
+
invalidatesTags: (_result, _error, { model }) => [
|
230
|
+
{ type: "Document", id: `${model}_LIST` },
|
231
|
+
{ type: "UidAvailability", id: model }
|
232
|
+
]
|
318
233
|
}),
|
319
234
|
/**
|
320
235
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -331,7 +246,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
331
246
|
}),
|
332
247
|
invalidatesTags: (result, _error, { model }) => [
|
333
248
|
{ type: "Document", id: `${model}_LIST` },
|
334
|
-
"Relations"
|
249
|
+
"Relations",
|
250
|
+
{ type: "UidAvailability", id: model }
|
335
251
|
]
|
336
252
|
}),
|
337
253
|
deleteDocument: builder.mutation({
|
@@ -347,12 +263,15 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
347
263
|
]
|
348
264
|
}),
|
349
265
|
deleteManyDocuments: builder.mutation({
|
350
|
-
query: ({ model, ...body }) => ({
|
266
|
+
query: ({ model, params, ...body }) => ({
|
351
267
|
url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
|
352
268
|
method: "POST",
|
353
|
-
data: body
|
269
|
+
data: body,
|
270
|
+
config: {
|
271
|
+
params
|
272
|
+
}
|
354
273
|
}),
|
355
|
-
invalidatesTags: (_res, _error, { model
|
274
|
+
invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
|
356
275
|
}),
|
357
276
|
discardDocument: builder.mutation({
|
358
277
|
query: ({ collectionType, model, documentId, params }) => ({
|
@@ -369,7 +288,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
369
288
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
370
289
|
},
|
371
290
|
{ type: "Document", id: `${model}_LIST` },
|
372
|
-
"Relations"
|
291
|
+
"Relations",
|
292
|
+
{ type: "UidAvailability", id: model }
|
373
293
|
];
|
374
294
|
}
|
375
295
|
}),
|
@@ -382,11 +302,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
382
302
|
url: `/content-manager/collection-types/${model}`,
|
383
303
|
method: "GET",
|
384
304
|
config: {
|
385
|
-
params
|
305
|
+
params: qs.stringify(params, { encode: true })
|
386
306
|
}
|
387
307
|
}),
|
388
308
|
providesTags: (result, _error, arg) => {
|
389
309
|
return [
|
310
|
+
{ type: "Document", id: `ALL_LIST` },
|
390
311
|
{ type: "Document", id: `${arg.model}_LIST` },
|
391
312
|
...result?.results.map(({ documentId }) => ({
|
392
313
|
type: "Document",
|
@@ -425,6 +346,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
425
346
|
{
|
426
347
|
type: "Document",
|
427
348
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
349
|
+
},
|
350
|
+
// Make it easy to invalidate all individual documents queries for a model
|
351
|
+
{
|
352
|
+
type: "Document",
|
353
|
+
id: `${model}_ALL_ITEMS`
|
428
354
|
}
|
429
355
|
];
|
430
356
|
}
|
@@ -463,10 +389,13 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
463
389
|
}
|
464
390
|
}),
|
465
391
|
publishManyDocuments: builder.mutation({
|
466
|
-
query: ({ model, ...body }) => ({
|
392
|
+
query: ({ model, params, ...body }) => ({
|
467
393
|
url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
|
468
394
|
method: "POST",
|
469
|
-
data: body
|
395
|
+
data: body,
|
396
|
+
config: {
|
397
|
+
params
|
398
|
+
}
|
470
399
|
}),
|
471
400
|
invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
|
472
401
|
}),
|
@@ -485,8 +414,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
485
414
|
type: "Document",
|
486
415
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
487
416
|
},
|
488
|
-
"Relations"
|
417
|
+
"Relations",
|
418
|
+
{ type: "UidAvailability", id: model }
|
489
419
|
];
|
420
|
+
},
|
421
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
422
|
+
const patchResult = dispatch(
|
423
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
424
|
+
Object.assign(draft.data, data);
|
425
|
+
})
|
426
|
+
);
|
427
|
+
try {
|
428
|
+
await queryFulfilled;
|
429
|
+
} catch {
|
430
|
+
patchResult.undo();
|
431
|
+
}
|
490
432
|
}
|
491
433
|
}),
|
492
434
|
unpublishDocument: builder.mutation({
|
@@ -508,10 +450,13 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
508
450
|
}
|
509
451
|
}),
|
510
452
|
unpublishManyDocuments: builder.mutation({
|
511
|
-
query: ({ model, ...body }) => ({
|
453
|
+
query: ({ model, params, ...body }) => ({
|
512
454
|
url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
|
513
455
|
method: "POST",
|
514
|
-
data: body
|
456
|
+
data: body,
|
457
|
+
config: {
|
458
|
+
params
|
459
|
+
}
|
515
460
|
}),
|
516
461
|
invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
|
517
462
|
})
|
@@ -535,20 +480,53 @@ const {
|
|
535
480
|
useUnpublishDocumentMutation,
|
536
481
|
useUnpublishManyDocumentsMutation
|
537
482
|
} = documentApi;
|
538
|
-
const
|
483
|
+
const buildValidParams = (query) => {
|
484
|
+
if (!query) return query;
|
485
|
+
const { plugins: _, ...validQueryParams } = {
|
486
|
+
...query,
|
487
|
+
...Object.values(query?.plugins ?? {}).reduce(
|
488
|
+
(acc, current) => Object.assign(acc, current),
|
489
|
+
{}
|
490
|
+
)
|
491
|
+
};
|
492
|
+
return validQueryParams;
|
493
|
+
};
|
494
|
+
const isBaseQueryError = (error) => {
|
495
|
+
return error.name !== void 0;
|
496
|
+
};
|
497
|
+
const arrayValidator = (attribute, options) => ({
|
498
|
+
message: strapiAdmin.translatedErrors.required,
|
499
|
+
test(value) {
|
500
|
+
if (options.status === "draft") {
|
501
|
+
return true;
|
502
|
+
}
|
503
|
+
if (!attribute.required) {
|
504
|
+
return true;
|
505
|
+
}
|
506
|
+
if (!value) {
|
507
|
+
return false;
|
508
|
+
}
|
509
|
+
if (Array.isArray(value) && value.length === 0) {
|
510
|
+
return false;
|
511
|
+
}
|
512
|
+
return true;
|
513
|
+
}
|
514
|
+
});
|
515
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
539
516
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
540
517
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
541
518
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
542
519
|
return acc;
|
543
520
|
}
|
544
521
|
const validations = [
|
522
|
+
addNullableValidation,
|
545
523
|
addRequiredValidation,
|
546
524
|
addMinLengthValidation,
|
547
525
|
addMaxLengthValidation,
|
548
526
|
addMinValidation,
|
549
527
|
addMaxValidation,
|
550
528
|
addRegexValidation
|
551
|
-
].map((fn) => fn(attribute));
|
529
|
+
].map((fn) => fn(attribute, options));
|
552
530
|
const transformSchema = pipe__default.default(...validations);
|
553
531
|
switch (attribute.type) {
|
554
532
|
case "component": {
|
@@ -558,12 +536,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
558
536
|
...acc,
|
559
537
|
[name]: transformSchema(
|
560
538
|
yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
|
561
|
-
)
|
539
|
+
).test(arrayValidator(attribute, options))
|
562
540
|
};
|
563
541
|
} else {
|
564
542
|
return {
|
565
543
|
...acc,
|
566
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
544
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
567
545
|
};
|
568
546
|
}
|
569
547
|
}
|
@@ -574,24 +552,42 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
574
552
|
yup__namespace.array().of(
|
575
553
|
yup__namespace.lazy(
|
576
554
|
(data) => {
|
577
|
-
const
|
578
|
-
|
555
|
+
const attributes3 = components?.[data?.__component]?.attributes;
|
556
|
+
const validation = yup__namespace.object().shape({
|
579
557
|
__component: yup__namespace.string().required().oneOf(Object.keys(components))
|
580
|
-
}).nullable(false)
|
558
|
+
}).nullable(false);
|
559
|
+
if (!attributes3) {
|
560
|
+
return validation;
|
561
|
+
}
|
562
|
+
return validation.concat(createModelSchema(attributes3));
|
581
563
|
}
|
582
564
|
)
|
583
565
|
)
|
584
|
-
)
|
566
|
+
).test(arrayValidator(attribute, options))
|
585
567
|
};
|
586
568
|
case "relation":
|
587
569
|
return {
|
588
570
|
...acc,
|
589
571
|
[name]: transformSchema(
|
590
|
-
yup__namespace.
|
591
|
-
|
592
|
-
|
593
|
-
})
|
594
|
-
|
572
|
+
yup__namespace.lazy((value) => {
|
573
|
+
if (!value) {
|
574
|
+
return yup__namespace.mixed().nullable(true);
|
575
|
+
} else if (Array.isArray(value)) {
|
576
|
+
return yup__namespace.array().of(
|
577
|
+
yup__namespace.object().shape({
|
578
|
+
id: yup__namespace.number().required()
|
579
|
+
})
|
580
|
+
);
|
581
|
+
} else if (typeof value === "object") {
|
582
|
+
return yup__namespace.object();
|
583
|
+
} else {
|
584
|
+
return yup__namespace.mixed().test(
|
585
|
+
"type-error",
|
586
|
+
"Relation values must be either null, an array of objects with {id} or an object.",
|
587
|
+
() => false
|
588
|
+
);
|
589
|
+
}
|
590
|
+
})
|
595
591
|
)
|
596
592
|
};
|
597
593
|
default:
|
@@ -631,6 +627,14 @@ const createAttributeSchema = (attribute) => {
|
|
631
627
|
if (!value || typeof value === "string" && value.length === 0) {
|
632
628
|
return true;
|
633
629
|
}
|
630
|
+
if (typeof value === "object") {
|
631
|
+
try {
|
632
|
+
JSON.stringify(value);
|
633
|
+
return true;
|
634
|
+
} catch (err) {
|
635
|
+
return false;
|
636
|
+
}
|
637
|
+
}
|
634
638
|
try {
|
635
639
|
JSON.parse(value);
|
636
640
|
return true;
|
@@ -649,16 +653,30 @@ const createAttributeSchema = (attribute) => {
|
|
649
653
|
return yup__namespace.mixed();
|
650
654
|
}
|
651
655
|
};
|
652
|
-
const
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
656
|
+
const nullableSchema = (schema) => {
|
657
|
+
return schema?.nullable ? schema.nullable() : (
|
658
|
+
// In some cases '.nullable' will not be available on the schema.
|
659
|
+
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
660
|
+
// In these cases we should just return the schema as it is.
|
661
|
+
schema
|
662
|
+
);
|
663
|
+
};
|
664
|
+
const addNullableValidation = () => (schema) => {
|
665
|
+
return nullableSchema(schema);
|
666
|
+
};
|
667
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
668
|
+
if (options.status === "draft" || !attribute.required) {
|
669
|
+
return schema;
|
658
670
|
}
|
659
|
-
|
671
|
+
if (attribute.required && "required" in schema) {
|
672
|
+
return schema.required(strapiAdmin.translatedErrors.required);
|
673
|
+
}
|
674
|
+
return schema;
|
660
675
|
};
|
661
|
-
const addMinLengthValidation = (attribute) => (schema) => {
|
676
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
677
|
+
if (options.status === "draft") {
|
678
|
+
return schema;
|
679
|
+
}
|
662
680
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
663
681
|
return schema.min(attribute.minLength, {
|
664
682
|
...strapiAdmin.translatedErrors.minLength,
|
@@ -680,10 +698,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
680
698
|
}
|
681
699
|
return schema;
|
682
700
|
};
|
683
|
-
const addMinValidation = (attribute) => (schema) => {
|
684
|
-
if ("
|
701
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
702
|
+
if (options.status === "draft") {
|
703
|
+
return schema;
|
704
|
+
}
|
705
|
+
if ("min" in attribute && "min" in schema) {
|
685
706
|
const min = toInteger(attribute.min);
|
686
|
-
if (
|
707
|
+
if (min) {
|
687
708
|
return schema.min(min, {
|
688
709
|
...strapiAdmin.translatedErrors.min,
|
689
710
|
values: {
|
@@ -728,24 +749,6 @@ const addRegexValidation = (attribute) => (schema) => {
|
|
728
749
|
}
|
729
750
|
return schema;
|
730
751
|
};
|
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
752
|
const initApi = contentManagerApi.injectEndpoints({
|
750
753
|
endpoints: (builder) => ({
|
751
754
|
getInitialData: builder.query({
|
@@ -759,27 +762,20 @@ const { useGetInitialDataQuery } = initApi;
|
|
759
762
|
const useContentTypeSchema = (model) => {
|
760
763
|
const { toggleNotification } = strapiAdmin.useNotification();
|
761
764
|
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
|
-
});
|
765
|
+
const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
|
766
|
+
const { components, contentType, contentTypes } = React__namespace.useMemo(() => {
|
767
|
+
const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
|
768
|
+
const componentsByKey = data?.components.reduce((acc, component) => {
|
769
|
+
acc[component.uid] = component;
|
770
|
+
return acc;
|
771
|
+
}, {});
|
772
|
+
const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
|
773
|
+
return {
|
774
|
+
components: Object.keys(components2).length === 0 ? void 0 : components2,
|
775
|
+
contentType: contentType2,
|
776
|
+
contentTypes: data?.contentTypes ?? []
|
777
|
+
};
|
778
|
+
}, [model, data]);
|
783
779
|
React__namespace.useEffect(() => {
|
784
780
|
if (error) {
|
785
781
|
toggleNotification({
|
@@ -826,16 +822,328 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
826
822
|
}, {});
|
827
823
|
return componentsByKey;
|
828
824
|
};
|
829
|
-
const
|
825
|
+
const HOOKS = {
|
826
|
+
/**
|
827
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
828
|
+
* @constant
|
829
|
+
* @type {string}
|
830
|
+
*/
|
831
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
832
|
+
/**
|
833
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
834
|
+
* @constant
|
835
|
+
* @type {string}
|
836
|
+
*/
|
837
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
838
|
+
/**
|
839
|
+
* Hook that allows to mutate the CM's edit view layout
|
840
|
+
* @constant
|
841
|
+
* @type {string}
|
842
|
+
*/
|
843
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
844
|
+
/**
|
845
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
846
|
+
* @constant
|
847
|
+
* @type {string}
|
848
|
+
*/
|
849
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
850
|
+
};
|
851
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
852
|
+
endpoints: (builder) => ({
|
853
|
+
getContentTypeConfiguration: builder.query({
|
854
|
+
query: (uid) => ({
|
855
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
856
|
+
method: "GET"
|
857
|
+
}),
|
858
|
+
transformResponse: (response) => response.data,
|
859
|
+
providesTags: (_result, _error, uid) => [
|
860
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
861
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
862
|
+
]
|
863
|
+
}),
|
864
|
+
getAllContentTypeSettings: builder.query({
|
865
|
+
query: () => "/content-manager/content-types-settings",
|
866
|
+
transformResponse: (response) => response.data,
|
867
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
868
|
+
}),
|
869
|
+
updateContentTypeConfiguration: builder.mutation({
|
870
|
+
query: ({ uid, ...body }) => ({
|
871
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
872
|
+
method: "PUT",
|
873
|
+
data: body
|
874
|
+
}),
|
875
|
+
transformResponse: (response) => response.data,
|
876
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
877
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
878
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
879
|
+
// Is this necessary?
|
880
|
+
{ type: "InitialData" }
|
881
|
+
]
|
882
|
+
})
|
883
|
+
})
|
884
|
+
});
|
885
|
+
const {
|
886
|
+
useGetContentTypeConfigurationQuery,
|
887
|
+
useGetAllContentTypeSettingsQuery,
|
888
|
+
useUpdateContentTypeConfigurationMutation
|
889
|
+
} = contentTypesApi;
|
890
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
891
|
+
const { type } = attribute;
|
892
|
+
if (type === "relation") {
|
893
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
894
|
+
}
|
895
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
896
|
+
};
|
897
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
898
|
+
if (!mainFieldName) {
|
899
|
+
return void 0;
|
900
|
+
}
|
901
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
902
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
903
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
904
|
+
);
|
905
|
+
return {
|
906
|
+
name: mainFieldName,
|
907
|
+
type: mainFieldType ?? "string"
|
908
|
+
};
|
909
|
+
};
|
910
|
+
const DEFAULT_SETTINGS = {
|
911
|
+
bulkable: false,
|
912
|
+
filterable: false,
|
913
|
+
searchable: false,
|
914
|
+
pagination: false,
|
915
|
+
defaultSortBy: "",
|
916
|
+
defaultSortOrder: "asc",
|
917
|
+
mainField: "id",
|
918
|
+
pageSize: 10
|
919
|
+
};
|
920
|
+
const useDocumentLayout = (model) => {
|
921
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
922
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
923
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
830
924
|
const { toggleNotification } = strapiAdmin.useNotification();
|
831
925
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
926
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
832
927
|
const {
|
833
|
-
|
834
|
-
isLoading:
|
835
|
-
|
928
|
+
data,
|
929
|
+
isLoading: isLoadingConfigs,
|
930
|
+
error,
|
931
|
+
isFetching: isFetchingConfigs
|
932
|
+
} = useGetContentTypeConfigurationQuery(model);
|
933
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
934
|
+
React__namespace.useEffect(() => {
|
935
|
+
if (error) {
|
936
|
+
toggleNotification({
|
937
|
+
type: "danger",
|
938
|
+
message: formatAPIError(error)
|
939
|
+
});
|
940
|
+
}
|
941
|
+
}, [error, formatAPIError, toggleNotification]);
|
942
|
+
const editLayout = React__namespace.useMemo(
|
943
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
944
|
+
layout: [],
|
945
|
+
components: {},
|
946
|
+
metadatas: {},
|
947
|
+
options: {},
|
948
|
+
settings: DEFAULT_SETTINGS
|
949
|
+
},
|
950
|
+
[data, isLoading, schemas, schema, components]
|
951
|
+
);
|
952
|
+
const listLayout = React__namespace.useMemo(() => {
|
953
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
954
|
+
layout: [],
|
955
|
+
metadatas: {},
|
956
|
+
options: {},
|
957
|
+
settings: DEFAULT_SETTINGS
|
958
|
+
};
|
959
|
+
}, [data, isLoading, schemas, schema, components]);
|
960
|
+
const { layout: edit } = React__namespace.useMemo(
|
961
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
962
|
+
layout: editLayout,
|
963
|
+
query
|
964
|
+
}),
|
965
|
+
[editLayout, query, runHookWaterfall]
|
966
|
+
);
|
967
|
+
return {
|
968
|
+
error,
|
969
|
+
isLoading,
|
970
|
+
edit,
|
971
|
+
list: listLayout
|
972
|
+
};
|
973
|
+
};
|
974
|
+
const useDocLayout = () => {
|
975
|
+
const { model } = useDoc();
|
976
|
+
return useDocumentLayout(model);
|
977
|
+
};
|
978
|
+
const formatEditLayout = (data, {
|
979
|
+
schemas,
|
980
|
+
schema,
|
981
|
+
components
|
982
|
+
}) => {
|
983
|
+
let currentPanelIndex = 0;
|
984
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
985
|
+
data.contentType.layouts.edit,
|
986
|
+
schema?.attributes,
|
987
|
+
data.contentType.metadatas,
|
988
|
+
{ configurations: data.components, schemas: components },
|
989
|
+
schemas
|
990
|
+
).reduce((panels, row) => {
|
991
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
992
|
+
panels.push([row]);
|
993
|
+
currentPanelIndex += 2;
|
994
|
+
} else {
|
995
|
+
if (!panels[currentPanelIndex]) {
|
996
|
+
panels.push([row]);
|
997
|
+
} else {
|
998
|
+
panels[currentPanelIndex].push(row);
|
999
|
+
}
|
1000
|
+
}
|
1001
|
+
return panels;
|
1002
|
+
}, []);
|
1003
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
1004
|
+
(acc, [uid, configuration]) => {
|
1005
|
+
acc[uid] = {
|
1006
|
+
layout: convertEditLayoutToFieldLayouts(
|
1007
|
+
configuration.layouts.edit,
|
1008
|
+
components[uid].attributes,
|
1009
|
+
configuration.metadatas,
|
1010
|
+
{ configurations: data.components, schemas: components }
|
1011
|
+
),
|
1012
|
+
settings: {
|
1013
|
+
...configuration.settings,
|
1014
|
+
icon: components[uid].info.icon,
|
1015
|
+
displayName: components[uid].info.displayName
|
1016
|
+
}
|
1017
|
+
};
|
1018
|
+
return acc;
|
1019
|
+
},
|
1020
|
+
{}
|
1021
|
+
);
|
1022
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1023
|
+
(acc, [attribute, metadata]) => {
|
1024
|
+
return {
|
1025
|
+
...acc,
|
1026
|
+
[attribute]: metadata.edit
|
1027
|
+
};
|
1028
|
+
},
|
1029
|
+
{}
|
1030
|
+
);
|
1031
|
+
return {
|
1032
|
+
layout: panelledEditAttributes,
|
1033
|
+
components: componentEditAttributes,
|
1034
|
+
metadatas: editMetadatas,
|
1035
|
+
settings: {
|
1036
|
+
...data.contentType.settings,
|
1037
|
+
displayName: schema?.info.displayName
|
1038
|
+
},
|
1039
|
+
options: {
|
1040
|
+
...schema?.options,
|
1041
|
+
...schema?.pluginOptions,
|
1042
|
+
...data.contentType.options
|
1043
|
+
}
|
1044
|
+
};
|
1045
|
+
};
|
1046
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1047
|
+
return rows.map(
|
1048
|
+
(row) => row.map((field) => {
|
1049
|
+
const attribute = attributes[field.name];
|
1050
|
+
if (!attribute) {
|
1051
|
+
return null;
|
1052
|
+
}
|
1053
|
+
const { edit: metadata } = metadatas[field.name];
|
1054
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1055
|
+
return {
|
1056
|
+
attribute,
|
1057
|
+
disabled: !metadata.editable,
|
1058
|
+
hint: metadata.description,
|
1059
|
+
label: metadata.label ?? "",
|
1060
|
+
name: field.name,
|
1061
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1062
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1063
|
+
schemas,
|
1064
|
+
components: components?.schemas ?? {}
|
1065
|
+
}),
|
1066
|
+
placeholder: metadata.placeholder ?? "",
|
1067
|
+
required: attribute.required ?? false,
|
1068
|
+
size: field.size,
|
1069
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1070
|
+
visible: metadata.visible ?? true,
|
1071
|
+
type: attribute.type
|
1072
|
+
};
|
1073
|
+
}).filter((field) => field !== null)
|
1074
|
+
);
|
1075
|
+
};
|
1076
|
+
const formatListLayout = (data, {
|
1077
|
+
schemas,
|
1078
|
+
schema,
|
1079
|
+
components
|
1080
|
+
}) => {
|
1081
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1082
|
+
(acc, [attribute, metadata]) => {
|
1083
|
+
return {
|
1084
|
+
...acc,
|
1085
|
+
[attribute]: metadata.list
|
1086
|
+
};
|
1087
|
+
},
|
1088
|
+
{}
|
1089
|
+
);
|
1090
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1091
|
+
data.contentType.layouts.list,
|
1092
|
+
schema?.attributes,
|
1093
|
+
listMetadatas,
|
1094
|
+
{ configurations: data.components, schemas: components },
|
1095
|
+
schemas
|
1096
|
+
);
|
1097
|
+
return {
|
1098
|
+
layout: listAttributes,
|
1099
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1100
|
+
metadatas: listMetadatas,
|
1101
|
+
options: {
|
1102
|
+
...schema?.options,
|
1103
|
+
...schema?.pluginOptions,
|
1104
|
+
...data.contentType.options
|
1105
|
+
}
|
1106
|
+
};
|
1107
|
+
};
|
1108
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1109
|
+
return columns.map((name) => {
|
1110
|
+
const attribute = attributes[name];
|
1111
|
+
if (!attribute) {
|
1112
|
+
return null;
|
1113
|
+
}
|
1114
|
+
const metadata = metadatas[name];
|
1115
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1116
|
+
return {
|
1117
|
+
attribute,
|
1118
|
+
label: metadata.label ?? "",
|
1119
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1120
|
+
schemas,
|
1121
|
+
components: components?.schemas ?? {}
|
1122
|
+
}),
|
1123
|
+
name,
|
1124
|
+
searchable: metadata.searchable ?? true,
|
1125
|
+
sortable: metadata.sortable ?? true
|
1126
|
+
};
|
1127
|
+
}).filter((field) => field !== null);
|
1128
|
+
};
|
1129
|
+
const useDocument = (args, opts) => {
|
1130
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1131
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1132
|
+
const {
|
1133
|
+
currentData: data,
|
1134
|
+
isLoading: isLoadingDocument,
|
1135
|
+
isFetching: isFetchingDocument,
|
836
1136
|
error
|
837
|
-
} = useGetDocumentQuery(args,
|
838
|
-
|
1137
|
+
} = useGetDocumentQuery(args, {
|
1138
|
+
...opts,
|
1139
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1140
|
+
});
|
1141
|
+
const {
|
1142
|
+
components,
|
1143
|
+
schema,
|
1144
|
+
schemas,
|
1145
|
+
isLoading: isLoadingSchema
|
1146
|
+
} = useContentTypeSchema(args.model);
|
839
1147
|
React__namespace.useEffect(() => {
|
840
1148
|
if (error) {
|
841
1149
|
toggleNotification({
|
@@ -862,7 +1170,7 @@ const useDocument = (args, opts) => {
|
|
862
1170
|
return null;
|
863
1171
|
} catch (error2) {
|
864
1172
|
if (error2 instanceof yup.ValidationError) {
|
865
|
-
return
|
1173
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
866
1174
|
}
|
867
1175
|
throw error2;
|
868
1176
|
}
|
@@ -870,12 +1178,15 @@ const useDocument = (args, opts) => {
|
|
870
1178
|
[validationSchema]
|
871
1179
|
);
|
872
1180
|
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1181
|
+
const hasError = !!error;
|
873
1182
|
return {
|
874
1183
|
components,
|
875
1184
|
document: data?.data,
|
876
1185
|
meta: data?.meta,
|
877
1186
|
isLoading,
|
1187
|
+
hasError,
|
878
1188
|
schema,
|
1189
|
+
schemas,
|
879
1190
|
validate
|
880
1191
|
};
|
881
1192
|
};
|
@@ -889,22 +1200,60 @@ const useDoc = () => {
|
|
889
1200
|
if (!slug) {
|
890
1201
|
throw new Error("Could not find model in url params");
|
891
1202
|
}
|
1203
|
+
const document = useDocument(
|
1204
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1205
|
+
{
|
1206
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1207
|
+
}
|
1208
|
+
);
|
1209
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
892
1210
|
return {
|
893
1211
|
collectionType,
|
894
1212
|
model: slug,
|
895
|
-
id:
|
896
|
-
...
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
1213
|
+
id: returnId,
|
1214
|
+
...document
|
1215
|
+
};
|
1216
|
+
};
|
1217
|
+
const useContentManagerContext = () => {
|
1218
|
+
const {
|
1219
|
+
collectionType,
|
1220
|
+
model,
|
1221
|
+
id,
|
1222
|
+
components,
|
1223
|
+
isLoading: isLoadingDoc,
|
1224
|
+
schema,
|
1225
|
+
schemas
|
1226
|
+
} = useDoc();
|
1227
|
+
const layout = useDocumentLayout(model);
|
1228
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1229
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1230
|
+
const slug = model;
|
1231
|
+
const isCreatingEntry = id === "create";
|
1232
|
+
useContentTypeSchema();
|
1233
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1234
|
+
const error = layout.error;
|
1235
|
+
return {
|
1236
|
+
error,
|
1237
|
+
isLoading,
|
1238
|
+
// Base metadata
|
1239
|
+
model,
|
1240
|
+
collectionType,
|
1241
|
+
id,
|
1242
|
+
slug,
|
1243
|
+
isCreatingEntry,
|
1244
|
+
isSingleType,
|
1245
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1246
|
+
// All schema infos
|
1247
|
+
components,
|
1248
|
+
contentType: schema,
|
1249
|
+
contentTypes: schemas,
|
1250
|
+
// Form state
|
1251
|
+
form,
|
1252
|
+
// layout infos
|
1253
|
+
layout
|
902
1254
|
};
|
903
1255
|
};
|
904
1256
|
const prefixPluginTranslations = (trad, pluginId) => {
|
905
|
-
if (!pluginId) {
|
906
|
-
throw new TypeError("pluginId can't be empty");
|
907
|
-
}
|
908
1257
|
return Object.keys(trad).reduce((acc, current) => {
|
909
1258
|
acc[`${pluginId}.${current}`] = trad[current];
|
910
1259
|
return acc;
|
@@ -920,6 +1269,8 @@ const useDocumentActions = () => {
|
|
920
1269
|
const { formatMessage } = reactIntl.useIntl();
|
921
1270
|
const { trackUsage } = strapiAdmin.useTracking();
|
922
1271
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1272
|
+
const navigate = reactRouterDom.useNavigate();
|
1273
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
923
1274
|
const [deleteDocument] = useDeleteDocumentMutation();
|
924
1275
|
const _delete = React__namespace.useCallback(
|
925
1276
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -958,14 +1309,15 @@ const useDocumentActions = () => {
|
|
958
1309
|
},
|
959
1310
|
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
960
1311
|
);
|
961
|
-
const [
|
962
|
-
const
|
963
|
-
async ({
|
1312
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1313
|
+
const deleteMany = React__namespace.useCallback(
|
1314
|
+
async ({ model, documentIds, params }) => {
|
964
1315
|
try {
|
965
|
-
|
966
|
-
|
1316
|
+
trackUsage("willBulkDeleteEntries");
|
1317
|
+
const res = await deleteManyDocuments({
|
967
1318
|
model,
|
968
|
-
|
1319
|
+
documentIds,
|
1320
|
+
params
|
969
1321
|
});
|
970
1322
|
if ("error" in res) {
|
971
1323
|
toggleNotification({
|
@@ -976,39 +1328,77 @@ const useDocumentActions = () => {
|
|
976
1328
|
}
|
977
1329
|
toggleNotification({
|
978
1330
|
type: "success",
|
979
|
-
|
980
|
-
id: "
|
981
|
-
defaultMessage: "
|
982
|
-
})
|
1331
|
+
title: formatMessage({
|
1332
|
+
id: getTranslation("success.records.delete"),
|
1333
|
+
defaultMessage: "Successfully deleted."
|
1334
|
+
}),
|
1335
|
+
message: ""
|
983
1336
|
});
|
1337
|
+
trackUsage("didBulkDeleteEntries");
|
984
1338
|
return res.data;
|
985
1339
|
} catch (err) {
|
986
1340
|
toggleNotification({
|
987
1341
|
type: "danger",
|
988
1342
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
989
1343
|
});
|
1344
|
+
trackUsage("didNotBulkDeleteEntries");
|
990
1345
|
throw err;
|
991
1346
|
}
|
992
1347
|
},
|
993
|
-
[
|
1348
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
994
1349
|
);
|
995
|
-
const [
|
996
|
-
const
|
997
|
-
async ({ collectionType, model, documentId, params }
|
1350
|
+
const [discardDocument] = useDiscardDocumentMutation();
|
1351
|
+
const discard = React__namespace.useCallback(
|
1352
|
+
async ({ collectionType, model, documentId, params }) => {
|
998
1353
|
try {
|
999
|
-
|
1000
|
-
const res = await publishDocument({
|
1354
|
+
const res = await discardDocument({
|
1001
1355
|
collectionType,
|
1002
1356
|
model,
|
1003
1357
|
documentId,
|
1004
|
-
data,
|
1005
1358
|
params
|
1006
1359
|
});
|
1007
1360
|
if ("error" in res) {
|
1008
|
-
toggleNotification({
|
1361
|
+
toggleNotification({
|
1362
|
+
type: "danger",
|
1363
|
+
message: formatAPIError(res.error)
|
1364
|
+
});
|
1009
1365
|
return { error: res.error };
|
1010
1366
|
}
|
1011
|
-
|
1367
|
+
toggleNotification({
|
1368
|
+
type: "success",
|
1369
|
+
message: formatMessage({
|
1370
|
+
id: "content-manager.success.record.discard",
|
1371
|
+
defaultMessage: "Changes discarded"
|
1372
|
+
})
|
1373
|
+
});
|
1374
|
+
return res.data;
|
1375
|
+
} catch (err) {
|
1376
|
+
toggleNotification({
|
1377
|
+
type: "danger",
|
1378
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1379
|
+
});
|
1380
|
+
throw err;
|
1381
|
+
}
|
1382
|
+
},
|
1383
|
+
[discardDocument, formatAPIError, formatMessage, toggleNotification]
|
1384
|
+
);
|
1385
|
+
const [publishDocument] = usePublishDocumentMutation();
|
1386
|
+
const publish = React__namespace.useCallback(
|
1387
|
+
async ({ collectionType, model, documentId, params }, data) => {
|
1388
|
+
try {
|
1389
|
+
trackUsage("willPublishEntry");
|
1390
|
+
const res = await publishDocument({
|
1391
|
+
collectionType,
|
1392
|
+
model,
|
1393
|
+
documentId,
|
1394
|
+
data,
|
1395
|
+
params
|
1396
|
+
});
|
1397
|
+
if ("error" in res) {
|
1398
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1399
|
+
return { error: res.error };
|
1400
|
+
}
|
1401
|
+
trackUsage("didPublishEntry");
|
1012
1402
|
toggleNotification({
|
1013
1403
|
type: "success",
|
1014
1404
|
message: formatMessage({
|
@@ -1027,6 +1417,43 @@ const useDocumentActions = () => {
|
|
1027
1417
|
},
|
1028
1418
|
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1029
1419
|
);
|
1420
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1421
|
+
const publishMany = React__namespace.useCallback(
|
1422
|
+
async ({ model, documentIds, params }) => {
|
1423
|
+
try {
|
1424
|
+
const res = await publishManyDocuments({
|
1425
|
+
model,
|
1426
|
+
documentIds,
|
1427
|
+
params
|
1428
|
+
});
|
1429
|
+
if ("error" in res) {
|
1430
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1431
|
+
return { error: res.error };
|
1432
|
+
}
|
1433
|
+
toggleNotification({
|
1434
|
+
type: "success",
|
1435
|
+
message: formatMessage({
|
1436
|
+
id: getTranslation("success.record.publish"),
|
1437
|
+
defaultMessage: "Published document"
|
1438
|
+
})
|
1439
|
+
});
|
1440
|
+
return res.data;
|
1441
|
+
} catch (err) {
|
1442
|
+
toggleNotification({
|
1443
|
+
type: "danger",
|
1444
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1445
|
+
});
|
1446
|
+
throw err;
|
1447
|
+
}
|
1448
|
+
},
|
1449
|
+
[
|
1450
|
+
// trackUsage,
|
1451
|
+
publishManyDocuments,
|
1452
|
+
toggleNotification,
|
1453
|
+
formatMessage,
|
1454
|
+
formatAPIError
|
1455
|
+
]
|
1456
|
+
);
|
1030
1457
|
const [updateDocument] = useUpdateDocumentMutation();
|
1031
1458
|
const update = React__namespace.useCallback(
|
1032
1459
|
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
@@ -1101,6 +1528,41 @@ const useDocumentActions = () => {
|
|
1101
1528
|
},
|
1102
1529
|
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1103
1530
|
);
|
1531
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1532
|
+
const unpublishMany = React__namespace.useCallback(
|
1533
|
+
async ({ model, documentIds, params }) => {
|
1534
|
+
try {
|
1535
|
+
trackUsage("willBulkUnpublishEntries");
|
1536
|
+
const res = await unpublishManyDocuments({
|
1537
|
+
model,
|
1538
|
+
documentIds,
|
1539
|
+
params
|
1540
|
+
});
|
1541
|
+
if ("error" in res) {
|
1542
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1543
|
+
return { error: res.error };
|
1544
|
+
}
|
1545
|
+
trackUsage("didBulkUnpublishEntries");
|
1546
|
+
toggleNotification({
|
1547
|
+
type: "success",
|
1548
|
+
title: formatMessage({
|
1549
|
+
id: getTranslation("success.records.unpublish"),
|
1550
|
+
defaultMessage: "Successfully unpublished."
|
1551
|
+
}),
|
1552
|
+
message: ""
|
1553
|
+
});
|
1554
|
+
return res.data;
|
1555
|
+
} catch (err) {
|
1556
|
+
toggleNotification({
|
1557
|
+
type: "danger",
|
1558
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1559
|
+
});
|
1560
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1561
|
+
throw err;
|
1562
|
+
}
|
1563
|
+
},
|
1564
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1565
|
+
);
|
1104
1566
|
const [createDocument] = useCreateDocumentMutation();
|
1105
1567
|
const create = React__namespace.useCallback(
|
1106
1568
|
async ({ model, params }, data, trackerProperty) => {
|
@@ -1123,6 +1585,7 @@ const useDocumentActions = () => {
|
|
1123
1585
|
defaultMessage: "Saved document"
|
1124
1586
|
})
|
1125
1587
|
});
|
1588
|
+
setCurrentStep("contentManager.success");
|
1126
1589
|
return res.data;
|
1127
1590
|
} catch (err) {
|
1128
1591
|
toggleNotification({
|
@@ -1144,7 +1607,6 @@ const useDocumentActions = () => {
|
|
1144
1607
|
sourceId
|
1145
1608
|
});
|
1146
1609
|
if ("error" in res) {
|
1147
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1148
1610
|
return { error: res.error };
|
1149
1611
|
}
|
1150
1612
|
toggleNotification({
|
@@ -1163,7 +1625,7 @@ const useDocumentActions = () => {
|
|
1163
1625
|
throw err;
|
1164
1626
|
}
|
1165
1627
|
},
|
1166
|
-
[autoCloneDocument,
|
1628
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1167
1629
|
);
|
1168
1630
|
const [cloneDocument] = useCloneDocumentMutation();
|
1169
1631
|
const clone = React__namespace.useCallback(
|
@@ -1189,6 +1651,7 @@ const useDocumentActions = () => {
|
|
1189
1651
|
defaultMessage: "Cloned document"
|
1190
1652
|
})
|
1191
1653
|
});
|
1654
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1192
1655
|
return res.data;
|
1193
1656
|
} catch (err) {
|
1194
1657
|
toggleNotification({
|
@@ -1199,7 +1662,7 @@ const useDocumentActions = () => {
|
|
1199
1662
|
throw err;
|
1200
1663
|
}
|
1201
1664
|
},
|
1202
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1665
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1203
1666
|
);
|
1204
1667
|
const [getDoc] = useLazyGetDocumentQuery();
|
1205
1668
|
const getDocument = React__namespace.useCallback(
|
@@ -1214,17 +1677,20 @@ const useDocumentActions = () => {
|
|
1214
1677
|
clone,
|
1215
1678
|
create,
|
1216
1679
|
delete: _delete,
|
1680
|
+
deleteMany,
|
1217
1681
|
discard,
|
1218
1682
|
getDocument,
|
1219
1683
|
publish,
|
1684
|
+
publishMany,
|
1220
1685
|
unpublish,
|
1686
|
+
unpublishMany,
|
1221
1687
|
update
|
1222
1688
|
};
|
1223
1689
|
};
|
1224
|
-
const ProtectedHistoryPage =
|
1225
|
-
() => Promise.resolve().then(() => require("./History-
|
1690
|
+
const ProtectedHistoryPage = React__namespace.lazy(
|
1691
|
+
() => Promise.resolve().then(() => require("./History-BMndx49M.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1226
1692
|
);
|
1227
|
-
const routes$
|
1693
|
+
const routes$2 = [
|
1228
1694
|
{
|
1229
1695
|
path: ":collectionType/:slug/:id/history",
|
1230
1696
|
Component: ProtectedHistoryPage
|
@@ -1234,32 +1700,45 @@ const routes$1 = [
|
|
1234
1700
|
Component: ProtectedHistoryPage
|
1235
1701
|
}
|
1236
1702
|
];
|
1703
|
+
const ProtectedPreviewPage = React__namespace.lazy(
|
1704
|
+
() => Promise.resolve().then(() => require("./Preview-B7PR3Ok_.js")).then((mod) => ({ default: mod.ProtectedPreviewPage }))
|
1705
|
+
);
|
1706
|
+
const routes$1 = [
|
1707
|
+
{
|
1708
|
+
path: ":collectionType/:slug/:id/preview",
|
1709
|
+
Component: ProtectedPreviewPage
|
1710
|
+
},
|
1711
|
+
{
|
1712
|
+
path: ":collectionType/:slug/preview",
|
1713
|
+
Component: ProtectedPreviewPage
|
1714
|
+
}
|
1715
|
+
];
|
1237
1716
|
const ProtectedEditViewPage = React.lazy(
|
1238
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1717
|
+
() => Promise.resolve().then(() => require("./EditViewPage-DT6A4ayX.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1239
1718
|
);
|
1240
1719
|
const ProtectedListViewPage = React.lazy(
|
1241
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1720
|
+
() => Promise.resolve().then(() => require("./ListViewPage-BPVmh9pq.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1242
1721
|
);
|
1243
1722
|
const ProtectedListConfiguration = React.lazy(
|
1244
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1723
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-DouY1EWM.js")).then((mod) => ({
|
1245
1724
|
default: mod.ProtectedListConfiguration
|
1246
1725
|
}))
|
1247
1726
|
);
|
1248
1727
|
const ProtectedEditConfigurationPage = React.lazy(
|
1249
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1728
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-uy-v43AR.js")).then((mod) => ({
|
1250
1729
|
default: mod.ProtectedEditConfigurationPage
|
1251
1730
|
}))
|
1252
1731
|
);
|
1253
1732
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1254
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1733
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-BlzvDpbX.js")).then((mod) => ({
|
1255
1734
|
default: mod.ProtectedComponentConfigurationPage
|
1256
1735
|
}))
|
1257
1736
|
);
|
1258
1737
|
const NoPermissions = React.lazy(
|
1259
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1738
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-BMFKVcwJ.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1260
1739
|
);
|
1261
1740
|
const NoContentType = React.lazy(
|
1262
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1741
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-BwcL--4H.js")).then((mod) => ({ default: mod.NoContentType }))
|
1263
1742
|
);
|
1264
1743
|
const CollectionTypePages = () => {
|
1265
1744
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1271,7 +1750,7 @@ const CollectionTypePages = () => {
|
|
1271
1750
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1272
1751
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1273
1752
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1274
|
-
const LIST_PATH = `/content-manager
|
1753
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1275
1754
|
const routes = [
|
1276
1755
|
{
|
1277
1756
|
path: LIST_RELATIVE_PATH,
|
@@ -1305,6 +1784,7 @@ const routes = [
|
|
1305
1784
|
path: "no-content-types",
|
1306
1785
|
Component: NoContentType
|
1307
1786
|
},
|
1787
|
+
...routes$2,
|
1308
1788
|
...routes$1
|
1309
1789
|
];
|
1310
1790
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1373,12 +1853,14 @@ const DocumentActionButton = (action) => {
|
|
1373
1853
|
/* @__PURE__ */ jsxRuntime.jsx(
|
1374
1854
|
designSystem.Button,
|
1375
1855
|
{
|
1376
|
-
flex:
|
1856
|
+
flex: "auto",
|
1377
1857
|
startIcon: action.icon,
|
1378
1858
|
disabled: action.disabled,
|
1379
1859
|
onClick: handleClick(action),
|
1380
1860
|
justifyContent: "center",
|
1381
1861
|
variant: action.variant || "default",
|
1862
|
+
paddingTop: "7px",
|
1863
|
+
paddingBottom: "7px",
|
1382
1864
|
children: action.label
|
1383
1865
|
}
|
1384
1866
|
),
|
@@ -1386,7 +1868,7 @@ const DocumentActionButton = (action) => {
|
|
1386
1868
|
DocumentActionConfirmDialog,
|
1387
1869
|
{
|
1388
1870
|
...action.dialog,
|
1389
|
-
variant: action.variant,
|
1871
|
+
variant: action.dialog?.variant ?? action.variant,
|
1390
1872
|
isOpen: dialogId === action.id,
|
1391
1873
|
onClose: handleClose
|
1392
1874
|
}
|
@@ -1401,6 +1883,11 @@ const DocumentActionButton = (action) => {
|
|
1401
1883
|
) : null
|
1402
1884
|
] });
|
1403
1885
|
};
|
1886
|
+
const MenuItem = styledComponents.styled(designSystem.Menu.Item)`
|
1887
|
+
&:hover {
|
1888
|
+
background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
|
1889
|
+
}
|
1890
|
+
`;
|
1404
1891
|
const DocumentActionsMenu = ({
|
1405
1892
|
actions: actions2,
|
1406
1893
|
children,
|
@@ -1443,49 +1930,48 @@ const DocumentActionsMenu = ({
|
|
1443
1930
|
disabled: isDisabled,
|
1444
1931
|
size: "S",
|
1445
1932
|
endIcon: null,
|
1446
|
-
paddingTop: "
|
1447
|
-
paddingLeft: "
|
1448
|
-
paddingRight: "
|
1933
|
+
paddingTop: "4px",
|
1934
|
+
paddingLeft: "7px",
|
1935
|
+
paddingRight: "7px",
|
1449
1936
|
variant,
|
1450
1937
|
children: [
|
1451
1938
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
1452
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, {
|
1939
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1453
1940
|
id: "content-manager.containers.edit.panels.default.more-actions",
|
1454
1941
|
defaultMessage: "More document actions"
|
1455
1942
|
}) })
|
1456
1943
|
]
|
1457
1944
|
}
|
1458
1945
|
),
|
1459
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, {
|
1946
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1460
1947
|
actions2.map((action) => {
|
1461
1948
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
1462
|
-
|
1949
|
+
MenuItem,
|
1463
1950
|
{
|
1464
1951
|
disabled: action.disabled,
|
1465
1952
|
onSelect: handleClick(action),
|
1466
1953
|
display: "block",
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
] })
|
1954
|
+
isVariantDanger: action.variant === "danger",
|
1955
|
+
isDisabled: action.disabled,
|
1956
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
1957
|
+
designSystem.Flex,
|
1958
|
+
{
|
1959
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1960
|
+
gap: 2,
|
1961
|
+
tag: "span",
|
1962
|
+
children: [
|
1963
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1964
|
+
designSystem.Flex,
|
1965
|
+
{
|
1966
|
+
tag: "span",
|
1967
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1968
|
+
children: action.icon
|
1969
|
+
}
|
1970
|
+
),
|
1971
|
+
action.label
|
1972
|
+
]
|
1973
|
+
}
|
1974
|
+
) })
|
1489
1975
|
},
|
1490
1976
|
action.id
|
1491
1977
|
);
|
@@ -1527,6 +2013,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
|
|
1527
2013
|
return "primary600";
|
1528
2014
|
}
|
1529
2015
|
};
|
2016
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
2017
|
+
switch (variant) {
|
2018
|
+
case "danger":
|
2019
|
+
return "danger600";
|
2020
|
+
case "secondary":
|
2021
|
+
return "neutral500";
|
2022
|
+
case "success":
|
2023
|
+
return "success600";
|
2024
|
+
default:
|
2025
|
+
return "primary600";
|
2026
|
+
}
|
2027
|
+
};
|
1530
2028
|
const DocumentActionConfirmDialog = ({
|
1531
2029
|
onClose,
|
1532
2030
|
onCancel,
|
@@ -1549,61 +2047,54 @@ const DocumentActionConfirmDialog = ({
|
|
1549
2047
|
}
|
1550
2048
|
onClose();
|
1551
2049
|
};
|
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
|
-
] });
|
2050
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2051
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2052
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
2053
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
2054
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
2055
|
+
id: "app.components.Button.cancel",
|
2056
|
+
defaultMessage: "Cancel"
|
2057
|
+
}) }) }),
|
2058
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
2059
|
+
id: "app.components.Button.confirm",
|
2060
|
+
defaultMessage: "Confirm"
|
2061
|
+
}) })
|
2062
|
+
] })
|
2063
|
+
] }) });
|
1568
2064
|
};
|
1569
2065
|
const DocumentActionModal = ({
|
1570
2066
|
isOpen,
|
1571
2067
|
title,
|
1572
2068
|
onClose,
|
1573
2069
|
footer: Footer,
|
1574
|
-
content,
|
2070
|
+
content: Content,
|
1575
2071
|
onModalClose
|
1576
2072
|
}) => {
|
1577
|
-
const id = React__namespace.useId();
|
1578
|
-
if (!isOpen) {
|
1579
|
-
return null;
|
1580
|
-
}
|
1581
2073
|
const handleClose = () => {
|
1582
2074
|
if (onClose) {
|
1583
2075
|
onClose();
|
1584
2076
|
}
|
1585
2077
|
onModalClose();
|
1586
2078
|
};
|
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
|
-
] });
|
2079
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
|
2080
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
|
2081
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
|
2082
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
2083
|
+
] }) });
|
2084
|
+
};
|
2085
|
+
const transformData = (data) => {
|
2086
|
+
if (Array.isArray(data)) {
|
2087
|
+
return data.map(transformData);
|
2088
|
+
}
|
2089
|
+
if (typeof data === "object" && data !== null) {
|
2090
|
+
if ("apiData" in data) {
|
2091
|
+
return data.apiData;
|
2092
|
+
}
|
2093
|
+
return mapValues__default.default(transformData)(data);
|
2094
|
+
}
|
2095
|
+
return data;
|
1605
2096
|
};
|
1606
|
-
const PublishAction = ({
|
2097
|
+
const PublishAction$1 = ({
|
1607
2098
|
activeTab,
|
1608
2099
|
documentId,
|
1609
2100
|
model,
|
@@ -1615,13 +2106,18 @@ const PublishAction = ({
|
|
1615
2106
|
const navigate = reactRouterDom.useNavigate();
|
1616
2107
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1617
2108
|
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2109
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
1618
2110
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2111
|
+
const { id } = reactRouterDom.useParams();
|
1619
2112
|
const { formatMessage } = reactIntl.useIntl();
|
1620
|
-
const { canPublish
|
1621
|
-
"PublishAction",
|
1622
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1623
|
-
);
|
2113
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1624
2114
|
const { publish } = useDocumentActions();
|
2115
|
+
const [
|
2116
|
+
countDraftRelations,
|
2117
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2118
|
+
] = useLazyGetDraftRelationCountQuery();
|
2119
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
2120
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1625
2121
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1626
2122
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1627
2123
|
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1630,10 +2126,107 @@ const PublishAction = ({
|
|
1630
2126
|
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1631
2127
|
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1632
2128
|
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
2129
|
+
React__namespace.useEffect(() => {
|
2130
|
+
if (isErrorDraftRelations) {
|
2131
|
+
toggleNotification({
|
2132
|
+
type: "danger",
|
2133
|
+
message: formatMessage({
|
2134
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2135
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2136
|
+
})
|
2137
|
+
});
|
2138
|
+
}
|
2139
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2140
|
+
React__namespace.useEffect(() => {
|
2141
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2142
|
+
const extractDraftRelations = (data) => {
|
2143
|
+
const relations = data.connect || [];
|
2144
|
+
relations.forEach((relation) => {
|
2145
|
+
if (relation.status === "draft") {
|
2146
|
+
localDraftRelations.add(relation.id);
|
2147
|
+
}
|
2148
|
+
});
|
2149
|
+
};
|
2150
|
+
const traverseAndExtract = (data) => {
|
2151
|
+
Object.entries(data).forEach(([key, value]) => {
|
2152
|
+
if (key === "connect" && Array.isArray(value)) {
|
2153
|
+
extractDraftRelations({ connect: value });
|
2154
|
+
} else if (typeof value === "object" && value !== null) {
|
2155
|
+
traverseAndExtract(value);
|
2156
|
+
}
|
2157
|
+
});
|
2158
|
+
};
|
2159
|
+
if (!documentId || modified) {
|
2160
|
+
traverseAndExtract(formValues);
|
2161
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2162
|
+
}
|
2163
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2164
|
+
React__namespace.useEffect(() => {
|
2165
|
+
if (!document || !document.documentId || isListView) {
|
2166
|
+
return;
|
2167
|
+
}
|
2168
|
+
const fetchDraftRelationsCount = async () => {
|
2169
|
+
const { data, error } = await countDraftRelations({
|
2170
|
+
collectionType,
|
2171
|
+
model,
|
2172
|
+
documentId,
|
2173
|
+
params
|
2174
|
+
});
|
2175
|
+
if (error) {
|
2176
|
+
throw error;
|
2177
|
+
}
|
2178
|
+
if (data) {
|
2179
|
+
setServerCountOfDraftRelations(data.data);
|
2180
|
+
}
|
2181
|
+
};
|
2182
|
+
fetchDraftRelationsCount();
|
2183
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
1633
2184
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1634
2185
|
if (!schema?.options?.draftAndPublish) {
|
1635
2186
|
return null;
|
1636
2187
|
}
|
2188
|
+
const performPublish = async () => {
|
2189
|
+
setSubmitting(true);
|
2190
|
+
try {
|
2191
|
+
const { errors } = await validate(true, {
|
2192
|
+
status: "published"
|
2193
|
+
});
|
2194
|
+
if (errors) {
|
2195
|
+
toggleNotification({
|
2196
|
+
type: "danger",
|
2197
|
+
message: formatMessage({
|
2198
|
+
id: "content-manager.validation.error",
|
2199
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2200
|
+
})
|
2201
|
+
});
|
2202
|
+
return;
|
2203
|
+
}
|
2204
|
+
const res = await publish(
|
2205
|
+
{
|
2206
|
+
collectionType,
|
2207
|
+
model,
|
2208
|
+
documentId,
|
2209
|
+
params
|
2210
|
+
},
|
2211
|
+
transformData(formValues)
|
2212
|
+
);
|
2213
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2214
|
+
if (id === "create") {
|
2215
|
+
navigate({
|
2216
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2217
|
+
search: rawQuery
|
2218
|
+
});
|
2219
|
+
}
|
2220
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2221
|
+
setErrors(formatValidationErrors(res.error));
|
2222
|
+
}
|
2223
|
+
} finally {
|
2224
|
+
setSubmitting(false);
|
2225
|
+
}
|
2226
|
+
};
|
2227
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2228
|
+
const enableDraftRelationsCount = false;
|
2229
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1637
2230
|
return {
|
1638
2231
|
/**
|
1639
2232
|
* Disabled when:
|
@@ -1643,52 +2236,40 @@ const PublishAction = ({
|
|
1643
2236
|
* - the document is already published & not modified
|
1644
2237
|
* - the document is being created & not modified
|
1645
2238
|
* - 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
2239
|
*/
|
1649
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2240
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1650
2241
|
label: formatMessage({
|
1651
2242
|
id: "app.utils.publish",
|
1652
2243
|
defaultMessage: "Publish"
|
1653
2244
|
}),
|
1654
2245
|
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));
|
2246
|
+
await performPublish();
|
2247
|
+
},
|
2248
|
+
dialog: hasDraftRelations ? {
|
2249
|
+
type: "dialog",
|
2250
|
+
variant: "danger",
|
2251
|
+
footer: null,
|
2252
|
+
title: formatMessage({
|
2253
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2254
|
+
defaultMessage: "Confirmation"
|
2255
|
+
}),
|
2256
|
+
content: formatMessage(
|
2257
|
+
{
|
2258
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2259
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2260
|
+
},
|
2261
|
+
{
|
2262
|
+
count: totalDraftRelations
|
1684
2263
|
}
|
1685
|
-
|
1686
|
-
|
2264
|
+
),
|
2265
|
+
onConfirm: async () => {
|
2266
|
+
await performPublish();
|
1687
2267
|
}
|
1688
|
-
}
|
2268
|
+
} : void 0
|
1689
2269
|
};
|
1690
2270
|
};
|
1691
|
-
PublishAction.type = "publish";
|
2271
|
+
PublishAction$1.type = "publish";
|
2272
|
+
PublishAction$1.position = "panel";
|
1692
2273
|
const UpdateAction = ({
|
1693
2274
|
activeTab,
|
1694
2275
|
documentId,
|
@@ -1701,10 +2282,6 @@ const UpdateAction = ({
|
|
1701
2282
|
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
1702
2283
|
const isCloning = cloneMatch !== null;
|
1703
2284
|
const { formatMessage } = reactIntl.useIntl();
|
1704
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1705
|
-
canCreate: canCreate2,
|
1706
|
-
canUpdate: canUpdate2
|
1707
|
-
}));
|
1708
2285
|
const { create, update, clone } = useDocumentActions();
|
1709
2286
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1710
2287
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
@@ -1715,95 +2292,139 @@ const UpdateAction = ({
|
|
1715
2292
|
const validate = strapiAdmin.useForm("UpdateAction", (state) => state.validate);
|
1716
2293
|
const setErrors = strapiAdmin.useForm("UpdateAction", (state) => state.setErrors);
|
1717
2294
|
const resetForm = strapiAdmin.useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1742
|
-
|
1743
|
-
}
|
1744
|
-
|
1745
|
-
|
1746
|
-
if (
|
1747
|
-
|
2295
|
+
const handleUpdate = React__namespace.useCallback(async () => {
|
2296
|
+
setSubmitting(true);
|
2297
|
+
try {
|
2298
|
+
if (!modified) {
|
2299
|
+
return;
|
2300
|
+
}
|
2301
|
+
const { errors } = await validate(true, {
|
2302
|
+
status: "draft"
|
2303
|
+
});
|
2304
|
+
if (errors) {
|
2305
|
+
toggleNotification({
|
2306
|
+
type: "danger",
|
2307
|
+
message: formatMessage({
|
2308
|
+
id: "content-manager.validation.error",
|
2309
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2310
|
+
})
|
2311
|
+
});
|
2312
|
+
return;
|
2313
|
+
}
|
2314
|
+
if (isCloning) {
|
2315
|
+
const res = await clone(
|
2316
|
+
{
|
2317
|
+
model,
|
2318
|
+
documentId: cloneMatch.params.origin,
|
2319
|
+
params
|
2320
|
+
},
|
2321
|
+
transformData(document)
|
2322
|
+
);
|
2323
|
+
if ("data" in res) {
|
2324
|
+
navigate(
|
1748
2325
|
{
|
1749
|
-
|
1750
|
-
documentId: cloneMatch.params.origin,
|
1751
|
-
params
|
1752
|
-
},
|
1753
|
-
document
|
1754
|
-
);
|
1755
|
-
if ("data" in res) {
|
1756
|
-
navigate({
|
1757
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2326
|
+
pathname: `../${res.data.documentId}`,
|
1758
2327
|
search: rawQuery
|
1759
|
-
});
|
1760
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1761
|
-
setErrors(formatValidationErrors(res.error));
|
1762
|
-
}
|
1763
|
-
} else if (documentId || collectionType === SINGLE_TYPES) {
|
1764
|
-
const res = await update(
|
1765
|
-
{
|
1766
|
-
collectionType,
|
1767
|
-
model,
|
1768
|
-
documentId,
|
1769
|
-
params
|
1770
|
-
},
|
1771
|
-
document
|
1772
|
-
);
|
1773
|
-
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1774
|
-
setErrors(formatValidationErrors(res.error));
|
1775
|
-
} else {
|
1776
|
-
resetForm();
|
1777
|
-
}
|
1778
|
-
} else {
|
1779
|
-
const res = await create(
|
1780
|
-
{
|
1781
|
-
model,
|
1782
|
-
params
|
1783
2328
|
},
|
1784
|
-
|
2329
|
+
{ relative: "path" }
|
1785
2330
|
);
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
2331
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2332
|
+
setErrors(formatValidationErrors(res.error));
|
2333
|
+
}
|
2334
|
+
} else if (documentId || collectionType === SINGLE_TYPES) {
|
2335
|
+
const res = await update(
|
2336
|
+
{
|
2337
|
+
collectionType,
|
2338
|
+
model,
|
2339
|
+
documentId,
|
2340
|
+
params
|
2341
|
+
},
|
2342
|
+
transformData(document)
|
2343
|
+
);
|
2344
|
+
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2345
|
+
setErrors(formatValidationErrors(res.error));
|
2346
|
+
} else {
|
2347
|
+
resetForm();
|
2348
|
+
}
|
2349
|
+
} else {
|
2350
|
+
const res = await create(
|
2351
|
+
{
|
2352
|
+
model,
|
2353
|
+
params
|
2354
|
+
},
|
2355
|
+
transformData(document)
|
2356
|
+
);
|
2357
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2358
|
+
navigate(
|
2359
|
+
{
|
2360
|
+
pathname: `../${res.data.documentId}`,
|
2361
|
+
search: rawQuery
|
2362
|
+
},
|
2363
|
+
{ replace: true, relative: "path" }
|
2364
|
+
);
|
2365
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2366
|
+
setErrors(formatValidationErrors(res.error));
|
2367
|
+
}
|
1797
2368
|
}
|
2369
|
+
} finally {
|
2370
|
+
setSubmitting(false);
|
1798
2371
|
}
|
2372
|
+
}, [
|
2373
|
+
clone,
|
2374
|
+
cloneMatch?.params.origin,
|
2375
|
+
collectionType,
|
2376
|
+
create,
|
2377
|
+
document,
|
2378
|
+
documentId,
|
2379
|
+
formatMessage,
|
2380
|
+
formatValidationErrors,
|
2381
|
+
isCloning,
|
2382
|
+
model,
|
2383
|
+
modified,
|
2384
|
+
navigate,
|
2385
|
+
params,
|
2386
|
+
rawQuery,
|
2387
|
+
resetForm,
|
2388
|
+
setErrors,
|
2389
|
+
setSubmitting,
|
2390
|
+
toggleNotification,
|
2391
|
+
update,
|
2392
|
+
validate
|
2393
|
+
]);
|
2394
|
+
React__namespace.useEffect(() => {
|
2395
|
+
const handleKeyDown = (e) => {
|
2396
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
2397
|
+
e.preventDefault();
|
2398
|
+
handleUpdate();
|
2399
|
+
}
|
2400
|
+
};
|
2401
|
+
window.addEventListener("keydown", handleKeyDown);
|
2402
|
+
return () => {
|
2403
|
+
window.removeEventListener("keydown", handleKeyDown);
|
2404
|
+
};
|
2405
|
+
}, [handleUpdate]);
|
2406
|
+
return {
|
2407
|
+
/**
|
2408
|
+
* Disabled when:
|
2409
|
+
* - the form is submitting
|
2410
|
+
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
2411
|
+
* - the active tab is the published tab
|
2412
|
+
*/
|
2413
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
2414
|
+
label: formatMessage({
|
2415
|
+
id: "global.save",
|
2416
|
+
defaultMessage: "Save"
|
2417
|
+
}),
|
2418
|
+
onClick: handleUpdate
|
1799
2419
|
};
|
1800
2420
|
};
|
1801
2421
|
UpdateAction.type = "update";
|
2422
|
+
UpdateAction.position = "panel";
|
1802
2423
|
const UNPUBLISH_DRAFT_OPTIONS = {
|
1803
2424
|
KEEP: "keep",
|
1804
2425
|
DISCARD: "discard"
|
1805
2426
|
};
|
1806
|
-
const UnpublishAction = ({
|
2427
|
+
const UnpublishAction$1 = ({
|
1807
2428
|
activeTab,
|
1808
2429
|
documentId,
|
1809
2430
|
model,
|
@@ -1819,10 +2440,8 @@ const UnpublishAction = ({
|
|
1819
2440
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1820
2441
|
const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
|
1821
2442
|
const isDocumentModified = document?.status === "modified";
|
1822
|
-
const handleChange = (
|
1823
|
-
|
1824
|
-
setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1825
|
-
}
|
2443
|
+
const handleChange = (value) => {
|
2444
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1826
2445
|
};
|
1827
2446
|
if (!schema?.options?.draftAndPublish) {
|
1828
2447
|
return null;
|
@@ -1833,7 +2452,7 @@ const UnpublishAction = ({
|
|
1833
2452
|
id: "app.utils.unpublish",
|
1834
2453
|
defaultMessage: "Unpublish"
|
1835
2454
|
}),
|
1836
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2455
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1837
2456
|
onClick: async () => {
|
1838
2457
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1839
2458
|
if (!documentId) {
|
@@ -1866,45 +2485,30 @@ const UnpublishAction = ({
|
|
1866
2485
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
|
1867
2486
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
|
1868
2487
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
1869
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2488
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
1870
2489
|
id: "content-manager.actions.unpublish.dialog.body",
|
1871
2490
|
defaultMessage: "Are you sure?"
|
1872
2491
|
}) })
|
1873
2492
|
] }),
|
1874
2493
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
1875
|
-
designSystem.
|
2494
|
+
designSystem.Radio.Group,
|
1876
2495
|
{
|
1877
|
-
|
1878
|
-
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
2496
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2497
|
+
name: "discard-options",
|
2498
|
+
"aria-label": formatMessage({
|
2499
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2500
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2501
|
+
}),
|
2502
|
+
onValueChange: handleChange,
|
1882
2503
|
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
|
-
)
|
2504
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2505
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2506
|
+
defaultMessage: "Keep draft"
|
2507
|
+
}) }),
|
2508
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2509
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2510
|
+
defaultMessage: "Replace draft"
|
2511
|
+
}) })
|
1908
2512
|
]
|
1909
2513
|
}
|
1910
2514
|
)
|
@@ -1937,7 +2541,8 @@ const UnpublishAction = ({
|
|
1937
2541
|
position: ["panel", "table-row"]
|
1938
2542
|
};
|
1939
2543
|
};
|
1940
|
-
UnpublishAction.type = "unpublish";
|
2544
|
+
UnpublishAction$1.type = "unpublish";
|
2545
|
+
UnpublishAction$1.position = "panel";
|
1941
2546
|
const DiscardAction = ({
|
1942
2547
|
activeTab,
|
1943
2548
|
documentId,
|
@@ -1960,7 +2565,7 @@ const DiscardAction = ({
|
|
1960
2565
|
id: "content-manager.actions.discard.label",
|
1961
2566
|
defaultMessage: "Discard changes"
|
1962
2567
|
}),
|
1963
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2568
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1964
2569
|
position: ["panel", "table-row"],
|
1965
2570
|
variant: "danger",
|
1966
2571
|
dialog: {
|
@@ -1971,7 +2576,7 @@ const DiscardAction = ({
|
|
1971
2576
|
}),
|
1972
2577
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
1973
2578
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
1974
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2579
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
1975
2580
|
id: "content-manager.actions.discard.dialog.body",
|
1976
2581
|
defaultMessage: "Are you sure?"
|
1977
2582
|
}) })
|
@@ -1988,12 +2593,8 @@ const DiscardAction = ({
|
|
1988
2593
|
};
|
1989
2594
|
};
|
1990
2595
|
DiscardAction.type = "discard";
|
1991
|
-
|
1992
|
-
|
1993
|
-
fill: currentColor;
|
1994
|
-
}
|
1995
|
-
`;
|
1996
|
-
const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
|
2596
|
+
DiscardAction.position = "panel";
|
2597
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
1997
2598
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
1998
2599
|
const RelativeTime = React__namespace.forwardRef(
|
1999
2600
|
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
@@ -2005,7 +2606,7 @@ const RelativeTime = React__namespace.forwardRef(
|
|
2005
2606
|
});
|
2006
2607
|
const unit = intervals.find((intervalUnit) => {
|
2007
2608
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2008
|
-
});
|
2609
|
+
}) ?? "seconds";
|
2009
2610
|
const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
|
2010
2611
|
const customInterval = customIntervals.find(
|
2011
2612
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2039,34 +2640,34 @@ const getDisplayName = ({
|
|
2039
2640
|
return email ?? "";
|
2040
2641
|
};
|
2041
2642
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2042
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2043
|
-
const statusVariant = status === "draft" ? "
|
2044
|
-
|
2643
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2644
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2645
|
+
const { formatMessage } = reactIntl.useIntl();
|
2646
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2647
|
+
id: `content-manager.containers.List.${status}`,
|
2648
|
+
defaultMessage: capitalise(status)
|
2649
|
+
}) }) });
|
2045
2650
|
};
|
2046
2651
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2047
2652
|
const { formatMessage } = reactIntl.useIntl();
|
2048
2653
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2654
|
+
const params = reactRouterDom.useParams();
|
2049
2655
|
const title = isCreating ? formatMessage({
|
2050
2656
|
id: "content-manager.containers.edit.title.new",
|
2051
2657
|
defaultMessage: "Create an entry"
|
2052
2658
|
}) : documentTitle;
|
2053
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2054
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2055
|
-
|
2056
|
-
designSystem.Flex,
|
2659
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2660
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2661
|
+
strapiAdmin.BackButton,
|
2057
2662
|
{
|
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
|
-
]
|
2663
|
+
fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
|
2067
2664
|
}
|
2068
2665
|
),
|
2069
|
-
|
2666
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2667
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2668
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2669
|
+
] }),
|
2670
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2070
2671
|
] });
|
2071
2672
|
};
|
2072
2673
|
const HeaderToolbar = () => {
|
@@ -2112,7 +2713,7 @@ const HeaderToolbar = () => {
|
|
2112
2713
|
meta: isCloning ? void 0 : meta,
|
2113
2714
|
collectionType
|
2114
2715
|
},
|
2115
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2716
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
|
2116
2717
|
children: (actions2) => {
|
2117
2718
|
const headerActions = actions2.filter((action) => {
|
2118
2719
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -2149,12 +2750,12 @@ const Information = ({ activeTab }) => {
|
|
2149
2750
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2150
2751
|
label: formatMessage({
|
2151
2752
|
id: "content-manager.containers.edit.information.last-published.label",
|
2152
|
-
defaultMessage: "
|
2753
|
+
defaultMessage: "Published"
|
2153
2754
|
}),
|
2154
2755
|
value: formatMessage(
|
2155
2756
|
{
|
2156
2757
|
id: "content-manager.containers.edit.information.last-published.value",
|
2157
|
-
defaultMessage: `
|
2758
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2158
2759
|
},
|
2159
2760
|
{
|
2160
2761
|
time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2167,12 +2768,12 @@ const Information = ({ activeTab }) => {
|
|
2167
2768
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2168
2769
|
label: formatMessage({
|
2169
2770
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2170
|
-
defaultMessage: "
|
2771
|
+
defaultMessage: "Updated"
|
2171
2772
|
}),
|
2172
2773
|
value: formatMessage(
|
2173
2774
|
{
|
2174
2775
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2175
|
-
defaultMessage: `
|
2776
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2176
2777
|
},
|
2177
2778
|
{
|
2178
2779
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2190,12 +2791,12 @@ const Information = ({ activeTab }) => {
|
|
2190
2791
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2191
2792
|
label: formatMessage({
|
2192
2793
|
id: "content-manager.containers.edit.information.document.label",
|
2193
|
-
defaultMessage: "
|
2794
|
+
defaultMessage: "Created"
|
2194
2795
|
}),
|
2195
2796
|
value: formatMessage(
|
2196
2797
|
{
|
2197
2798
|
id: "content-manager.containers.edit.information.document.value",
|
2198
|
-
defaultMessage: `
|
2799
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2199
2800
|
},
|
2200
2801
|
{
|
2201
2802
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2218,7 +2819,7 @@ const Information = ({ activeTab }) => {
|
|
2218
2819
|
borderColor: "neutral150",
|
2219
2820
|
direction: "column",
|
2220
2821
|
marginTop: 2,
|
2221
|
-
|
2822
|
+
tag: "dl",
|
2222
2823
|
padding: 5,
|
2223
2824
|
gap: 3,
|
2224
2825
|
alignItems: "flex-start",
|
@@ -2226,32 +2827,84 @@ const Information = ({ activeTab }) => {
|
|
2226
2827
|
marginRight: "-0.4rem",
|
2227
2828
|
width: "calc(100% + 8px)",
|
2228
2829
|
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, {
|
2830
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
|
2831
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
|
2231
2832
|
] }, info.label))
|
2232
2833
|
}
|
2233
2834
|
);
|
2234
2835
|
};
|
2235
2836
|
const HeaderActions = ({ actions: actions2 }) => {
|
2236
|
-
|
2237
|
-
|
2837
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2838
|
+
const handleClick = (action) => async (e) => {
|
2839
|
+
if (!("options" in action)) {
|
2840
|
+
const { onClick = () => false, dialog, id } = action;
|
2841
|
+
const muteDialog = await onClick(e);
|
2842
|
+
if (dialog && !muteDialog) {
|
2843
|
+
e.preventDefault();
|
2844
|
+
setDialogId(id);
|
2845
|
+
}
|
2846
|
+
}
|
2847
|
+
};
|
2848
|
+
const handleClose = () => {
|
2849
|
+
setDialogId(null);
|
2850
|
+
};
|
2851
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2852
|
+
if (action.options) {
|
2238
2853
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
2239
2854
|
designSystem.SingleSelect,
|
2240
2855
|
{
|
2241
2856
|
size: "S",
|
2242
|
-
disabled: action.disabled,
|
2243
|
-
"aria-label": action.label,
|
2244
2857
|
onChange: action.onSelect,
|
2245
|
-
|
2858
|
+
"aria-label": action.label,
|
2859
|
+
...action,
|
2246
2860
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2247
2861
|
},
|
2248
2862
|
action.id
|
2249
2863
|
);
|
2250
2864
|
} else {
|
2251
|
-
|
2865
|
+
if (action.type === "icon") {
|
2866
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2867
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2868
|
+
designSystem.IconButton,
|
2869
|
+
{
|
2870
|
+
disabled: action.disabled,
|
2871
|
+
label: action.label,
|
2872
|
+
size: "S",
|
2873
|
+
onClick: handleClick(action),
|
2874
|
+
children: action.icon
|
2875
|
+
}
|
2876
|
+
),
|
2877
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2878
|
+
HeaderActionDialog,
|
2879
|
+
{
|
2880
|
+
...action.dialog,
|
2881
|
+
isOpen: dialogId === action.id,
|
2882
|
+
onClose: handleClose
|
2883
|
+
}
|
2884
|
+
) : null
|
2885
|
+
] }, action.id);
|
2886
|
+
}
|
2252
2887
|
}
|
2253
2888
|
}) });
|
2254
2889
|
};
|
2890
|
+
const HeaderActionDialog = ({
|
2891
|
+
onClose,
|
2892
|
+
onCancel,
|
2893
|
+
title,
|
2894
|
+
content: Content,
|
2895
|
+
isOpen
|
2896
|
+
}) => {
|
2897
|
+
const handleClose = async () => {
|
2898
|
+
if (onCancel) {
|
2899
|
+
await onCancel();
|
2900
|
+
}
|
2901
|
+
onClose();
|
2902
|
+
};
|
2903
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2904
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2905
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2906
|
+
] }) });
|
2907
|
+
};
|
2255
2908
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2256
2909
|
const navigate = reactRouterDom.useNavigate();
|
2257
2910
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2260,7 +2913,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2260
2913
|
id: "app.links.configure-view",
|
2261
2914
|
defaultMessage: "Configure the view"
|
2262
2915
|
}),
|
2263
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2916
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
|
2264
2917
|
onClick: () => {
|
2265
2918
|
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2266
2919
|
},
|
@@ -2268,11 +2921,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2268
2921
|
};
|
2269
2922
|
};
|
2270
2923
|
ConfigureTheViewAction.type = "configure-the-view";
|
2271
|
-
|
2272
|
-
path {
|
2273
|
-
fill: currentColor;
|
2274
|
-
}
|
2275
|
-
`;
|
2924
|
+
ConfigureTheViewAction.position = "header";
|
2276
2925
|
const EditTheModelAction = ({ model }) => {
|
2277
2926
|
const navigate = reactRouterDom.useNavigate();
|
2278
2927
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2281,7 +2930,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2281
2930
|
id: "content-manager.link-to-ctb",
|
2282
2931
|
defaultMessage: "Edit the model"
|
2283
2932
|
}),
|
2284
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2933
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
|
2285
2934
|
onClick: () => {
|
2286
2935
|
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2287
2936
|
},
|
@@ -2289,12 +2938,8 @@ const EditTheModelAction = ({ model }) => {
|
|
2289
2938
|
};
|
2290
2939
|
};
|
2291
2940
|
EditTheModelAction.type = "edit-the-model";
|
2292
|
-
|
2293
|
-
|
2294
|
-
fill: currentColor;
|
2295
|
-
}
|
2296
|
-
`;
|
2297
|
-
const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
2941
|
+
EditTheModelAction.position = "header";
|
2942
|
+
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2298
2943
|
const navigate = reactRouterDom.useNavigate();
|
2299
2944
|
const { formatMessage } = reactIntl.useIntl();
|
2300
2945
|
const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
|
@@ -2302,13 +2947,17 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2302
2947
|
const { delete: deleteAction } = useDocumentActions();
|
2303
2948
|
const { toggleNotification } = strapiAdmin.useNotification();
|
2304
2949
|
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2950
|
+
const isLocalized = document?.locale != null;
|
2305
2951
|
return {
|
2306
2952
|
disabled: !canDelete || !document,
|
2307
|
-
label: formatMessage(
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2953
|
+
label: formatMessage(
|
2954
|
+
{
|
2955
|
+
id: "content-manager.actions.delete.label",
|
2956
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2957
|
+
},
|
2958
|
+
{ isLocalized }
|
2959
|
+
),
|
2960
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2312
2961
|
dialog: {
|
2313
2962
|
type: "dialog",
|
2314
2963
|
title: formatMessage({
|
@@ -2317,7 +2966,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2317
2966
|
}),
|
2318
2967
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2319
2968
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2320
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2969
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2321
2970
|
id: "content-manager.actions.delete.dialog.body",
|
2322
2971
|
defaultMessage: "Are you sure?"
|
2323
2972
|
}) })
|
@@ -2362,13 +3011,9 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2362
3011
|
position: ["header", "table-row"]
|
2363
3012
|
};
|
2364
3013
|
};
|
2365
|
-
DeleteAction.type = "delete";
|
2366
|
-
|
2367
|
-
|
2368
|
-
fill: currentColor;
|
2369
|
-
}
|
2370
|
-
`;
|
2371
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction];
|
3014
|
+
DeleteAction$1.type = "delete";
|
3015
|
+
DeleteAction$1.position = ["header", "table-row"];
|
3016
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2372
3017
|
const Panels = () => {
|
2373
3018
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2374
3019
|
const [
|
@@ -2402,7 +3047,7 @@ const ActionsPanel = () => {
|
|
2402
3047
|
return {
|
2403
3048
|
title: formatMessage({
|
2404
3049
|
id: "content-manager.containers.edit.panels.default.title",
|
2405
|
-
defaultMessage: "
|
3050
|
+
defaultMessage: "Entry"
|
2406
3051
|
}),
|
2407
3052
|
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2408
3053
|
};
|
@@ -2430,7 +3075,7 @@ const ActionsPanelContent = () => {
|
|
2430
3075
|
strapiAdmin.DescriptionComponentRenderer,
|
2431
3076
|
{
|
2432
3077
|
props,
|
2433
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3078
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
|
2434
3079
|
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
2435
3080
|
}
|
2436
3081
|
),
|
@@ -2442,7 +3087,7 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
|
2442
3087
|
designSystem.Flex,
|
2443
3088
|
{
|
2444
3089
|
ref,
|
2445
|
-
|
3090
|
+
tag: "aside",
|
2446
3091
|
"aria-labelledby": "additional-information",
|
2447
3092
|
background: "neutral0",
|
2448
3093
|
borderColor: "neutral150",
|
@@ -2457,133 +3102,707 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
|
2457
3102
|
justifyContent: "stretch",
|
2458
3103
|
alignItems: "flex-start",
|
2459
3104
|
children: [
|
2460
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
3105
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
2461
3106
|
children
|
2462
3107
|
]
|
2463
3108
|
}
|
2464
3109
|
);
|
2465
3110
|
});
|
2466
|
-
const
|
2467
|
-
|
3111
|
+
const ConfirmBulkActionDialog = ({
|
3112
|
+
onToggleDialog,
|
3113
|
+
isOpen = false,
|
3114
|
+
dialogBody,
|
3115
|
+
endAction
|
3116
|
+
}) => {
|
2468
3117
|
const { formatMessage } = reactIntl.useIntl();
|
2469
|
-
|
2470
|
-
|
2471
|
-
|
2472
|
-
|
2473
|
-
case "unique":
|
2474
|
-
return "Identical values in a unique field are not allowed";
|
2475
|
-
default:
|
2476
|
-
return reason;
|
2477
|
-
}
|
2478
|
-
};
|
2479
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
2480
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: formatMessage({
|
2481
|
-
id: getTranslation("containers.list.autoCloneModal.title"),
|
2482
|
-
defaultMessage: "This entry can't be duplicated directly."
|
3118
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
3119
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
|
3120
|
+
id: "app.components.ConfirmDialog.title",
|
3121
|
+
defaultMessage: "Confirmation"
|
2483
3122
|
}) }),
|
2484
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
2485
|
-
|
2486
|
-
|
2487
|
-
|
2488
|
-
/* @__PURE__ */ jsxRuntime.
|
2489
|
-
designSystem.
|
2490
|
-
|
2491
|
-
|
2492
|
-
|
2493
|
-
|
2494
|
-
|
2495
|
-
|
2496
|
-
padding: 6,
|
2497
|
-
children: [
|
2498
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", as: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", as: "li", children: [
|
2499
|
-
pathSegment,
|
2500
|
-
index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
2501
|
-
Icons.ChevronRight,
|
2502
|
-
{
|
2503
|
-
fill: "neutral500",
|
2504
|
-
height: "0.8rem",
|
2505
|
-
width: "0.8rem",
|
2506
|
-
style: { margin: "0 0.8rem" }
|
2507
|
-
}
|
2508
|
-
)
|
2509
|
-
] }, index2)) }),
|
2510
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "p", textColor: "neutral600", children: formatMessage({
|
2511
|
-
id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
|
2512
|
-
defaultMessage: getDefaultErrorMessage(reason)
|
2513
|
-
}) })
|
2514
|
-
]
|
2515
|
-
},
|
2516
|
-
fieldPath.join()
|
2517
|
-
)) })
|
2518
|
-
] });
|
3123
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3124
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3125
|
+
dialogBody
|
3126
|
+
] }) }),
|
3127
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
3128
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
|
3129
|
+
id: "app.components.Button.cancel",
|
3130
|
+
defaultMessage: "Cancel"
|
3131
|
+
}) }) }),
|
3132
|
+
endAction
|
3133
|
+
] })
|
3134
|
+
] }) });
|
2519
3135
|
};
|
2520
|
-
const
|
3136
|
+
const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
|
3137
|
+
const ConfirmDialogPublishAll = ({
|
3138
|
+
isOpen,
|
3139
|
+
onToggleDialog,
|
3140
|
+
isConfirmButtonLoading = false,
|
3141
|
+
onConfirm
|
3142
|
+
}) => {
|
2521
3143
|
const { formatMessage } = reactIntl.useIntl();
|
2522
|
-
const
|
2523
|
-
const
|
2524
|
-
const
|
2525
|
-
|
2526
|
-
|
2527
|
-
|
2528
|
-
|
2529
|
-
|
2530
|
-
|
3144
|
+
const selectedEntries = strapiAdmin.useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
|
3145
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
3146
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
3147
|
+
const { model, schema } = useDoc();
|
3148
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3149
|
+
const enableDraftRelationsCount = false;
|
3150
|
+
const {
|
3151
|
+
data: countDraftRelations = 0,
|
3152
|
+
isLoading,
|
3153
|
+
error
|
3154
|
+
} = useGetManyDraftRelationCountQuery(
|
3155
|
+
{
|
3156
|
+
model,
|
3157
|
+
documentIds: selectedEntries.map((entry) => entry.documentId),
|
3158
|
+
locale: query?.plugins?.i18n?.locale
|
3159
|
+
},
|
3160
|
+
{
|
3161
|
+
skip: !enableDraftRelationsCount
|
3162
|
+
}
|
3163
|
+
);
|
3164
|
+
React__namespace.useEffect(() => {
|
3165
|
+
if (error) {
|
3166
|
+
toggleNotification({ type: "danger", message: formatAPIError(error) });
|
3167
|
+
}
|
3168
|
+
}, [error, formatAPIError, toggleNotification]);
|
3169
|
+
if (error) {
|
3170
|
+
return null;
|
3171
|
+
}
|
2531
3172
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
2532
|
-
|
3173
|
+
ConfirmBulkActionDialog,
|
2533
3174
|
{
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2542
|
-
|
3175
|
+
isOpen: isOpen && !isLoading,
|
3176
|
+
onToggleDialog,
|
3177
|
+
dialogBody: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
3178
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: [
|
3179
|
+
countDraftRelations > 0 && formatMessage(
|
3180
|
+
{
|
3181
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
3182
|
+
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. "
|
3183
|
+
},
|
3184
|
+
{
|
3185
|
+
b: BoldChunk$1,
|
3186
|
+
count: countDraftRelations,
|
3187
|
+
entities: selectedEntries.length
|
3188
|
+
}
|
3189
|
+
),
|
3190
|
+
formatMessage({
|
3191
|
+
id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
|
3192
|
+
defaultMessage: "Are you sure you want to publish these entries?"
|
3193
|
+
})
|
3194
|
+
] }),
|
3195
|
+
schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
|
2543
3196
|
{
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
|
2549
|
-
variant: "ghost"
|
3197
|
+
id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
|
3198
|
+
defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
|
3199
|
+
},
|
3200
|
+
{
|
3201
|
+
em: Emphasis
|
2550
3202
|
}
|
2551
|
-
)
|
2552
|
-
}
|
3203
|
+
) })
|
3204
|
+
] }),
|
3205
|
+
endAction: /* @__PURE__ */ jsxRuntime.jsx(
|
3206
|
+
designSystem.Button,
|
3207
|
+
{
|
3208
|
+
onClick: onConfirm,
|
3209
|
+
variant: "secondary",
|
3210
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
|
3211
|
+
loading: isConfirmButtonLoading,
|
3212
|
+
children: formatMessage({
|
3213
|
+
id: "app.utils.publish",
|
3214
|
+
defaultMessage: "Publish"
|
3215
|
+
})
|
3216
|
+
}
|
3217
|
+
)
|
2553
3218
|
}
|
2554
3219
|
);
|
2555
3220
|
};
|
2556
|
-
const
|
2557
|
-
|
2558
|
-
|
2559
|
-
|
2560
|
-
const
|
2561
|
-
|
2562
|
-
|
2563
|
-
|
2564
|
-
|
2565
|
-
|
2566
|
-
|
2567
|
-
|
2568
|
-
|
2569
|
-
|
2570
|
-
|
2571
|
-
|
2572
|
-
|
2573
|
-
|
3221
|
+
const TypographyMaxWidth = styledComponents.styled(designSystem.Typography)`
|
3222
|
+
max-width: 300px;
|
3223
|
+
`;
|
3224
|
+
const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
3225
|
+
const messages = [];
|
3226
|
+
Object.entries(errors).forEach(([key, value]) => {
|
3227
|
+
const currentKey = parentKey ? `${parentKey}.${key}` : key;
|
3228
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
3229
|
+
if ("id" in value && "defaultMessage" in value) {
|
3230
|
+
messages.push(
|
3231
|
+
formatMessage(
|
3232
|
+
{
|
3233
|
+
id: `${value.id}.withField`,
|
3234
|
+
defaultMessage: value.defaultMessage
|
3235
|
+
},
|
3236
|
+
{ field: currentKey }
|
3237
|
+
)
|
3238
|
+
);
|
3239
|
+
} else {
|
3240
|
+
messages.push(
|
3241
|
+
...formatErrorMessages(
|
3242
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3243
|
+
value,
|
3244
|
+
currentKey,
|
3245
|
+
formatMessage
|
3246
|
+
)
|
2574
3247
|
);
|
2575
|
-
toggleNotification({
|
2576
|
-
message: formatMessage({
|
2577
|
-
id: "content-manager.actions.edit.error",
|
2578
|
-
defaultMessage: "An error occurred while trying to edit the document."
|
2579
|
-
}),
|
2580
|
-
type: "danger"
|
2581
|
-
});
|
2582
|
-
return;
|
2583
3248
|
}
|
2584
|
-
|
2585
|
-
|
2586
|
-
|
3249
|
+
} else {
|
3250
|
+
messages.push(
|
3251
|
+
formatMessage(
|
3252
|
+
{
|
3253
|
+
id: `${value}.withField`,
|
3254
|
+
defaultMessage: value
|
3255
|
+
},
|
3256
|
+
{ field: currentKey }
|
3257
|
+
)
|
3258
|
+
);
|
3259
|
+
}
|
3260
|
+
});
|
3261
|
+
return messages;
|
3262
|
+
};
|
3263
|
+
const EntryValidationText = ({ validationErrors, status }) => {
|
3264
|
+
const { formatMessage } = reactIntl.useIntl();
|
3265
|
+
if (validationErrors) {
|
3266
|
+
const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
|
3267
|
+
" "
|
3268
|
+
);
|
3269
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3270
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CrossCircle, { fill: "danger600" }),
|
3271
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
|
3272
|
+
] });
|
3273
|
+
}
|
3274
|
+
if (status === "published") {
|
3275
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3276
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
|
3277
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
|
3278
|
+
id: "content-manager.bulk-publish.already-published",
|
3279
|
+
defaultMessage: "Already Published"
|
3280
|
+
}) })
|
3281
|
+
] });
|
3282
|
+
}
|
3283
|
+
if (status === "modified") {
|
3284
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3285
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.ArrowsCounterClockwise, { fill: "alternative600" }),
|
3286
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3287
|
+
id: "content-manager.bulk-publish.modified",
|
3288
|
+
defaultMessage: "Ready to publish changes"
|
3289
|
+
}) })
|
3290
|
+
] });
|
3291
|
+
}
|
3292
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3293
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
|
3294
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3295
|
+
id: "app.utils.ready-to-publish",
|
3296
|
+
defaultMessage: "Ready to publish"
|
3297
|
+
}) })
|
3298
|
+
] });
|
3299
|
+
};
|
3300
|
+
const TABLE_HEADERS = [
|
3301
|
+
{ name: "id", label: "id" },
|
3302
|
+
{ name: "name", label: "name" },
|
3303
|
+
{ name: "status", label: "status" },
|
3304
|
+
{ name: "publicationStatus", label: "Publication status" }
|
3305
|
+
];
|
3306
|
+
const SelectedEntriesTableContent = ({
|
3307
|
+
isPublishing,
|
3308
|
+
rowsToDisplay = [],
|
3309
|
+
entriesToPublish = [],
|
3310
|
+
validationErrors = {}
|
3311
|
+
}) => {
|
3312
|
+
const { pathname } = reactRouterDom.useLocation();
|
3313
|
+
const { formatMessage } = reactIntl.useIntl();
|
3314
|
+
const {
|
3315
|
+
list: {
|
3316
|
+
settings: { mainField }
|
3317
|
+
}
|
3318
|
+
} = useDocLayout();
|
3319
|
+
const shouldDisplayMainField = mainField != null && mainField !== "id";
|
3320
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Content, { children: [
|
3321
|
+
/* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Head, { children: [
|
3322
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCheckboxCell, {}),
|
3323
|
+
TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
|
3324
|
+
(head) => /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCell, { ...head }, head.name)
|
3325
|
+
)
|
3326
|
+
] }),
|
3327
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Loading, {}),
|
3328
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
|
3329
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, { id: row.id }),
|
3330
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row.id }) }),
|
3331
|
+
shouldDisplayMainField && /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row[mainField] }) }),
|
3332
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
|
3333
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3334
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3335
|
+
id: "content-manager.success.record.publishing",
|
3336
|
+
defaultMessage: "Publishing..."
|
3337
|
+
}) }),
|
3338
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true })
|
3339
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
3340
|
+
EntryValidationText,
|
3341
|
+
{
|
3342
|
+
validationErrors: validationErrors[row.documentId],
|
3343
|
+
status: row.status
|
3344
|
+
}
|
3345
|
+
) }),
|
3346
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3347
|
+
designSystem.IconButton,
|
3348
|
+
{
|
3349
|
+
tag: reactRouterDom.Link,
|
3350
|
+
to: {
|
3351
|
+
pathname: `${pathname}/${row.documentId}`,
|
3352
|
+
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3353
|
+
},
|
3354
|
+
state: { from: pathname },
|
3355
|
+
label: formatMessage({
|
3356
|
+
id: "content-manager.bulk-publish.edit",
|
3357
|
+
defaultMessage: "Edit"
|
3358
|
+
}),
|
3359
|
+
target: "_blank",
|
3360
|
+
marginLeft: "auto",
|
3361
|
+
variant: "ghost",
|
3362
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3363
|
+
}
|
3364
|
+
) }) })
|
3365
|
+
] }, row.id)) })
|
3366
|
+
] });
|
3367
|
+
};
|
3368
|
+
const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
|
3369
|
+
const SelectedEntriesModalContent = ({
|
3370
|
+
listViewSelectedEntries,
|
3371
|
+
toggleModal,
|
3372
|
+
setListViewSelectedDocuments,
|
3373
|
+
model
|
3374
|
+
}) => {
|
3375
|
+
const { formatMessage } = reactIntl.useIntl();
|
3376
|
+
const { schema, components } = useContentTypeSchema(model);
|
3377
|
+
const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
|
3378
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3379
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3380
|
+
const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
|
3381
|
+
{
|
3382
|
+
model,
|
3383
|
+
params: {
|
3384
|
+
page: "1",
|
3385
|
+
pageSize: documentIds.length.toString(),
|
3386
|
+
sort: query.sort,
|
3387
|
+
filters: {
|
3388
|
+
documentId: {
|
3389
|
+
$in: documentIds
|
3390
|
+
}
|
3391
|
+
},
|
3392
|
+
locale: query.plugins?.i18n?.locale
|
3393
|
+
}
|
3394
|
+
},
|
3395
|
+
{
|
3396
|
+
selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
|
3397
|
+
}
|
3398
|
+
);
|
3399
|
+
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3400
|
+
if (data.length > 0 && schema) {
|
3401
|
+
const validate = createYupSchema(
|
3402
|
+
schema.attributes,
|
3403
|
+
components,
|
3404
|
+
// Since this is the "Publish" action, the validation
|
3405
|
+
// schema must enforce the rules for published entities
|
3406
|
+
{ status: "published" }
|
3407
|
+
);
|
3408
|
+
const validationErrors2 = {};
|
3409
|
+
const rows2 = data.map((entry) => {
|
3410
|
+
try {
|
3411
|
+
validate.validateSync(entry, { abortEarly: false });
|
3412
|
+
return entry;
|
3413
|
+
} catch (e) {
|
3414
|
+
if (e instanceof yup.ValidationError) {
|
3415
|
+
validationErrors2[entry.documentId] = strapiAdmin.getYupValidationErrors(e);
|
3416
|
+
}
|
3417
|
+
return entry;
|
3418
|
+
}
|
3419
|
+
});
|
3420
|
+
return { rows: rows2, validationErrors: validationErrors2 };
|
3421
|
+
}
|
3422
|
+
return {
|
3423
|
+
rows: [],
|
3424
|
+
validationErrors: {}
|
3425
|
+
};
|
3426
|
+
}, [components, data, schema]);
|
3427
|
+
const [publishedCount, setPublishedCount] = React__namespace.useState(0);
|
3428
|
+
const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
|
3429
|
+
const { publishMany: bulkPublishAction } = useDocumentActions();
|
3430
|
+
const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
|
3431
|
+
const selectedRows = strapiAdmin.useTable("publishAction", (state) => state.selectedRows);
|
3432
|
+
const selectedEntries = rows.filter(
|
3433
|
+
(entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
|
3434
|
+
);
|
3435
|
+
const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
|
3436
|
+
const selectedEntriesWithErrorsCount = selectedEntries.filter(
|
3437
|
+
({ documentId }) => validationErrors[documentId]
|
3438
|
+
).length;
|
3439
|
+
const selectedEntriesPublished = selectedEntries.filter(
|
3440
|
+
({ status }) => status === "published"
|
3441
|
+
).length;
|
3442
|
+
const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
|
3443
|
+
const toggleDialog = () => setIsDialogOpen((prev) => !prev);
|
3444
|
+
const handleConfirmBulkPublish = async () => {
|
3445
|
+
toggleDialog();
|
3446
|
+
const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
|
3447
|
+
if (!("error" in res)) {
|
3448
|
+
setPublishedCount(res.count);
|
3449
|
+
const unpublishedEntries = rows.filter((row) => {
|
3450
|
+
return !entriesToPublish.includes(row.documentId);
|
3451
|
+
});
|
3452
|
+
setListViewSelectedDocuments(unpublishedEntries);
|
3453
|
+
}
|
3454
|
+
};
|
3455
|
+
const getFormattedCountMessage = () => {
|
3456
|
+
if (publishedCount) {
|
3457
|
+
return formatMessage(
|
3458
|
+
{
|
3459
|
+
id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
|
3460
|
+
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."
|
3461
|
+
},
|
3462
|
+
{
|
3463
|
+
publishedCount,
|
3464
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3465
|
+
b: BoldChunk
|
3466
|
+
}
|
3467
|
+
);
|
3468
|
+
}
|
3469
|
+
return formatMessage(
|
3470
|
+
{
|
3471
|
+
id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
|
3472
|
+
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."
|
3473
|
+
},
|
3474
|
+
{
|
3475
|
+
readyToPublishCount: selectedEntriesWithNoErrorsCount,
|
3476
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3477
|
+
alreadyPublishedCount: selectedEntriesPublished,
|
3478
|
+
b: BoldChunk
|
3479
|
+
}
|
3480
|
+
);
|
3481
|
+
};
|
3482
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
3483
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
|
3484
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
|
3485
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3486
|
+
SelectedEntriesTableContent,
|
3487
|
+
{
|
3488
|
+
isPublishing: isSubmittingForm,
|
3489
|
+
rowsToDisplay: rows,
|
3490
|
+
entriesToPublish,
|
3491
|
+
validationErrors
|
3492
|
+
}
|
3493
|
+
) })
|
3494
|
+
] }),
|
3495
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3496
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
|
3497
|
+
id: "app.components.Button.cancel",
|
3498
|
+
defaultMessage: "Cancel"
|
3499
|
+
}) }),
|
3500
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3501
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
|
3502
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3503
|
+
designSystem.Button,
|
3504
|
+
{
|
3505
|
+
onClick: toggleDialog,
|
3506
|
+
disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
|
3507
|
+
loading: isSubmittingForm,
|
3508
|
+
children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
|
3509
|
+
}
|
3510
|
+
)
|
3511
|
+
] })
|
3512
|
+
] }),
|
3513
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3514
|
+
ConfirmDialogPublishAll,
|
3515
|
+
{
|
3516
|
+
isOpen: isDialogOpen,
|
3517
|
+
onToggleDialog: toggleDialog,
|
3518
|
+
isConfirmButtonLoading: isSubmittingForm,
|
3519
|
+
onConfirm: handleConfirmBulkPublish
|
3520
|
+
}
|
3521
|
+
)
|
3522
|
+
] });
|
3523
|
+
};
|
3524
|
+
const PublishAction = ({ documents, model }) => {
|
3525
|
+
const { formatMessage } = reactIntl.useIntl();
|
3526
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3527
|
+
const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
|
3528
|
+
const setListViewSelectedDocuments = strapiAdmin.useTable("publishAction", (state) => state.selectRow);
|
3529
|
+
const refetchList = () => {
|
3530
|
+
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3531
|
+
};
|
3532
|
+
if (!showPublishButton) return null;
|
3533
|
+
return {
|
3534
|
+
actionType: "publish",
|
3535
|
+
variant: "tertiary",
|
3536
|
+
label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
|
3537
|
+
dialog: {
|
3538
|
+
type: "modal",
|
3539
|
+
title: formatMessage({
|
3540
|
+
id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
|
3541
|
+
defaultMessage: "Publish entries"
|
3542
|
+
}),
|
3543
|
+
content: ({ onClose }) => {
|
3544
|
+
return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3545
|
+
SelectedEntriesModalContent,
|
3546
|
+
{
|
3547
|
+
listViewSelectedEntries: documents,
|
3548
|
+
toggleModal: () => {
|
3549
|
+
onClose();
|
3550
|
+
refetchList();
|
3551
|
+
},
|
3552
|
+
setListViewSelectedDocuments,
|
3553
|
+
model
|
3554
|
+
}
|
3555
|
+
) });
|
3556
|
+
},
|
3557
|
+
onClose: () => {
|
3558
|
+
refetchList();
|
3559
|
+
}
|
3560
|
+
}
|
3561
|
+
};
|
3562
|
+
};
|
3563
|
+
const BulkActionsRenderer = () => {
|
3564
|
+
const plugins = strapiAdmin.useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
|
3565
|
+
const { model, collectionType } = useDoc();
|
3566
|
+
const { selectedRows } = strapiAdmin.useTable("BulkActionsRenderer", (state) => state);
|
3567
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3568
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3569
|
+
{
|
3570
|
+
props: {
|
3571
|
+
model,
|
3572
|
+
collectionType,
|
3573
|
+
documents: selectedRows
|
3574
|
+
},
|
3575
|
+
descriptions: plugins["content-manager"].apis.getBulkActions(),
|
3576
|
+
children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...action }, action.id))
|
3577
|
+
}
|
3578
|
+
) });
|
3579
|
+
};
|
3580
|
+
const DeleteAction = ({ documents, model }) => {
|
3581
|
+
const { formatMessage } = reactIntl.useIntl();
|
3582
|
+
const { schema: contentType } = useDoc();
|
3583
|
+
const selectRow = strapiAdmin.useTable("DeleteAction", (state) => state.selectRow);
|
3584
|
+
const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
|
3585
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3586
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3587
|
+
const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
|
3588
|
+
const { deleteMany: bulkDeleteAction } = useDocumentActions();
|
3589
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3590
|
+
const handleConfirmBulkDelete = async () => {
|
3591
|
+
const res = await bulkDeleteAction({
|
3592
|
+
documentIds,
|
3593
|
+
model,
|
3594
|
+
params
|
3595
|
+
});
|
3596
|
+
if (!("error" in res)) {
|
3597
|
+
selectRow([]);
|
3598
|
+
}
|
3599
|
+
};
|
3600
|
+
if (!hasDeletePermission) return null;
|
3601
|
+
return {
|
3602
|
+
variant: "danger-light",
|
3603
|
+
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
3604
|
+
dialog: {
|
3605
|
+
type: "dialog",
|
3606
|
+
title: formatMessage({
|
3607
|
+
id: "app.components.ConfirmDialog.title",
|
3608
|
+
defaultMessage: "Confirmation"
|
3609
|
+
}),
|
3610
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3611
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3612
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3613
|
+
id: "popUpWarning.bodyMessage.contentType.delete.all",
|
3614
|
+
defaultMessage: "Are you sure you want to delete these entries?"
|
3615
|
+
}) }),
|
3616
|
+
hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
|
3617
|
+
{
|
3618
|
+
id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
|
3619
|
+
defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
|
3620
|
+
},
|
3621
|
+
{
|
3622
|
+
em: Emphasis
|
3623
|
+
}
|
3624
|
+
) }) })
|
3625
|
+
] }),
|
3626
|
+
onConfirm: handleConfirmBulkDelete
|
3627
|
+
}
|
3628
|
+
};
|
3629
|
+
};
|
3630
|
+
DeleteAction.type = "delete";
|
3631
|
+
const UnpublishAction = ({ documents, model }) => {
|
3632
|
+
const { formatMessage } = reactIntl.useIntl();
|
3633
|
+
const { schema } = useDoc();
|
3634
|
+
const selectRow = strapiAdmin.useTable("UnpublishAction", (state) => state.selectRow);
|
3635
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3636
|
+
const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
|
3637
|
+
const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
|
3638
|
+
const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
|
3639
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3640
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3641
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3642
|
+
const handleConfirmBulkUnpublish = async () => {
|
3643
|
+
const data = await bulkUnpublishAction({ documentIds, model, params });
|
3644
|
+
if (!("error" in data)) {
|
3645
|
+
selectRow([]);
|
3646
|
+
}
|
3647
|
+
};
|
3648
|
+
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3649
|
+
if (!showUnpublishButton) return null;
|
3650
|
+
return {
|
3651
|
+
variant: "tertiary",
|
3652
|
+
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
3653
|
+
dialog: {
|
3654
|
+
type: "dialog",
|
3655
|
+
title: formatMessage({
|
3656
|
+
id: "app.components.ConfirmDialog.title",
|
3657
|
+
defaultMessage: "Confirmation"
|
3658
|
+
}),
|
3659
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3660
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3661
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3662
|
+
id: "popUpWarning.bodyMessage.contentType.unpublish.all",
|
3663
|
+
defaultMessage: "Are you sure you want to unpublish these entries?"
|
3664
|
+
}) }),
|
3665
|
+
hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
|
3666
|
+
{
|
3667
|
+
id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
|
3668
|
+
defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
|
3669
|
+
},
|
3670
|
+
{
|
3671
|
+
em: Emphasis
|
3672
|
+
}
|
3673
|
+
) }) })
|
3674
|
+
] }),
|
3675
|
+
confirmButton: formatMessage({
|
3676
|
+
id: "app.utils.unpublish",
|
3677
|
+
defaultMessage: "Unpublish"
|
3678
|
+
}),
|
3679
|
+
onConfirm: handleConfirmBulkUnpublish
|
3680
|
+
}
|
3681
|
+
};
|
3682
|
+
};
|
3683
|
+
UnpublishAction.type = "unpublish";
|
3684
|
+
const Emphasis = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
|
3685
|
+
const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
|
3686
|
+
const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
3687
|
+
const { formatMessage } = reactIntl.useIntl();
|
3688
|
+
const getDefaultErrorMessage = (reason) => {
|
3689
|
+
switch (reason) {
|
3690
|
+
case "relation":
|
3691
|
+
return "Duplicating the relation could remove it from the original entry.";
|
3692
|
+
case "unique":
|
3693
|
+
return "Identical values in a unique field are not allowed";
|
3694
|
+
default:
|
3695
|
+
return reason;
|
3696
|
+
}
|
3697
|
+
};
|
3698
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
3699
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: formatMessage({
|
3700
|
+
id: getTranslation("containers.list.autoCloneModal.title"),
|
3701
|
+
defaultMessage: "This entry can't be duplicated directly."
|
3702
|
+
}) }),
|
3703
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatMessage({
|
3704
|
+
id: getTranslation("containers.list.autoCloneModal.description"),
|
3705
|
+
defaultMessage: "A new entry will be created with the same content, but you'll have to change the following fields to save it."
|
3706
|
+
}) }) }),
|
3707
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { marginTop: 6, gap: 2, direction: "column", alignItems: "stretch", children: prohibitedFields.map(([fieldPath, reason]) => /* @__PURE__ */ jsxRuntime.jsxs(
|
3708
|
+
designSystem.Flex,
|
3709
|
+
{
|
3710
|
+
direction: "column",
|
3711
|
+
gap: 2,
|
3712
|
+
alignItems: "flex-start",
|
3713
|
+
borderColor: "neutral200",
|
3714
|
+
hasRadius: true,
|
3715
|
+
padding: 6,
|
3716
|
+
children: [
|
3717
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", tag: "li", children: [
|
3718
|
+
pathSegment,
|
3719
|
+
index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
3720
|
+
Icons.ChevronRight,
|
3721
|
+
{
|
3722
|
+
fill: "neutral500",
|
3723
|
+
height: "0.8rem",
|
3724
|
+
width: "0.8rem",
|
3725
|
+
style: { margin: "0 0.8rem" }
|
3726
|
+
}
|
3727
|
+
)
|
3728
|
+
] }, index2)) }),
|
3729
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
|
3730
|
+
id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
|
3731
|
+
defaultMessage: getDefaultErrorMessage(reason)
|
3732
|
+
}) })
|
3733
|
+
]
|
3734
|
+
},
|
3735
|
+
fieldPath.join()
|
3736
|
+
)) })
|
3737
|
+
] });
|
3738
|
+
};
|
3739
|
+
const TableActions = ({ document }) => {
|
3740
|
+
const { formatMessage } = reactIntl.useIntl();
|
3741
|
+
const { model, collectionType } = useDoc();
|
3742
|
+
const plugins = strapiAdmin.useStrapiApp("TableActions", (state) => state.plugins);
|
3743
|
+
const props = {
|
3744
|
+
activeTab: null,
|
3745
|
+
model,
|
3746
|
+
documentId: document.documentId,
|
3747
|
+
collectionType,
|
3748
|
+
document
|
3749
|
+
};
|
3750
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
3751
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3752
|
+
{
|
3753
|
+
props,
|
3754
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
|
3755
|
+
children: (actions2) => {
|
3756
|
+
const tableRowActions = actions2.filter((action) => {
|
3757
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
3758
|
+
return positions.includes("table-row");
|
3759
|
+
});
|
3760
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
3761
|
+
DocumentActionsMenu,
|
3762
|
+
{
|
3763
|
+
actions: tableRowActions,
|
3764
|
+
label: formatMessage({
|
3765
|
+
id: "content-manager.containers.list.table.row-actions",
|
3766
|
+
defaultMessage: "Row action"
|
3767
|
+
}),
|
3768
|
+
variant: "ghost"
|
3769
|
+
}
|
3770
|
+
);
|
3771
|
+
}
|
3772
|
+
}
|
3773
|
+
);
|
3774
|
+
};
|
3775
|
+
const EditAction = ({ documentId }) => {
|
3776
|
+
const navigate = reactRouterDom.useNavigate();
|
3777
|
+
const { formatMessage } = reactIntl.useIntl();
|
3778
|
+
const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
|
3779
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
3780
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3781
|
+
return {
|
3782
|
+
disabled: !canRead,
|
3783
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil, {}),
|
3784
|
+
label: formatMessage({
|
3785
|
+
id: "content-manager.actions.edit.label",
|
3786
|
+
defaultMessage: "Edit"
|
3787
|
+
}),
|
3788
|
+
position: "table-row",
|
3789
|
+
onClick: async () => {
|
3790
|
+
if (!documentId) {
|
3791
|
+
console.error(
|
3792
|
+
"You're trying to edit a document without an id, this is likely a bug with Strapi. Please open an issue."
|
3793
|
+
);
|
3794
|
+
toggleNotification({
|
3795
|
+
message: formatMessage({
|
3796
|
+
id: "content-manager.actions.edit.error",
|
3797
|
+
defaultMessage: "An error occurred while trying to edit the document."
|
3798
|
+
}),
|
3799
|
+
type: "danger"
|
3800
|
+
});
|
3801
|
+
return;
|
3802
|
+
}
|
3803
|
+
navigate({
|
3804
|
+
pathname: documentId,
|
3805
|
+
search: qs.stringify({
|
2587
3806
|
plugins: query.plugins
|
2588
3807
|
})
|
2589
3808
|
});
|
@@ -2591,7 +3810,8 @@ const EditAction = ({ documentId }) => {
|
|
2591
3810
|
};
|
2592
3811
|
};
|
2593
3812
|
EditAction.type = "edit";
|
2594
|
-
|
3813
|
+
EditAction.position = "table-row";
|
3814
|
+
const StyledPencil = styledComponents.styled(Icons.Pencil)`
|
2595
3815
|
path {
|
2596
3816
|
fill: currentColor;
|
2597
3817
|
}
|
@@ -2643,7 +3863,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
2643
3863
|
}),
|
2644
3864
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
2645
3865
|
footer: ({ onClose }) => {
|
2646
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3866
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
2647
3867
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
2648
3868
|
id: "cancel",
|
2649
3869
|
defaultMessage: "Cancel"
|
@@ -2651,7 +3871,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
2651
3871
|
/* @__PURE__ */ jsxRuntime.jsx(
|
2652
3872
|
designSystem.LinkButton,
|
2653
3873
|
{
|
2654
|
-
|
3874
|
+
tag: reactRouterDom.NavLink,
|
2655
3875
|
to: {
|
2656
3876
|
pathname: `clone/${documentId}`
|
2657
3877
|
},
|
@@ -2667,7 +3887,8 @@ const CloneAction = ({ model, documentId }) => {
|
|
2667
3887
|
};
|
2668
3888
|
};
|
2669
3889
|
CloneAction.type = "clone";
|
2670
|
-
|
3890
|
+
CloneAction.position = "table-row";
|
3891
|
+
const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
|
2671
3892
|
path {
|
2672
3893
|
fill: currentColor;
|
2673
3894
|
}
|
@@ -2684,8 +3905,7 @@ class ContentManagerPlugin {
|
|
2684
3905
|
documentActions = [
|
2685
3906
|
...DEFAULT_ACTIONS,
|
2686
3907
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
2687
|
-
...DEFAULT_HEADER_ACTIONS
|
2688
|
-
HistoryAction
|
3908
|
+
...DEFAULT_HEADER_ACTIONS
|
2689
3909
|
];
|
2690
3910
|
editViewSidePanels = [ActionsPanel];
|
2691
3911
|
headerActions = [];
|
@@ -2754,7 +3974,14 @@ class ContentManagerPlugin {
|
|
2754
3974
|
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
2755
3975
|
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
2756
3976
|
getBulkActions: () => this.bulkActions,
|
2757
|
-
getDocumentActions: () =>
|
3977
|
+
getDocumentActions: (position) => {
|
3978
|
+
if (position) {
|
3979
|
+
return this.documentActions.filter(
|
3980
|
+
(action) => action.position == void 0 || [action.position].flat().includes(position)
|
3981
|
+
);
|
3982
|
+
}
|
3983
|
+
return this.documentActions;
|
3984
|
+
},
|
2758
3985
|
getEditViewSidePanels: () => this.editViewSidePanels,
|
2759
3986
|
getHeaderActions: () => this.headerActions
|
2760
3987
|
}
|
@@ -2764,16 +3991,71 @@ class ContentManagerPlugin {
|
|
2764
3991
|
const getPrintableType = (value) => {
|
2765
3992
|
const nativeType = typeof value;
|
2766
3993
|
if (nativeType === "object") {
|
2767
|
-
if (value === null)
|
2768
|
-
|
2769
|
-
if (Array.isArray(value))
|
2770
|
-
return "array";
|
3994
|
+
if (value === null) return "null";
|
3995
|
+
if (Array.isArray(value)) return "array";
|
2771
3996
|
if (value instanceof Object && value.constructor.name !== "Object") {
|
2772
3997
|
return value.constructor.name;
|
2773
3998
|
}
|
2774
3999
|
}
|
2775
4000
|
return nativeType;
|
2776
4001
|
};
|
4002
|
+
const HistoryAction = ({ model, document }) => {
|
4003
|
+
const { formatMessage } = reactIntl.useIntl();
|
4004
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
4005
|
+
const navigate = reactRouterDom.useNavigate();
|
4006
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
4007
|
+
const { pathname } = reactRouterDom.useLocation();
|
4008
|
+
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
4009
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
4010
|
+
return null;
|
4011
|
+
}
|
4012
|
+
const handleOnClick = () => {
|
4013
|
+
const destination = { pathname: "history", search: pluginsQueryParams };
|
4014
|
+
trackUsage("willNavigate", {
|
4015
|
+
from: pathname,
|
4016
|
+
to: `${pathname}/${destination.pathname}`
|
4017
|
+
});
|
4018
|
+
navigate(destination);
|
4019
|
+
};
|
4020
|
+
return {
|
4021
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
4022
|
+
label: formatMessage({
|
4023
|
+
id: "content-manager.history.document-action",
|
4024
|
+
defaultMessage: "Content History"
|
4025
|
+
}),
|
4026
|
+
onClick: handleOnClick,
|
4027
|
+
disabled: (
|
4028
|
+
/**
|
4029
|
+
* The user is creating a new document.
|
4030
|
+
* It hasn't been saved yet, so there's no history to go to
|
4031
|
+
*/
|
4032
|
+
!document || /**
|
4033
|
+
* The document has been created but the current dimension has never been saved.
|
4034
|
+
* For example, the user is creating a new locale in an existing document,
|
4035
|
+
* so there's no history for the document in that locale
|
4036
|
+
*/
|
4037
|
+
!document.id || /**
|
4038
|
+
* History is only available for content types created by the user.
|
4039
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
4040
|
+
* which start with `admin::` or `plugin::`
|
4041
|
+
*/
|
4042
|
+
!model.startsWith("api::")
|
4043
|
+
),
|
4044
|
+
position: "header"
|
4045
|
+
};
|
4046
|
+
};
|
4047
|
+
HistoryAction.type = "history";
|
4048
|
+
HistoryAction.position = "header";
|
4049
|
+
const historyAdmin = {
|
4050
|
+
bootstrap(app) {
|
4051
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
4052
|
+
addDocumentAction((actions2) => {
|
4053
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
4054
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
4055
|
+
return actions2;
|
4056
|
+
});
|
4057
|
+
}
|
4058
|
+
};
|
2777
4059
|
const initialState = {
|
2778
4060
|
collectionTypeLinks: [],
|
2779
4061
|
components: [],
|
@@ -2810,316 +4092,94 @@ const { setInitialData } = actions;
|
|
2810
4092
|
const reducer = toolkit.combineReducers({
|
2811
4093
|
app: reducer$1
|
2812
4094
|
});
|
2813
|
-
const
|
2814
|
-
|
2815
|
-
|
2816
|
-
|
2817
|
-
|
2818
|
-
|
2819
|
-
|
2820
|
-
|
2821
|
-
|
2822
|
-
|
2823
|
-
|
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({
|
2840
|
-
endpoints: (builder) => ({
|
2841
|
-
getContentTypeConfiguration: builder.query({
|
2842
|
-
query: (uid) => ({
|
2843
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2844
|
-
method: "GET"
|
2845
|
-
}),
|
2846
|
-
transformResponse: (response) => response.data,
|
2847
|
-
providesTags: (_result, _error, uid) => [
|
2848
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2849
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
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
|
-
]
|
4095
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4096
|
+
endpoints: (builder) => ({
|
4097
|
+
getPreviewUrl: builder.query({
|
4098
|
+
query({ query, params }) {
|
4099
|
+
return {
|
4100
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4101
|
+
method: "GET",
|
4102
|
+
config: {
|
4103
|
+
params: query
|
4104
|
+
}
|
4105
|
+
};
|
4106
|
+
}
|
2870
4107
|
})
|
2871
4108
|
})
|
2872
4109
|
});
|
2873
|
-
const {
|
2874
|
-
|
2875
|
-
|
2876
|
-
|
2877
|
-
} = contentTypesApi;
|
2878
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2879
|
-
const { type } = attribute;
|
2880
|
-
if (type === "relation") {
|
2881
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
4110
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4111
|
+
const ConditionalTooltip = ({ isShown, label, children }) => {
|
4112
|
+
if (isShown) {
|
4113
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { label, children });
|
2882
4114
|
}
|
2883
|
-
return
|
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
|
4115
|
+
return children;
|
2907
4116
|
};
|
2908
|
-
const
|
2909
|
-
const {
|
4117
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4118
|
+
const { formatMessage } = reactIntl.useIntl();
|
4119
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
4120
|
+
const { pathname } = reactRouterDom.useLocation();
|
2910
4121
|
const [{ query }] = strapiAdmin.useQueryParams();
|
2911
|
-
const
|
2912
|
-
const {
|
2913
|
-
|
2914
|
-
|
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
|
2937
|
-
},
|
2938
|
-
[data, isLoading, schemas, schema, components]
|
2939
|
-
);
|
2940
|
-
const listLayout = React__namespace.useMemo(() => {
|
2941
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
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
|
-
};
|
4122
|
+
const isModified = strapiAdmin.useForm("PreviewSidePanel", (state) => state.modified);
|
4123
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4124
|
+
params: {
|
4125
|
+
contentType: model
|
3014
4126
|
},
|
3015
|
-
{
|
3016
|
-
|
3017
|
-
|
3018
|
-
|
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
|
4127
|
+
query: {
|
4128
|
+
documentId,
|
4129
|
+
locale: document?.locale,
|
4130
|
+
status: document?.status
|
3029
4131
|
}
|
4132
|
+
});
|
4133
|
+
if (!data?.data?.url || error) {
|
4134
|
+
return null;
|
4135
|
+
}
|
4136
|
+
const trackNavigation = () => {
|
4137
|
+
const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
|
4138
|
+
trackUsage("willNavigate", { from: pathname, to: destinationPathname });
|
3030
4139
|
};
|
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
4140
|
return {
|
3084
|
-
|
3085
|
-
|
3086
|
-
|
3087
|
-
|
3088
|
-
|
3089
|
-
|
3090
|
-
|
3091
|
-
|
4141
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4142
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(
|
4143
|
+
ConditionalTooltip,
|
4144
|
+
{
|
4145
|
+
label: formatMessage({
|
4146
|
+
id: "content-manager.preview.panel.button-disabled-tooltip",
|
4147
|
+
defaultMessage: "Please save to open the preview"
|
4148
|
+
}),
|
4149
|
+
isShown: isModified,
|
4150
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { cursor: "not-allowed", width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
|
4151
|
+
designSystem.Button,
|
4152
|
+
{
|
4153
|
+
variant: "tertiary",
|
4154
|
+
tag: reactRouterDom.Link,
|
4155
|
+
to: { pathname: "preview", search: qs.stringify(query, { encode: false }) },
|
4156
|
+
onClick: trackNavigation,
|
4157
|
+
width: "100%",
|
4158
|
+
disabled: isModified,
|
4159
|
+
pointerEvents: isModified ? "none" : void 0,
|
4160
|
+
tabIndex: isModified ? -1 : void 0,
|
4161
|
+
children: formatMessage({
|
4162
|
+
id: "content-manager.preview.panel.button",
|
4163
|
+
defaultMessage: "Open preview"
|
4164
|
+
})
|
4165
|
+
}
|
4166
|
+
) })
|
4167
|
+
}
|
4168
|
+
)
|
3092
4169
|
};
|
3093
4170
|
};
|
3094
|
-
const
|
3095
|
-
|
3096
|
-
const
|
3097
|
-
|
3098
|
-
|
3099
|
-
}
|
3100
|
-
const metadata = metadatas[name];
|
3101
|
-
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
3102
|
-
return {
|
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);
|
4171
|
+
const previewAdmin = {
|
4172
|
+
bootstrap(app) {
|
4173
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4174
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4175
|
+
}
|
3114
4176
|
};
|
3115
4177
|
const index = {
|
3116
4178
|
register(app) {
|
3117
4179
|
const cm = new ContentManagerPlugin();
|
3118
4180
|
app.addReducers({
|
3119
|
-
[contentManagerApi.reducerPath]: contentManagerApi.reducer,
|
3120
4181
|
[PLUGIN_ID]: reducer
|
3121
4182
|
});
|
3122
|
-
app.addMiddlewares([() => contentManagerApi.middleware]);
|
3123
4183
|
app.addMenuLink({
|
3124
4184
|
to: PLUGIN_ID,
|
3125
4185
|
icon: Icons.Feather,
|
@@ -3128,14 +4188,32 @@ const index = {
|
|
3128
4188
|
defaultMessage: "Content Manager"
|
3129
4189
|
},
|
3130
4190
|
permissions: [],
|
3131
|
-
|
4191
|
+
position: 1
|
4192
|
+
});
|
4193
|
+
app.router.addRoute({
|
4194
|
+
path: "content-manager/*",
|
4195
|
+
lazy: async () => {
|
4196
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-ivwIVPnV.js"));
|
4197
|
+
return {
|
4198
|
+
Component: Layout
|
4199
|
+
};
|
4200
|
+
},
|
4201
|
+
children: routes
|
3132
4202
|
});
|
3133
4203
|
app.registerPlugin(cm.config);
|
3134
4204
|
},
|
4205
|
+
bootstrap(app) {
|
4206
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4207
|
+
historyAdmin.bootstrap(app);
|
4208
|
+
}
|
4209
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4210
|
+
previewAdmin.bootstrap(app);
|
4211
|
+
}
|
4212
|
+
},
|
3135
4213
|
async registerTrads({ locales }) {
|
3136
4214
|
const importedTrads = await Promise.all(
|
3137
4215
|
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-
|
4216
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-BK8Xyl5I.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-9K52xZIr.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B2Kyv8Z9.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-7sfIbjxE.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`, 3).then(({ default: data }) => {
|
3139
4217
|
return {
|
3140
4218
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3141
4219
|
locale
|
@@ -3152,6 +4230,8 @@ const index = {
|
|
3152
4230
|
}
|
3153
4231
|
};
|
3154
4232
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
4233
|
+
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4234
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3155
4235
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3156
4236
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3157
4237
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3178,8 +4258,8 @@ exports.getDisplayName = getDisplayName;
|
|
3178
4258
|
exports.getMainField = getMainField;
|
3179
4259
|
exports.getTranslation = getTranslation;
|
3180
4260
|
exports.index = index;
|
3181
|
-
exports.routes = routes;
|
3182
4261
|
exports.setInitialData = setInitialData;
|
4262
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3183
4263
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3184
4264
|
exports.useDoc = useDoc;
|
3185
4265
|
exports.useDocLayout = useDocLayout;
|
@@ -3191,5 +4271,6 @@ exports.useGetAllContentTypeSettingsQuery = useGetAllContentTypeSettingsQuery;
|
|
3191
4271
|
exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
3192
4272
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3193
4273
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
4274
|
+
exports.useGetPreviewUrlQuery = useGetPreviewUrlQuery;
|
3194
4275
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3195
|
-
//# sourceMappingURL=index-
|
4276
|
+
//# sourceMappingURL=index-Cnw4gqee.js.map
|