@strapi/content-manager 0.0.0-experimental.81dfdf02b1367004c7deed9e01afa9d3a15d0fa5 → 0.0.0-experimental.8f5736f39974781dca58cef1d1dea9d54580fbf1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{ComponentConfigurationPage-qemkOlnj.mjs → ComponentConfigurationPage-DfFSZQxe.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-qemkOlnj.mjs.map → ComponentConfigurationPage-DfFSZQxe.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-D_M8iBw5.js → ComponentConfigurationPage-FqfsxQ1j.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-D_M8iBw5.js.map → ComponentConfigurationPage-FqfsxQ1j.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-BePwPuHy.js → EditConfigurationPage-Cn0e8t3I.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-BePwPuHy.js.map → EditConfigurationPage-Cn0e8t3I.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CjUrEewK.mjs → EditConfigurationPage-DdPNAbl3.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CjUrEewK.mjs.map → EditConfigurationPage-DdPNAbl3.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-De8GyU8P.mjs → EditViewPage-B82x_x1b.mjs} +15 -5
- package/dist/_chunks/EditViewPage-B82x_x1b.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-B-RJeiJD.js → EditViewPage-DlxEHhUt.js} +15 -5
- package/dist/_chunks/EditViewPage-DlxEHhUt.js.map +1 -0
- package/dist/_chunks/{Field-dq8Tg1M_.js → Field-COL25JiC.js} +90 -84
- package/dist/_chunks/Field-COL25JiC.js.map +1 -0
- package/dist/_chunks/{Field-pb2o8uBe.mjs → Field-DufHXW17.mjs} +86 -80
- package/dist/_chunks/Field-DufHXW17.mjs.map +1 -0
- package/dist/_chunks/{Form-DGIf4jQU.js → Form-BssUwrTO.js} +16 -8
- package/dist/_chunks/Form-BssUwrTO.js.map +1 -0
- package/dist/_chunks/{Form-DJn0Dxha.mjs → Form-u_kAOhwB.mjs} +16 -8
- package/dist/_chunks/Form-u_kAOhwB.mjs.map +1 -0
- package/dist/_chunks/{History-Dh2NEHnR.js → History-C9t9UqpO.js} +23 -10
- package/dist/_chunks/History-C9t9UqpO.js.map +1 -0
- package/dist/_chunks/{History-BowL3JKP.mjs → History-DRwA3oMM.mjs} +24 -11
- package/dist/_chunks/History-DRwA3oMM.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-BxYCWz9e.js → ListConfigurationPage-BXYPohh-.js} +2 -2
- package/dist/_chunks/{ListConfigurationPage-BxYCWz9e.js.map → ListConfigurationPage-BXYPohh-.js.map} +1 -1
- package/dist/_chunks/{ListConfigurationPage-BpVOB-hn.mjs → ListConfigurationPage-BxfQJzPk.mjs} +2 -2
- package/dist/_chunks/{ListConfigurationPage-BpVOB-hn.mjs.map → ListConfigurationPage-BxfQJzPk.mjs.map} +1 -1
- package/dist/_chunks/{ListViewPage-CXFUjZQC.mjs → ListViewPage-CELx2ysp.mjs} +40 -36
- package/dist/_chunks/ListViewPage-CELx2ysp.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-4XsciqHZ.js → ListViewPage-D2VD8Szg.js} +43 -39
- package/dist/_chunks/ListViewPage-D2VD8Szg.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-C8OpoHeU.js → NoContentTypePage-BV9IjJSM.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-C8OpoHeU.js.map → NoContentTypePage-BV9IjJSM.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-DuhOTp3x.mjs → NoContentTypePage-DtJ9jcfk.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-DuhOTp3x.mjs.map → NoContentTypePage-DtJ9jcfk.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DVz3mzDz.mjs → NoPermissionsPage-DWleVYK7.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DVz3mzDz.mjs.map → NoPermissionsPage-DWleVYK7.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-y_r7DVA2.js → NoPermissionsPage-Dp8NpF9I.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-y_r7DVA2.js.map → NoPermissionsPage-Dp8NpF9I.js.map} +1 -1
- package/dist/_chunks/{Relations-CVNLrn1Y.mjs → Relations-BTcf5xaw.mjs} +32 -23
- package/dist/_chunks/Relations-BTcf5xaw.mjs.map +1 -0
- package/dist/_chunks/{Relations-DPFCAa7b.js → Relations-DR7EUgyC.js} +32 -23
- package/dist/_chunks/Relations-DR7EUgyC.js.map +1 -0
- package/dist/_chunks/{en-uOUIxfcQ.js → en-Bm0D0IWz.js} +13 -12
- package/dist/_chunks/{en-uOUIxfcQ.js.map → en-Bm0D0IWz.js.map} +1 -1
- package/dist/_chunks/{en-BrCTWlZv.mjs → en-DKV44jRb.mjs} +13 -12
- package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-DKV44jRb.mjs.map} +1 -1
- package/dist/_chunks/{index-C3fJE-1-.js → index-BdMf2lfT.js} +1877 -1767
- package/dist/_chunks/index-BdMf2lfT.js.map +1 -0
- package/dist/_chunks/{index-DiMrfcfy.mjs → index-wnqzm4Q8.mjs} +1881 -1771
- package/dist/_chunks/index-wnqzm4Q8.mjs.map +1 -0
- package/dist/_chunks/{layout-ls3gxfpH.mjs → layout-2CfjL0T9.mjs} +5 -4
- package/dist/_chunks/{layout-ls3gxfpH.mjs.map → layout-2CfjL0T9.mjs.map} +1 -1
- package/dist/_chunks/{layout-C788OmNr.js → layout-B2MyZU-_.js} +5 -4
- package/dist/_chunks/{layout-C788OmNr.js.map → layout-B2MyZU-_.js.map} +1 -1
- package/dist/_chunks/{relations-DYeotliT.js → relations-BH7JJGGe.js} +2 -2
- package/dist/_chunks/{relations-DYeotliT.js.map → relations-BH7JJGGe.js.map} +1 -1
- package/dist/_chunks/{relations-CLcOmGO0.mjs → relations-C0w0GcXi.mjs} +2 -2
- package/dist/_chunks/{relations-CLcOmGO0.mjs.map → relations-C0w0GcXi.mjs.map} +1 -1
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +3 -2
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +0 -32
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/services/documents.d.ts +3 -1
- package/dist/server/index.js +48 -21
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +48 -21
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +1 -0
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/package.json +12 -12
- package/dist/_chunks/EditViewPage-B-RJeiJD.js.map +0 -1
- package/dist/_chunks/EditViewPage-De8GyU8P.mjs.map +0 -1
- package/dist/_chunks/Field-dq8Tg1M_.js.map +0 -1
- package/dist/_chunks/Field-pb2o8uBe.mjs.map +0 -1
- package/dist/_chunks/Form-DGIf4jQU.js.map +0 -1
- package/dist/_chunks/Form-DJn0Dxha.mjs.map +0 -1
- package/dist/_chunks/History-BowL3JKP.mjs.map +0 -1
- package/dist/_chunks/History-Dh2NEHnR.js.map +0 -1
- package/dist/_chunks/ListViewPage-4XsciqHZ.js.map +0 -1
- package/dist/_chunks/ListViewPage-CXFUjZQC.mjs.map +0 -1
- package/dist/_chunks/Relations-CVNLrn1Y.mjs.map +0 -1
- package/dist/_chunks/Relations-DPFCAa7b.js.map +0 -1
- package/dist/_chunks/index-C3fJE-1-.js.map +0 -1
- package/dist/_chunks/index-DiMrfcfy.mjs.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
@@ -1,16 +1,16 @@
|
|
1
|
-
import {
|
1
|
+
import { More, Cross, WarningCircle, ListPlus, Pencil, Trash, Check, CrossCircle, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, ClockCounterClockwise, Feather } from "@strapi/icons";
|
2
2
|
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
3
|
-
import { useStrapiApp, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors,
|
3
|
+
import { useStrapiApp, createContext, useQueryParams, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useForm, useTracking, useGuidedTour, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
|
4
4
|
import * as React from "react";
|
5
5
|
import { lazy } from "react";
|
6
|
-
import {
|
6
|
+
import { Button, Menu, VisuallyHidden, Flex, Typography, Dialog, Modal, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
|
7
7
|
import { useIntl } from "react-intl";
|
8
8
|
import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
|
9
|
-
import { styled } from "styled-components";
|
10
9
|
import * as yup from "yup";
|
11
10
|
import { ValidationError } from "yup";
|
12
11
|
import pipe from "lodash/fp/pipe";
|
13
12
|
import { intervalToDuration, isPast } from "date-fns";
|
13
|
+
import { styled } from "styled-components";
|
14
14
|
import { stringify } from "qs";
|
15
15
|
import { createSlice, combineReducers } from "@reduxjs/toolkit";
|
16
16
|
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
@@ -100,6 +100,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
100
100
|
if (!slug) {
|
101
101
|
throw new Error("Cannot find the slug param in the URL");
|
102
102
|
}
|
103
|
+
const [{ rawQuery }] = useQueryParams();
|
103
104
|
const userPermissions = useAuth("DocumentRBAC", (state) => state.permissions);
|
104
105
|
const contentTypePermissions = React.useMemo(() => {
|
105
106
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -110,7 +111,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
110
111
|
return { ...acc, [action]: [permission] };
|
111
112
|
}, {});
|
112
113
|
}, [slug, userPermissions]);
|
113
|
-
const { isLoading, allowedActions } = useRBAC(
|
114
|
+
const { isLoading, allowedActions } = useRBAC(
|
115
|
+
contentTypePermissions,
|
116
|
+
permissions ?? void 0,
|
117
|
+
// TODO: useRBAC context should be typed and built differently
|
118
|
+
// We are passing raw query as context to the hook so that it can
|
119
|
+
// rely on the locale provided from DocumentRBAC for its permission calculations.
|
120
|
+
rawQuery
|
121
|
+
);
|
114
122
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
115
123
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
116
124
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -461,6 +469,24 @@ const buildValidParams = (query) => {
|
|
461
469
|
const isBaseQueryError = (error) => {
|
462
470
|
return error.name !== void 0;
|
463
471
|
};
|
472
|
+
const arrayValidator = (attribute, options) => ({
|
473
|
+
message: translatedErrors.required,
|
474
|
+
test(value) {
|
475
|
+
if (options.status === "draft") {
|
476
|
+
return true;
|
477
|
+
}
|
478
|
+
if (!attribute.required) {
|
479
|
+
return true;
|
480
|
+
}
|
481
|
+
if (!value) {
|
482
|
+
return false;
|
483
|
+
}
|
484
|
+
if (Array.isArray(value) && value.length === 0) {
|
485
|
+
return false;
|
486
|
+
}
|
487
|
+
return true;
|
488
|
+
}
|
489
|
+
});
|
464
490
|
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
465
491
|
const createModelSchema = (attributes2) => yup.object().shape(
|
466
492
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
@@ -468,6 +494,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
468
494
|
return acc;
|
469
495
|
}
|
470
496
|
const validations = [
|
497
|
+
addNullableValidation,
|
471
498
|
addRequiredValidation,
|
472
499
|
addMinLengthValidation,
|
473
500
|
addMaxLengthValidation,
|
@@ -484,12 +511,12 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
484
511
|
...acc,
|
485
512
|
[name]: transformSchema(
|
486
513
|
yup.array().of(createModelSchema(attributes3).nullable(false))
|
487
|
-
)
|
514
|
+
).test(arrayValidator(attribute, options))
|
488
515
|
};
|
489
516
|
} else {
|
490
517
|
return {
|
491
518
|
...acc,
|
492
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
519
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
493
520
|
};
|
494
521
|
}
|
495
522
|
}
|
@@ -511,7 +538,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
511
538
|
}
|
512
539
|
)
|
513
540
|
)
|
514
|
-
)
|
541
|
+
).test(arrayValidator(attribute, options))
|
515
542
|
};
|
516
543
|
case "relation":
|
517
544
|
return {
|
@@ -523,7 +550,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
523
550
|
} else if (Array.isArray(value)) {
|
524
551
|
return yup.array().of(
|
525
552
|
yup.object().shape({
|
526
|
-
id: yup.
|
553
|
+
id: yup.number().required()
|
527
554
|
})
|
528
555
|
);
|
529
556
|
} else if (typeof value === "object") {
|
@@ -609,17 +636,17 @@ const nullableSchema = (schema) => {
|
|
609
636
|
schema
|
610
637
|
);
|
611
638
|
};
|
639
|
+
const addNullableValidation = () => (schema) => {
|
640
|
+
return nullableSchema(schema);
|
641
|
+
};
|
612
642
|
const addRequiredValidation = (attribute, options) => (schema) => {
|
613
|
-
if (options.status === "draft") {
|
614
|
-
return
|
615
|
-
}
|
616
|
-
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
617
|
-
return schema.min(1, translatedErrors.required);
|
643
|
+
if (options.status === "draft" || !attribute.required) {
|
644
|
+
return schema;
|
618
645
|
}
|
619
|
-
if (attribute.required &&
|
646
|
+
if (attribute.required && "required" in schema) {
|
620
647
|
return schema.required(translatedErrors.required);
|
621
648
|
}
|
622
|
-
return
|
649
|
+
return schema;
|
623
650
|
};
|
624
651
|
const addMinLengthValidation = (attribute, options) => (schema) => {
|
625
652
|
if (options.status === "draft") {
|
@@ -647,31 +674,12 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
647
674
|
return schema;
|
648
675
|
};
|
649
676
|
const addMinValidation = (attribute, options) => (schema) => {
|
650
|
-
if ("
|
677
|
+
if (options.status === "draft") {
|
678
|
+
return schema;
|
679
|
+
}
|
680
|
+
if ("min" in attribute && "min" in schema) {
|
651
681
|
const min = toInteger(attribute.min);
|
652
|
-
if (
|
653
|
-
if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
|
654
|
-
return schema.test(
|
655
|
-
"custom-min",
|
656
|
-
{
|
657
|
-
...translatedErrors.min,
|
658
|
-
values: {
|
659
|
-
min: attribute.min
|
660
|
-
}
|
661
|
-
},
|
662
|
-
(value) => {
|
663
|
-
if (!value) {
|
664
|
-
return true;
|
665
|
-
}
|
666
|
-
if (Array.isArray(value) && value.length === 0) {
|
667
|
-
return true;
|
668
|
-
}
|
669
|
-
return value.length >= min;
|
670
|
-
}
|
671
|
-
);
|
672
|
-
}
|
673
|
-
}
|
674
|
-
if ("min" in schema && min) {
|
682
|
+
if (min) {
|
675
683
|
return schema.min(min, {
|
676
684
|
...translatedErrors.min,
|
677
685
|
values: {
|
@@ -789,19 +797,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
789
797
|
}, {});
|
790
798
|
return componentsByKey;
|
791
799
|
};
|
792
|
-
const
|
800
|
+
const HOOKS = {
|
801
|
+
/**
|
802
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
803
|
+
* @constant
|
804
|
+
* @type {string}
|
805
|
+
*/
|
806
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
807
|
+
/**
|
808
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
809
|
+
* @constant
|
810
|
+
* @type {string}
|
811
|
+
*/
|
812
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
813
|
+
/**
|
814
|
+
* Hook that allows to mutate the CM's edit view layout
|
815
|
+
* @constant
|
816
|
+
* @type {string}
|
817
|
+
*/
|
818
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
819
|
+
/**
|
820
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
821
|
+
* @constant
|
822
|
+
* @type {string}
|
823
|
+
*/
|
824
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
825
|
+
};
|
826
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
827
|
+
endpoints: (builder) => ({
|
828
|
+
getContentTypeConfiguration: builder.query({
|
829
|
+
query: (uid) => ({
|
830
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
831
|
+
method: "GET"
|
832
|
+
}),
|
833
|
+
transformResponse: (response) => response.data,
|
834
|
+
providesTags: (_result, _error, uid) => [
|
835
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
836
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
837
|
+
]
|
838
|
+
}),
|
839
|
+
getAllContentTypeSettings: builder.query({
|
840
|
+
query: () => "/content-manager/content-types-settings",
|
841
|
+
transformResponse: (response) => response.data,
|
842
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
843
|
+
}),
|
844
|
+
updateContentTypeConfiguration: builder.mutation({
|
845
|
+
query: ({ uid, ...body }) => ({
|
846
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
847
|
+
method: "PUT",
|
848
|
+
data: body
|
849
|
+
}),
|
850
|
+
transformResponse: (response) => response.data,
|
851
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
852
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
853
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
854
|
+
// Is this necessary?
|
855
|
+
{ type: "InitialData" }
|
856
|
+
]
|
857
|
+
})
|
858
|
+
})
|
859
|
+
});
|
860
|
+
const {
|
861
|
+
useGetContentTypeConfigurationQuery,
|
862
|
+
useGetAllContentTypeSettingsQuery,
|
863
|
+
useUpdateContentTypeConfigurationMutation
|
864
|
+
} = contentTypesApi;
|
865
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
866
|
+
const { type } = attribute;
|
867
|
+
if (type === "relation") {
|
868
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
869
|
+
}
|
870
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
871
|
+
};
|
872
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
873
|
+
if (!mainFieldName) {
|
874
|
+
return void 0;
|
875
|
+
}
|
876
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
877
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
878
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
879
|
+
);
|
880
|
+
return {
|
881
|
+
name: mainFieldName,
|
882
|
+
type: mainFieldType ?? "string"
|
883
|
+
};
|
884
|
+
};
|
885
|
+
const DEFAULT_SETTINGS = {
|
886
|
+
bulkable: false,
|
887
|
+
filterable: false,
|
888
|
+
searchable: false,
|
889
|
+
pagination: false,
|
890
|
+
defaultSortBy: "",
|
891
|
+
defaultSortOrder: "asc",
|
892
|
+
mainField: "id",
|
893
|
+
pageSize: 10
|
894
|
+
};
|
895
|
+
const useDocumentLayout = (model) => {
|
896
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
897
|
+
const [{ query }] = useQueryParams();
|
898
|
+
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
793
899
|
const { toggleNotification } = useNotification();
|
794
900
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
901
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
795
902
|
const {
|
796
|
-
|
797
|
-
isLoading:
|
798
|
-
|
799
|
-
|
800
|
-
} =
|
801
|
-
|
802
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
803
|
-
});
|
804
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
903
|
+
data,
|
904
|
+
isLoading: isLoadingConfigs,
|
905
|
+
error,
|
906
|
+
isFetching: isFetchingConfigs
|
907
|
+
} = useGetContentTypeConfigurationQuery(model);
|
908
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
805
909
|
React.useEffect(() => {
|
806
910
|
if (error) {
|
807
911
|
toggleNotification({
|
@@ -809,398 +913,656 @@ const useDocument = (args, opts) => {
|
|
809
913
|
message: formatAPIError(error)
|
810
914
|
});
|
811
915
|
}
|
812
|
-
}, [
|
813
|
-
const
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
(document) => {
|
821
|
-
if (!validationSchema) {
|
822
|
-
throw new Error(
|
823
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
824
|
-
);
|
825
|
-
}
|
826
|
-
try {
|
827
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
828
|
-
return null;
|
829
|
-
} catch (error2) {
|
830
|
-
if (error2 instanceof ValidationError) {
|
831
|
-
return getYupValidationErrors(error2);
|
832
|
-
}
|
833
|
-
throw error2;
|
834
|
-
}
|
916
|
+
}, [error, formatAPIError, toggleNotification]);
|
917
|
+
const editLayout = React.useMemo(
|
918
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
919
|
+
layout: [],
|
920
|
+
components: {},
|
921
|
+
metadatas: {},
|
922
|
+
options: {},
|
923
|
+
settings: DEFAULT_SETTINGS
|
835
924
|
},
|
836
|
-
[
|
925
|
+
[data, isLoading, schemas, schema, components]
|
926
|
+
);
|
927
|
+
const listLayout = React.useMemo(() => {
|
928
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
929
|
+
layout: [],
|
930
|
+
metadatas: {},
|
931
|
+
options: {},
|
932
|
+
settings: DEFAULT_SETTINGS
|
933
|
+
};
|
934
|
+
}, [data, isLoading, schemas, schema, components]);
|
935
|
+
const { layout: edit } = React.useMemo(
|
936
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
937
|
+
layout: editLayout,
|
938
|
+
query
|
939
|
+
}),
|
940
|
+
[editLayout, query, runHookWaterfall]
|
837
941
|
);
|
838
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
839
942
|
return {
|
840
|
-
|
841
|
-
document: data?.data,
|
842
|
-
meta: data?.meta,
|
943
|
+
error,
|
843
944
|
isLoading,
|
844
|
-
|
845
|
-
|
846
|
-
};
|
847
|
-
};
|
848
|
-
const useDoc = () => {
|
849
|
-
const { id, slug, collectionType, origin } = useParams();
|
850
|
-
const [{ query }] = useQueryParams();
|
851
|
-
const params = React.useMemo(() => buildValidParams(query), [query]);
|
852
|
-
if (!collectionType) {
|
853
|
-
throw new Error("Could not find collectionType in url params");
|
854
|
-
}
|
855
|
-
if (!slug) {
|
856
|
-
throw new Error("Could not find model in url params");
|
857
|
-
}
|
858
|
-
return {
|
859
|
-
collectionType,
|
860
|
-
model: slug,
|
861
|
-
id: origin || id === "create" ? void 0 : id,
|
862
|
-
...useDocument(
|
863
|
-
{ documentId: origin || id, model: slug, collectionType, params },
|
864
|
-
{
|
865
|
-
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
866
|
-
}
|
867
|
-
)
|
945
|
+
edit,
|
946
|
+
list: listLayout
|
868
947
|
};
|
869
948
|
};
|
870
|
-
const
|
871
|
-
|
872
|
-
|
873
|
-
}
|
874
|
-
return Object.keys(trad).reduce((acc, current) => {
|
875
|
-
acc[`${pluginId}.${current}`] = trad[current];
|
876
|
-
return acc;
|
877
|
-
}, {});
|
878
|
-
};
|
879
|
-
const getTranslation = (id) => `content-manager.${id}`;
|
880
|
-
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
881
|
-
id: "notification.error",
|
882
|
-
defaultMessage: "An error occurred, please try again"
|
949
|
+
const useDocLayout = () => {
|
950
|
+
const { model } = useDoc();
|
951
|
+
return useDocumentLayout(model);
|
883
952
|
};
|
884
|
-
const
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
const
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
type: "danger",
|
904
|
-
message: formatAPIError(res.error)
|
905
|
-
});
|
906
|
-
return { error: res.error };
|
907
|
-
}
|
908
|
-
toggleNotification({
|
909
|
-
type: "success",
|
910
|
-
message: formatMessage({
|
911
|
-
id: getTranslation("success.record.delete"),
|
912
|
-
defaultMessage: "Deleted document"
|
913
|
-
})
|
914
|
-
});
|
915
|
-
trackUsage("didDeleteEntry", trackerProperty);
|
916
|
-
return res.data;
|
917
|
-
} catch (err) {
|
918
|
-
toggleNotification({
|
919
|
-
type: "danger",
|
920
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
921
|
-
});
|
922
|
-
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
923
|
-
throw err;
|
953
|
+
const formatEditLayout = (data, {
|
954
|
+
schemas,
|
955
|
+
schema,
|
956
|
+
components
|
957
|
+
}) => {
|
958
|
+
let currentPanelIndex = 0;
|
959
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
960
|
+
data.contentType.layouts.edit,
|
961
|
+
schema?.attributes,
|
962
|
+
data.contentType.metadatas,
|
963
|
+
{ configurations: data.components, schemas: components },
|
964
|
+
schemas
|
965
|
+
).reduce((panels, row) => {
|
966
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
967
|
+
panels.push([row]);
|
968
|
+
currentPanelIndex += 2;
|
969
|
+
} else {
|
970
|
+
if (!panels[currentPanelIndex]) {
|
971
|
+
panels.push([]);
|
924
972
|
}
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
const
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
});
|
943
|
-
return { error: res.error };
|
973
|
+
panels[currentPanelIndex].push(row);
|
974
|
+
}
|
975
|
+
return panels;
|
976
|
+
}, []);
|
977
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
978
|
+
(acc, [uid, configuration]) => {
|
979
|
+
acc[uid] = {
|
980
|
+
layout: convertEditLayoutToFieldLayouts(
|
981
|
+
configuration.layouts.edit,
|
982
|
+
components[uid].attributes,
|
983
|
+
configuration.metadatas,
|
984
|
+
{ configurations: data.components, schemas: components }
|
985
|
+
),
|
986
|
+
settings: {
|
987
|
+
...configuration.settings,
|
988
|
+
icon: components[uid].info.icon,
|
989
|
+
displayName: components[uid].info.displayName
|
944
990
|
}
|
945
|
-
|
946
|
-
|
947
|
-
title: formatMessage({
|
948
|
-
id: getTranslation("success.records.delete"),
|
949
|
-
defaultMessage: "Successfully deleted."
|
950
|
-
}),
|
951
|
-
message: ""
|
952
|
-
});
|
953
|
-
trackUsage("didBulkDeleteEntries");
|
954
|
-
return res.data;
|
955
|
-
} catch (err) {
|
956
|
-
toggleNotification({
|
957
|
-
type: "danger",
|
958
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
959
|
-
});
|
960
|
-
trackUsage("didNotBulkDeleteEntries");
|
961
|
-
throw err;
|
962
|
-
}
|
991
|
+
};
|
992
|
+
return acc;
|
963
993
|
},
|
964
|
-
|
994
|
+
{}
|
965
995
|
);
|
966
|
-
const
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
model,
|
973
|
-
documentId,
|
974
|
-
params
|
975
|
-
});
|
976
|
-
if ("error" in res) {
|
977
|
-
toggleNotification({
|
978
|
-
type: "danger",
|
979
|
-
message: formatAPIError(res.error)
|
980
|
-
});
|
981
|
-
return { error: res.error };
|
982
|
-
}
|
983
|
-
toggleNotification({
|
984
|
-
type: "success",
|
985
|
-
message: formatMessage({
|
986
|
-
id: "content-manager.success.record.discard",
|
987
|
-
defaultMessage: "Changes discarded"
|
988
|
-
})
|
989
|
-
});
|
990
|
-
return res.data;
|
991
|
-
} catch (err) {
|
992
|
-
toggleNotification({
|
993
|
-
type: "danger",
|
994
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
995
|
-
});
|
996
|
-
throw err;
|
997
|
-
}
|
996
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
997
|
+
(acc, [attribute, metadata]) => {
|
998
|
+
return {
|
999
|
+
...acc,
|
1000
|
+
[attribute]: metadata.edit
|
1001
|
+
};
|
998
1002
|
},
|
999
|
-
|
1003
|
+
{}
|
1000
1004
|
);
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
model,
|
1009
|
-
documentId,
|
1010
|
-
data,
|
1011
|
-
params
|
1012
|
-
});
|
1013
|
-
if ("error" in res) {
|
1014
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1015
|
-
return { error: res.error };
|
1016
|
-
}
|
1017
|
-
trackUsage("didPublishEntry");
|
1018
|
-
toggleNotification({
|
1019
|
-
type: "success",
|
1020
|
-
message: formatMessage({
|
1021
|
-
id: getTranslation("success.record.publish"),
|
1022
|
-
defaultMessage: "Published document"
|
1023
|
-
})
|
1024
|
-
});
|
1025
|
-
return res.data;
|
1026
|
-
} catch (err) {
|
1027
|
-
toggleNotification({
|
1028
|
-
type: "danger",
|
1029
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1030
|
-
});
|
1031
|
-
throw err;
|
1032
|
-
}
|
1005
|
+
return {
|
1006
|
+
layout: panelledEditAttributes,
|
1007
|
+
components: componentEditAttributes,
|
1008
|
+
metadatas: editMetadatas,
|
1009
|
+
settings: {
|
1010
|
+
...data.contentType.settings,
|
1011
|
+
displayName: schema?.info.displayName
|
1033
1012
|
},
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
return { error: res.error };
|
1048
|
-
}
|
1049
|
-
toggleNotification({
|
1050
|
-
type: "success",
|
1051
|
-
message: formatMessage({
|
1052
|
-
id: getTranslation("success.record.publish"),
|
1053
|
-
defaultMessage: "Published document"
|
1054
|
-
})
|
1055
|
-
});
|
1056
|
-
return res.data;
|
1057
|
-
} catch (err) {
|
1058
|
-
toggleNotification({
|
1059
|
-
type: "danger",
|
1060
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1061
|
-
});
|
1062
|
-
throw err;
|
1013
|
+
options: {
|
1014
|
+
...schema?.options,
|
1015
|
+
...schema?.pluginOptions,
|
1016
|
+
...data.contentType.options
|
1017
|
+
}
|
1018
|
+
};
|
1019
|
+
};
|
1020
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1021
|
+
return rows.map(
|
1022
|
+
(row) => row.map((field) => {
|
1023
|
+
const attribute = attributes[field.name];
|
1024
|
+
if (!attribute) {
|
1025
|
+
return null;
|
1063
1026
|
}
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1027
|
+
const { edit: metadata } = metadatas[field.name];
|
1028
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1029
|
+
return {
|
1030
|
+
attribute,
|
1031
|
+
disabled: !metadata.editable,
|
1032
|
+
hint: metadata.description,
|
1033
|
+
label: metadata.label ?? "",
|
1034
|
+
name: field.name,
|
1035
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1036
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1037
|
+
schemas,
|
1038
|
+
components: components?.schemas ?? {}
|
1039
|
+
}),
|
1040
|
+
placeholder: metadata.placeholder ?? "",
|
1041
|
+
required: attribute.required ?? false,
|
1042
|
+
size: field.size,
|
1043
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1044
|
+
visible: metadata.visible ?? true,
|
1045
|
+
type: attribute.type
|
1046
|
+
};
|
1047
|
+
}).filter((field) => field !== null)
|
1072
1048
|
);
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1049
|
+
};
|
1050
|
+
const formatListLayout = (data, {
|
1051
|
+
schemas,
|
1052
|
+
schema,
|
1053
|
+
components
|
1054
|
+
}) => {
|
1055
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1056
|
+
(acc, [attribute, metadata]) => {
|
1057
|
+
return {
|
1058
|
+
...acc,
|
1059
|
+
[attribute]: metadata.list
|
1060
|
+
};
|
1061
|
+
},
|
1062
|
+
{}
|
1063
|
+
);
|
1064
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1065
|
+
data.contentType.layouts.list,
|
1066
|
+
schema?.attributes,
|
1067
|
+
listMetadatas,
|
1068
|
+
{ configurations: data.components, schemas: components },
|
1069
|
+
schemas
|
1070
|
+
);
|
1071
|
+
return {
|
1072
|
+
layout: listAttributes,
|
1073
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1074
|
+
metadatas: listMetadatas,
|
1075
|
+
options: {
|
1076
|
+
...schema?.options,
|
1077
|
+
...schema?.pluginOptions,
|
1078
|
+
...data.contentType.options
|
1079
|
+
}
|
1080
|
+
};
|
1081
|
+
};
|
1082
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1083
|
+
return columns.map((name) => {
|
1084
|
+
const attribute = attributes[name];
|
1085
|
+
if (!attribute) {
|
1086
|
+
return null;
|
1087
|
+
}
|
1088
|
+
const metadata = metadatas[name];
|
1089
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1090
|
+
return {
|
1091
|
+
attribute,
|
1092
|
+
label: metadata.label ?? "",
|
1093
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1094
|
+
schemas,
|
1095
|
+
components: components?.schemas ?? {}
|
1096
|
+
}),
|
1097
|
+
name,
|
1098
|
+
searchable: metadata.searchable ?? true,
|
1099
|
+
sortable: metadata.sortable ?? true
|
1100
|
+
};
|
1101
|
+
}).filter((field) => field !== null);
|
1102
|
+
};
|
1103
|
+
const useDocument = (args, opts) => {
|
1104
|
+
const { toggleNotification } = useNotification();
|
1105
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1106
|
+
const {
|
1107
|
+
currentData: data,
|
1108
|
+
isLoading: isLoadingDocument,
|
1109
|
+
isFetching: isFetchingDocument,
|
1110
|
+
error
|
1111
|
+
} = useGetDocumentQuery(args, {
|
1112
|
+
...opts,
|
1113
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1114
|
+
});
|
1115
|
+
const {
|
1116
|
+
components,
|
1117
|
+
schema,
|
1118
|
+
schemas,
|
1119
|
+
isLoading: isLoadingSchema
|
1120
|
+
} = useContentTypeSchema(args.model);
|
1121
|
+
React.useEffect(() => {
|
1122
|
+
if (error) {
|
1123
|
+
toggleNotification({
|
1124
|
+
type: "danger",
|
1125
|
+
message: formatAPIError(error)
|
1126
|
+
});
|
1127
|
+
}
|
1128
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1129
|
+
const validationSchema = React.useMemo(() => {
|
1130
|
+
if (!schema) {
|
1131
|
+
return null;
|
1132
|
+
}
|
1133
|
+
return createYupSchema(schema.attributes, components);
|
1134
|
+
}, [schema, components]);
|
1135
|
+
const validate = React.useCallback(
|
1136
|
+
(document) => {
|
1137
|
+
if (!validationSchema) {
|
1138
|
+
throw new Error(
|
1139
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1140
|
+
);
|
1141
|
+
}
|
1142
|
+
try {
|
1143
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1144
|
+
return null;
|
1145
|
+
} catch (error2) {
|
1146
|
+
if (error2 instanceof ValidationError) {
|
1147
|
+
return getYupValidationErrors(error2);
|
1089
1148
|
}
|
1090
|
-
|
1091
|
-
toggleNotification({
|
1092
|
-
type: "success",
|
1093
|
-
message: formatMessage({
|
1094
|
-
id: getTranslation("success.record.save"),
|
1095
|
-
defaultMessage: "Saved document"
|
1096
|
-
})
|
1097
|
-
});
|
1098
|
-
return res.data;
|
1099
|
-
} catch (err) {
|
1100
|
-
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1101
|
-
toggleNotification({
|
1102
|
-
type: "danger",
|
1103
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1104
|
-
});
|
1105
|
-
throw err;
|
1149
|
+
throw error2;
|
1106
1150
|
}
|
1107
1151
|
},
|
1108
|
-
[
|
1152
|
+
[validationSchema]
|
1109
1153
|
);
|
1110
|
-
const
|
1111
|
-
const
|
1112
|
-
|
1154
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1155
|
+
const hasError = !!error;
|
1156
|
+
return {
|
1157
|
+
components,
|
1158
|
+
document: data?.data,
|
1159
|
+
meta: data?.meta,
|
1160
|
+
isLoading,
|
1161
|
+
hasError,
|
1162
|
+
schema,
|
1163
|
+
schemas,
|
1164
|
+
validate
|
1165
|
+
};
|
1166
|
+
};
|
1167
|
+
const useDoc = () => {
|
1168
|
+
const { id, slug, collectionType, origin } = useParams();
|
1169
|
+
const [{ query }] = useQueryParams();
|
1170
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1171
|
+
if (!collectionType) {
|
1172
|
+
throw new Error("Could not find collectionType in url params");
|
1173
|
+
}
|
1174
|
+
if (!slug) {
|
1175
|
+
throw new Error("Could not find model in url params");
|
1176
|
+
}
|
1177
|
+
const document = useDocument(
|
1178
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1179
|
+
{
|
1180
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1181
|
+
}
|
1182
|
+
);
|
1183
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
1184
|
+
return {
|
1185
|
+
collectionType,
|
1186
|
+
model: slug,
|
1187
|
+
id: returnId,
|
1188
|
+
...document
|
1189
|
+
};
|
1190
|
+
};
|
1191
|
+
const useContentManagerContext = () => {
|
1192
|
+
const {
|
1193
|
+
collectionType,
|
1194
|
+
model,
|
1195
|
+
id,
|
1196
|
+
components,
|
1197
|
+
isLoading: isLoadingDoc,
|
1198
|
+
schema,
|
1199
|
+
schemas
|
1200
|
+
} = useDoc();
|
1201
|
+
const layout = useDocumentLayout(model);
|
1202
|
+
const form = useForm("useContentManagerContext", (state) => state);
|
1203
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1204
|
+
const slug = model;
|
1205
|
+
const isCreatingEntry = id === "create";
|
1206
|
+
useContentTypeSchema();
|
1207
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1208
|
+
const error = layout.error;
|
1209
|
+
return {
|
1210
|
+
error,
|
1211
|
+
isLoading,
|
1212
|
+
// Base metadata
|
1213
|
+
model,
|
1214
|
+
collectionType,
|
1215
|
+
id,
|
1216
|
+
slug,
|
1217
|
+
isCreatingEntry,
|
1218
|
+
isSingleType,
|
1219
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1220
|
+
// All schema infos
|
1221
|
+
components,
|
1222
|
+
contentType: schema,
|
1223
|
+
contentTypes: schemas,
|
1224
|
+
// Form state
|
1225
|
+
form,
|
1226
|
+
// layout infos
|
1227
|
+
layout
|
1228
|
+
};
|
1229
|
+
};
|
1230
|
+
const prefixPluginTranslations = (trad, pluginId) => {
|
1231
|
+
if (!pluginId) {
|
1232
|
+
throw new TypeError("pluginId can't be empty");
|
1233
|
+
}
|
1234
|
+
return Object.keys(trad).reduce((acc, current) => {
|
1235
|
+
acc[`${pluginId}.${current}`] = trad[current];
|
1236
|
+
return acc;
|
1237
|
+
}, {});
|
1238
|
+
};
|
1239
|
+
const getTranslation = (id) => `content-manager.${id}`;
|
1240
|
+
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
1241
|
+
id: "notification.error",
|
1242
|
+
defaultMessage: "An error occurred, please try again"
|
1243
|
+
};
|
1244
|
+
const useDocumentActions = () => {
|
1245
|
+
const { toggleNotification } = useNotification();
|
1246
|
+
const { formatMessage } = useIntl();
|
1247
|
+
const { trackUsage } = useTracking();
|
1248
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1249
|
+
const navigate = useNavigate();
|
1250
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
1251
|
+
const [deleteDocument] = useDeleteDocumentMutation();
|
1252
|
+
const _delete = React.useCallback(
|
1253
|
+
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
1113
1254
|
try {
|
1114
|
-
trackUsage("
|
1115
|
-
const res = await
|
1255
|
+
trackUsage("willDeleteEntry", trackerProperty);
|
1256
|
+
const res = await deleteDocument({
|
1116
1257
|
collectionType,
|
1117
1258
|
model,
|
1118
1259
|
documentId,
|
1119
|
-
params
|
1120
|
-
data: {
|
1121
|
-
discardDraft
|
1122
|
-
}
|
1260
|
+
params
|
1123
1261
|
});
|
1124
1262
|
if ("error" in res) {
|
1125
|
-
toggleNotification({
|
1263
|
+
toggleNotification({
|
1264
|
+
type: "danger",
|
1265
|
+
message: formatAPIError(res.error)
|
1266
|
+
});
|
1126
1267
|
return { error: res.error };
|
1127
1268
|
}
|
1128
|
-
trackUsage("didUnpublishEntry");
|
1129
1269
|
toggleNotification({
|
1130
1270
|
type: "success",
|
1131
1271
|
message: formatMessage({
|
1132
|
-
id: getTranslation("success.record.
|
1133
|
-
defaultMessage: "
|
1272
|
+
id: getTranslation("success.record.delete"),
|
1273
|
+
defaultMessage: "Deleted document"
|
1134
1274
|
})
|
1135
1275
|
});
|
1276
|
+
trackUsage("didDeleteEntry", trackerProperty);
|
1136
1277
|
return res.data;
|
1137
1278
|
} catch (err) {
|
1138
1279
|
toggleNotification({
|
1139
1280
|
type: "danger",
|
1140
1281
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1141
1282
|
});
|
1283
|
+
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
1142
1284
|
throw err;
|
1143
1285
|
}
|
1144
1286
|
},
|
1145
|
-
[trackUsage,
|
1287
|
+
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
1146
1288
|
);
|
1147
|
-
const [
|
1148
|
-
const
|
1289
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1290
|
+
const deleteMany = React.useCallback(
|
1149
1291
|
async ({ model, documentIds, params }) => {
|
1150
1292
|
try {
|
1151
|
-
trackUsage("
|
1152
|
-
const res = await
|
1293
|
+
trackUsage("willBulkDeleteEntries");
|
1294
|
+
const res = await deleteManyDocuments({
|
1153
1295
|
model,
|
1154
1296
|
documentIds,
|
1155
1297
|
params
|
1156
1298
|
});
|
1157
1299
|
if ("error" in res) {
|
1158
|
-
toggleNotification({
|
1300
|
+
toggleNotification({
|
1301
|
+
type: "danger",
|
1302
|
+
message: formatAPIError(res.error)
|
1303
|
+
});
|
1159
1304
|
return { error: res.error };
|
1160
1305
|
}
|
1161
|
-
trackUsage("didBulkUnpublishEntries");
|
1162
1306
|
toggleNotification({
|
1163
1307
|
type: "success",
|
1164
1308
|
title: formatMessage({
|
1165
|
-
id: getTranslation("success.records.
|
1166
|
-
defaultMessage: "Successfully
|
1309
|
+
id: getTranslation("success.records.delete"),
|
1310
|
+
defaultMessage: "Successfully deleted."
|
1167
1311
|
}),
|
1168
1312
|
message: ""
|
1169
1313
|
});
|
1314
|
+
trackUsage("didBulkDeleteEntries");
|
1170
1315
|
return res.data;
|
1171
1316
|
} catch (err) {
|
1172
1317
|
toggleNotification({
|
1173
1318
|
type: "danger",
|
1174
1319
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1175
1320
|
});
|
1176
|
-
trackUsage("
|
1321
|
+
trackUsage("didNotBulkDeleteEntries");
|
1177
1322
|
throw err;
|
1178
1323
|
}
|
1179
1324
|
},
|
1180
|
-
[trackUsage,
|
1325
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1181
1326
|
);
|
1182
|
-
const [
|
1183
|
-
const
|
1184
|
-
async ({ model, params }
|
1327
|
+
const [discardDocument] = useDiscardDocumentMutation();
|
1328
|
+
const discard = React.useCallback(
|
1329
|
+
async ({ collectionType, model, documentId, params }) => {
|
1185
1330
|
try {
|
1186
|
-
const res = await
|
1331
|
+
const res = await discardDocument({
|
1332
|
+
collectionType,
|
1187
1333
|
model,
|
1188
|
-
|
1334
|
+
documentId,
|
1189
1335
|
params
|
1190
1336
|
});
|
1191
1337
|
if ("error" in res) {
|
1192
|
-
toggleNotification({
|
1193
|
-
|
1338
|
+
toggleNotification({
|
1339
|
+
type: "danger",
|
1340
|
+
message: formatAPIError(res.error)
|
1341
|
+
});
|
1194
1342
|
return { error: res.error };
|
1195
1343
|
}
|
1196
|
-
trackUsage("didCreateEntry", trackerProperty);
|
1197
1344
|
toggleNotification({
|
1198
1345
|
type: "success",
|
1199
1346
|
message: formatMessage({
|
1200
|
-
id:
|
1201
|
-
defaultMessage: "
|
1347
|
+
id: "content-manager.success.record.discard",
|
1348
|
+
defaultMessage: "Changes discarded"
|
1349
|
+
})
|
1350
|
+
});
|
1351
|
+
return res.data;
|
1352
|
+
} catch (err) {
|
1353
|
+
toggleNotification({
|
1354
|
+
type: "danger",
|
1355
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1356
|
+
});
|
1357
|
+
throw err;
|
1358
|
+
}
|
1359
|
+
},
|
1360
|
+
[discardDocument, formatAPIError, formatMessage, toggleNotification]
|
1361
|
+
);
|
1362
|
+
const [publishDocument] = usePublishDocumentMutation();
|
1363
|
+
const publish = React.useCallback(
|
1364
|
+
async ({ collectionType, model, documentId, params }, data) => {
|
1365
|
+
try {
|
1366
|
+
trackUsage("willPublishEntry");
|
1367
|
+
const res = await publishDocument({
|
1368
|
+
collectionType,
|
1369
|
+
model,
|
1370
|
+
documentId,
|
1371
|
+
data,
|
1372
|
+
params
|
1373
|
+
});
|
1374
|
+
if ("error" in res) {
|
1375
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1376
|
+
return { error: res.error };
|
1377
|
+
}
|
1378
|
+
trackUsage("didPublishEntry");
|
1379
|
+
toggleNotification({
|
1380
|
+
type: "success",
|
1381
|
+
message: formatMessage({
|
1382
|
+
id: getTranslation("success.record.publish"),
|
1383
|
+
defaultMessage: "Published document"
|
1384
|
+
})
|
1385
|
+
});
|
1386
|
+
return res.data;
|
1387
|
+
} catch (err) {
|
1388
|
+
toggleNotification({
|
1389
|
+
type: "danger",
|
1390
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1391
|
+
});
|
1392
|
+
throw err;
|
1393
|
+
}
|
1394
|
+
},
|
1395
|
+
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1396
|
+
);
|
1397
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1398
|
+
const publishMany = React.useCallback(
|
1399
|
+
async ({ model, documentIds, params }) => {
|
1400
|
+
try {
|
1401
|
+
const res = await publishManyDocuments({
|
1402
|
+
model,
|
1403
|
+
documentIds,
|
1404
|
+
params
|
1405
|
+
});
|
1406
|
+
if ("error" in res) {
|
1407
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1408
|
+
return { error: res.error };
|
1409
|
+
}
|
1410
|
+
toggleNotification({
|
1411
|
+
type: "success",
|
1412
|
+
message: formatMessage({
|
1413
|
+
id: getTranslation("success.record.publish"),
|
1414
|
+
defaultMessage: "Published document"
|
1415
|
+
})
|
1416
|
+
});
|
1417
|
+
return res.data;
|
1418
|
+
} catch (err) {
|
1419
|
+
toggleNotification({
|
1420
|
+
type: "danger",
|
1421
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1422
|
+
});
|
1423
|
+
throw err;
|
1424
|
+
}
|
1425
|
+
},
|
1426
|
+
[
|
1427
|
+
// trackUsage,
|
1428
|
+
publishManyDocuments,
|
1429
|
+
toggleNotification,
|
1430
|
+
formatMessage,
|
1431
|
+
formatAPIError
|
1432
|
+
]
|
1433
|
+
);
|
1434
|
+
const [updateDocument] = useUpdateDocumentMutation();
|
1435
|
+
const update = React.useCallback(
|
1436
|
+
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
1437
|
+
try {
|
1438
|
+
trackUsage("willEditEntry", trackerProperty);
|
1439
|
+
const res = await updateDocument({
|
1440
|
+
collectionType,
|
1441
|
+
model,
|
1442
|
+
documentId,
|
1443
|
+
data,
|
1444
|
+
params
|
1445
|
+
});
|
1446
|
+
if ("error" in res) {
|
1447
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1448
|
+
trackUsage("didNotEditEntry", { error: res.error, ...trackerProperty });
|
1449
|
+
return { error: res.error };
|
1450
|
+
}
|
1451
|
+
trackUsage("didEditEntry", trackerProperty);
|
1452
|
+
toggleNotification({
|
1453
|
+
type: "success",
|
1454
|
+
message: formatMessage({
|
1455
|
+
id: getTranslation("success.record.save"),
|
1456
|
+
defaultMessage: "Saved document"
|
1457
|
+
})
|
1458
|
+
});
|
1459
|
+
return res.data;
|
1460
|
+
} catch (err) {
|
1461
|
+
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1462
|
+
toggleNotification({
|
1463
|
+
type: "danger",
|
1464
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1465
|
+
});
|
1466
|
+
throw err;
|
1467
|
+
}
|
1468
|
+
},
|
1469
|
+
[trackUsage, updateDocument, toggleNotification, formatMessage, formatAPIError]
|
1470
|
+
);
|
1471
|
+
const [unpublishDocument] = useUnpublishDocumentMutation();
|
1472
|
+
const unpublish = React.useCallback(
|
1473
|
+
async ({ collectionType, model, documentId, params }, discardDraft = false) => {
|
1474
|
+
try {
|
1475
|
+
trackUsage("willUnpublishEntry");
|
1476
|
+
const res = await unpublishDocument({
|
1477
|
+
collectionType,
|
1478
|
+
model,
|
1479
|
+
documentId,
|
1480
|
+
params,
|
1481
|
+
data: {
|
1482
|
+
discardDraft
|
1483
|
+
}
|
1484
|
+
});
|
1485
|
+
if ("error" in res) {
|
1486
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1487
|
+
return { error: res.error };
|
1488
|
+
}
|
1489
|
+
trackUsage("didUnpublishEntry");
|
1490
|
+
toggleNotification({
|
1491
|
+
type: "success",
|
1492
|
+
message: formatMessage({
|
1493
|
+
id: getTranslation("success.record.unpublish"),
|
1494
|
+
defaultMessage: "Unpublished document"
|
1495
|
+
})
|
1496
|
+
});
|
1497
|
+
return res.data;
|
1498
|
+
} catch (err) {
|
1499
|
+
toggleNotification({
|
1500
|
+
type: "danger",
|
1501
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1502
|
+
});
|
1503
|
+
throw err;
|
1504
|
+
}
|
1505
|
+
},
|
1506
|
+
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1507
|
+
);
|
1508
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1509
|
+
const unpublishMany = React.useCallback(
|
1510
|
+
async ({ model, documentIds, params }) => {
|
1511
|
+
try {
|
1512
|
+
trackUsage("willBulkUnpublishEntries");
|
1513
|
+
const res = await unpublishManyDocuments({
|
1514
|
+
model,
|
1515
|
+
documentIds,
|
1516
|
+
params
|
1517
|
+
});
|
1518
|
+
if ("error" in res) {
|
1519
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1520
|
+
return { error: res.error };
|
1521
|
+
}
|
1522
|
+
trackUsage("didBulkUnpublishEntries");
|
1523
|
+
toggleNotification({
|
1524
|
+
type: "success",
|
1525
|
+
title: formatMessage({
|
1526
|
+
id: getTranslation("success.records.unpublish"),
|
1527
|
+
defaultMessage: "Successfully unpublished."
|
1528
|
+
}),
|
1529
|
+
message: ""
|
1530
|
+
});
|
1531
|
+
return res.data;
|
1532
|
+
} catch (err) {
|
1533
|
+
toggleNotification({
|
1534
|
+
type: "danger",
|
1535
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1536
|
+
});
|
1537
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1538
|
+
throw err;
|
1539
|
+
}
|
1540
|
+
},
|
1541
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1542
|
+
);
|
1543
|
+
const [createDocument] = useCreateDocumentMutation();
|
1544
|
+
const create = React.useCallback(
|
1545
|
+
async ({ model, params }, data, trackerProperty) => {
|
1546
|
+
try {
|
1547
|
+
const res = await createDocument({
|
1548
|
+
model,
|
1549
|
+
data,
|
1550
|
+
params
|
1551
|
+
});
|
1552
|
+
if ("error" in res) {
|
1553
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1554
|
+
trackUsage("didNotCreateEntry", { error: res.error, ...trackerProperty });
|
1555
|
+
return { error: res.error };
|
1556
|
+
}
|
1557
|
+
trackUsage("didCreateEntry", trackerProperty);
|
1558
|
+
toggleNotification({
|
1559
|
+
type: "success",
|
1560
|
+
message: formatMessage({
|
1561
|
+
id: getTranslation("success.record.save"),
|
1562
|
+
defaultMessage: "Saved document"
|
1202
1563
|
})
|
1203
1564
|
});
|
1565
|
+
setCurrentStep("contentManager.success");
|
1204
1566
|
return res.data;
|
1205
1567
|
} catch (err) {
|
1206
1568
|
toggleNotification({
|
@@ -1303,7 +1665,7 @@ const useDocumentActions = () => {
|
|
1303
1665
|
};
|
1304
1666
|
};
|
1305
1667
|
const ProtectedHistoryPage = lazy(
|
1306
|
-
() => import("./History-
|
1668
|
+
() => import("./History-DRwA3oMM.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1307
1669
|
);
|
1308
1670
|
const routes$1 = [
|
1309
1671
|
{
|
@@ -1316,31 +1678,31 @@ const routes$1 = [
|
|
1316
1678
|
}
|
1317
1679
|
];
|
1318
1680
|
const ProtectedEditViewPage = lazy(
|
1319
|
-
() => import("./EditViewPage-
|
1681
|
+
() => import("./EditViewPage-B82x_x1b.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1320
1682
|
);
|
1321
1683
|
const ProtectedListViewPage = lazy(
|
1322
|
-
() => import("./ListViewPage-
|
1684
|
+
() => import("./ListViewPage-CELx2ysp.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1323
1685
|
);
|
1324
1686
|
const ProtectedListConfiguration = lazy(
|
1325
|
-
() => import("./ListConfigurationPage-
|
1687
|
+
() => import("./ListConfigurationPage-BxfQJzPk.mjs").then((mod) => ({
|
1326
1688
|
default: mod.ProtectedListConfiguration
|
1327
1689
|
}))
|
1328
1690
|
);
|
1329
1691
|
const ProtectedEditConfigurationPage = lazy(
|
1330
|
-
() => import("./EditConfigurationPage-
|
1692
|
+
() => import("./EditConfigurationPage-DdPNAbl3.mjs").then((mod) => ({
|
1331
1693
|
default: mod.ProtectedEditConfigurationPage
|
1332
1694
|
}))
|
1333
1695
|
);
|
1334
1696
|
const ProtectedComponentConfigurationPage = lazy(
|
1335
|
-
() => import("./ComponentConfigurationPage-
|
1697
|
+
() => import("./ComponentConfigurationPage-DfFSZQxe.mjs").then((mod) => ({
|
1336
1698
|
default: mod.ProtectedComponentConfigurationPage
|
1337
1699
|
}))
|
1338
1700
|
);
|
1339
1701
|
const NoPermissions = lazy(
|
1340
|
-
() => import("./NoPermissionsPage-
|
1702
|
+
() => import("./NoPermissionsPage-DWleVYK7.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1341
1703
|
);
|
1342
1704
|
const NoContentType = lazy(
|
1343
|
-
() => import("./NoContentTypePage-
|
1705
|
+
() => import("./NoContentTypePage-DtJ9jcfk.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1344
1706
|
);
|
1345
1707
|
const CollectionTypePages = () => {
|
1346
1708
|
const { collectionType } = useParams();
|
@@ -1396,1065 +1758,735 @@ const DocumentActions = ({ actions: actions2 }) => {
|
|
1396
1758
|
}
|
1397
1759
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
1398
1760
|
return positions.includes("panel");
|
1399
|
-
});
|
1400
|
-
if (!primaryAction) {
|
1401
|
-
return null;
|
1402
|
-
}
|
1403
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, alignItems: "stretch", width: "100%", children: [
|
1404
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
1405
|
-
/* @__PURE__ */ jsx(DocumentActionButton, { ...primaryAction, variant: primaryAction.variant || "default" }),
|
1406
|
-
restActions.length > 0 ? /* @__PURE__ */ jsx(
|
1407
|
-
DocumentActionsMenu,
|
1408
|
-
{
|
1409
|
-
actions: restActions,
|
1410
|
-
label: formatMessage({
|
1411
|
-
id: "content-manager.containers.edit.panels.default.more-actions",
|
1412
|
-
defaultMessage: "More document actions"
|
1413
|
-
})
|
1414
|
-
}
|
1415
|
-
) : null
|
1416
|
-
] }),
|
1417
|
-
secondaryAction ? /* @__PURE__ */ jsx(
|
1418
|
-
DocumentActionButton,
|
1419
|
-
{
|
1420
|
-
...secondaryAction,
|
1421
|
-
variant: secondaryAction.variant || "secondary"
|
1422
|
-
}
|
1423
|
-
) : null
|
1424
|
-
] });
|
1425
|
-
};
|
1426
|
-
const DocumentActionButton = (action) => {
|
1427
|
-
const [dialogId, setDialogId] = React.useState(null);
|
1428
|
-
const { toggleNotification } = useNotification();
|
1429
|
-
const handleClick = (action2) => async (e) => {
|
1430
|
-
const { onClick = () => false, dialog, id } = action2;
|
1431
|
-
const muteDialog = await onClick(e);
|
1432
|
-
if (dialog && !muteDialog) {
|
1433
|
-
switch (dialog.type) {
|
1434
|
-
case "notification":
|
1435
|
-
toggleNotification({
|
1436
|
-
title: dialog.title,
|
1437
|
-
message: dialog.content,
|
1438
|
-
type: dialog.status,
|
1439
|
-
timeout: dialog.timeout,
|
1440
|
-
onClose: dialog.onClose
|
1441
|
-
});
|
1442
|
-
break;
|
1443
|
-
case "dialog":
|
1444
|
-
case "modal":
|
1445
|
-
e.preventDefault();
|
1446
|
-
setDialogId(id);
|
1447
|
-
}
|
1448
|
-
}
|
1449
|
-
};
|
1450
|
-
const handleClose = () => {
|
1451
|
-
setDialogId(null);
|
1452
|
-
};
|
1453
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
1454
|
-
/* @__PURE__ */ jsx(
|
1455
|
-
Button,
|
1456
|
-
{
|
1457
|
-
flex: "auto",
|
1458
|
-
startIcon: action.icon,
|
1459
|
-
disabled: action.disabled,
|
1460
|
-
onClick: handleClick(action),
|
1461
|
-
justifyContent: "center",
|
1462
|
-
variant: action.variant || "default",
|
1463
|
-
paddingTop: "7px",
|
1464
|
-
paddingBottom: "7px",
|
1465
|
-
children: action.label
|
1466
|
-
}
|
1467
|
-
),
|
1468
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
|
1469
|
-
DocumentActionConfirmDialog,
|
1470
|
-
{
|
1471
|
-
...action.dialog,
|
1472
|
-
variant: action.dialog?.variant ?? action.variant,
|
1473
|
-
isOpen: dialogId === action.id,
|
1474
|
-
onClose: handleClose
|
1475
|
-
}
|
1476
|
-
) : null,
|
1477
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
|
1478
|
-
DocumentActionModal,
|
1479
|
-
{
|
1480
|
-
...action.dialog,
|
1481
|
-
onModalClose: handleClose,
|
1482
|
-
isOpen: dialogId === action.id
|
1483
|
-
}
|
1484
|
-
) : null
|
1485
|
-
] });
|
1486
|
-
};
|
1487
|
-
const DocumentActionsMenu = ({
|
1488
|
-
actions: actions2,
|
1489
|
-
children,
|
1490
|
-
label,
|
1491
|
-
variant = "tertiary"
|
1492
|
-
}) => {
|
1493
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
1494
|
-
const [dialogId, setDialogId] = React.useState(null);
|
1495
|
-
const { formatMessage } = useIntl();
|
1496
|
-
const { toggleNotification } = useNotification();
|
1497
|
-
const isDisabled = actions2.every((action) => action.disabled) || actions2.length === 0;
|
1498
|
-
const handleClick = (action) => async (e) => {
|
1499
|
-
const { onClick = () => false, dialog, id } = action;
|
1500
|
-
const muteDialog = await onClick(e);
|
1501
|
-
if (dialog && !muteDialog) {
|
1502
|
-
switch (dialog.type) {
|
1503
|
-
case "notification":
|
1504
|
-
toggleNotification({
|
1505
|
-
title: dialog.title,
|
1506
|
-
message: dialog.content,
|
1507
|
-
type: dialog.status,
|
1508
|
-
timeout: dialog.timeout,
|
1509
|
-
onClose: dialog.onClose
|
1510
|
-
});
|
1511
|
-
break;
|
1512
|
-
case "dialog":
|
1513
|
-
case "modal":
|
1514
|
-
setDialogId(id);
|
1515
|
-
}
|
1516
|
-
}
|
1517
|
-
};
|
1518
|
-
const handleClose = () => {
|
1519
|
-
setDialogId(null);
|
1520
|
-
setIsOpen(false);
|
1521
|
-
};
|
1522
|
-
return /* @__PURE__ */ jsxs(Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1523
|
-
/* @__PURE__ */ jsxs(
|
1524
|
-
StyledMoreButton,
|
1525
|
-
{
|
1526
|
-
disabled: isDisabled,
|
1527
|
-
size: "S",
|
1528
|
-
endIcon: null,
|
1529
|
-
paddingTop: "4px",
|
1530
|
-
paddingLeft: "7px",
|
1531
|
-
paddingRight: "7px",
|
1532
|
-
variant,
|
1533
|
-
children: [
|
1534
|
-
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
1535
|
-
/* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1536
|
-
id: "content-manager.containers.edit.panels.default.more-actions",
|
1537
|
-
defaultMessage: "More document actions"
|
1538
|
-
}) })
|
1539
|
-
]
|
1540
|
-
}
|
1541
|
-
),
|
1542
|
-
/* @__PURE__ */ jsxs(Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1543
|
-
actions2.map((action) => {
|
1544
|
-
return /* @__PURE__ */ jsx(
|
1545
|
-
Menu.Item,
|
1546
|
-
{
|
1547
|
-
disabled: action.disabled,
|
1548
|
-
onSelect: handleClick(action),
|
1549
|
-
display: "block",
|
1550
|
-
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
|
1551
|
-
/* @__PURE__ */ jsxs(
|
1552
|
-
Flex,
|
1553
|
-
{
|
1554
|
-
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1555
|
-
gap: 2,
|
1556
|
-
tag: "span",
|
1557
|
-
children: [
|
1558
|
-
/* @__PURE__ */ jsx(
|
1559
|
-
Flex,
|
1560
|
-
{
|
1561
|
-
tag: "span",
|
1562
|
-
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1563
|
-
children: action.icon
|
1564
|
-
}
|
1565
|
-
),
|
1566
|
-
action.label
|
1567
|
-
]
|
1568
|
-
}
|
1569
|
-
),
|
1570
|
-
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
|
1571
|
-
Flex,
|
1572
|
-
{
|
1573
|
-
alignItems: "center",
|
1574
|
-
background: "alternative100",
|
1575
|
-
borderStyle: "solid",
|
1576
|
-
borderColor: "alternative200",
|
1577
|
-
borderWidth: "1px",
|
1578
|
-
height: 5,
|
1579
|
-
paddingLeft: 2,
|
1580
|
-
paddingRight: 2,
|
1581
|
-
hasRadius: true,
|
1582
|
-
color: "alternative600",
|
1583
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1584
|
-
}
|
1585
|
-
)
|
1586
|
-
] })
|
1587
|
-
},
|
1588
|
-
action.id
|
1589
|
-
);
|
1590
|
-
}),
|
1591
|
-
children
|
1592
|
-
] }),
|
1593
|
-
actions2.map((action) => {
|
1594
|
-
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
1595
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
|
1596
|
-
DocumentActionConfirmDialog,
|
1597
|
-
{
|
1598
|
-
...action.dialog,
|
1599
|
-
variant: action.variant,
|
1600
|
-
isOpen: dialogId === action.id,
|
1601
|
-
onClose: handleClose
|
1602
|
-
}
|
1603
|
-
) : null,
|
1604
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
|
1605
|
-
DocumentActionModal,
|
1606
|
-
{
|
1607
|
-
...action.dialog,
|
1608
|
-
onModalClose: handleClose,
|
1609
|
-
isOpen: dialogId === action.id
|
1610
|
-
}
|
1611
|
-
) : null
|
1612
|
-
] }, action.id);
|
1613
|
-
})
|
1614
|
-
] });
|
1615
|
-
};
|
1616
|
-
const convertActionVariantToColor = (variant = "secondary") => {
|
1617
|
-
switch (variant) {
|
1618
|
-
case "danger":
|
1619
|
-
return "danger600";
|
1620
|
-
case "secondary":
|
1621
|
-
return void 0;
|
1622
|
-
case "success":
|
1623
|
-
return "success600";
|
1624
|
-
default:
|
1625
|
-
return "primary600";
|
1626
|
-
}
|
1627
|
-
};
|
1628
|
-
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1629
|
-
switch (variant) {
|
1630
|
-
case "danger":
|
1631
|
-
return "danger600";
|
1632
|
-
case "secondary":
|
1633
|
-
return "neutral500";
|
1634
|
-
case "success":
|
1635
|
-
return "success600";
|
1636
|
-
default:
|
1637
|
-
return "primary600";
|
1638
|
-
}
|
1639
|
-
};
|
1640
|
-
const StyledMoreButton = styled(Menu.Trigger)`
|
1641
|
-
& > span {
|
1642
|
-
display: flex;
|
1643
|
-
}
|
1644
|
-
`;
|
1645
|
-
const DocumentActionConfirmDialog = ({
|
1646
|
-
onClose,
|
1647
|
-
onCancel,
|
1648
|
-
onConfirm,
|
1649
|
-
title,
|
1650
|
-
content,
|
1651
|
-
isOpen,
|
1652
|
-
variant = "secondary"
|
1653
|
-
}) => {
|
1654
|
-
const { formatMessage } = useIntl();
|
1655
|
-
const handleClose = async () => {
|
1656
|
-
if (onCancel) {
|
1657
|
-
await onCancel();
|
1658
|
-
}
|
1659
|
-
onClose();
|
1660
|
-
};
|
1661
|
-
const handleConfirm = async () => {
|
1662
|
-
if (onConfirm) {
|
1663
|
-
await onConfirm();
|
1664
|
-
}
|
1665
|
-
onClose();
|
1666
|
-
};
|
1667
|
-
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
1668
|
-
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1669
|
-
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1670
|
-
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1671
|
-
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
1672
|
-
id: "app.components.Button.cancel",
|
1673
|
-
defaultMessage: "Cancel"
|
1674
|
-
}) }) }),
|
1675
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
1676
|
-
id: "app.components.Button.confirm",
|
1677
|
-
defaultMessage: "Confirm"
|
1678
|
-
}) })
|
1679
|
-
] })
|
1680
|
-
] }) });
|
1681
|
-
};
|
1682
|
-
const DocumentActionModal = ({
|
1683
|
-
isOpen,
|
1684
|
-
title,
|
1685
|
-
onClose,
|
1686
|
-
footer: Footer,
|
1687
|
-
content: Content,
|
1688
|
-
onModalClose
|
1689
|
-
}) => {
|
1690
|
-
const handleClose = () => {
|
1691
|
-
if (onClose) {
|
1692
|
-
onClose();
|
1693
|
-
}
|
1694
|
-
onModalClose();
|
1695
|
-
};
|
1696
|
-
return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
1697
|
-
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
|
1698
|
-
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
|
1699
|
-
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1700
|
-
] }) });
|
1701
|
-
};
|
1702
|
-
const PublishAction$1 = ({
|
1703
|
-
activeTab,
|
1704
|
-
documentId,
|
1705
|
-
model,
|
1706
|
-
collectionType,
|
1707
|
-
meta,
|
1708
|
-
document
|
1709
|
-
}) => {
|
1710
|
-
const { schema } = useDoc();
|
1711
|
-
const navigate = useNavigate();
|
1712
|
-
const { toggleNotification } = useNotification();
|
1713
|
-
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
1714
|
-
const isListView = useMatch(LIST_PATH) !== null;
|
1715
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
1716
|
-
const { formatMessage } = useIntl();
|
1717
|
-
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1718
|
-
const { publish } = useDocumentActions();
|
1719
|
-
const [
|
1720
|
-
countDraftRelations,
|
1721
|
-
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
1722
|
-
] = useLazyGetDraftRelationCountQuery();
|
1723
|
-
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
1724
|
-
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1725
|
-
const [{ query, rawQuery }] = useQueryParams();
|
1726
|
-
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1727
|
-
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
1728
|
-
const setSubmitting = useForm("PublishAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
1729
|
-
const isSubmitting = useForm("PublishAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
1730
|
-
const validate = useForm("PublishAction", (state) => state.validate);
|
1731
|
-
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1732
|
-
const formValues = useForm("PublishAction", ({ values }) => values);
|
1733
|
-
React.useEffect(() => {
|
1734
|
-
if (isErrorDraftRelations) {
|
1735
|
-
toggleNotification({
|
1736
|
-
type: "danger",
|
1737
|
-
message: formatMessage({
|
1738
|
-
id: getTranslation("error.records.fetch-draft-relatons"),
|
1739
|
-
defaultMessage: "An error occurred while fetching draft relations on this document."
|
1740
|
-
})
|
1741
|
-
});
|
1742
|
-
}
|
1743
|
-
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
1744
|
-
React.useEffect(() => {
|
1745
|
-
const localDraftRelations = /* @__PURE__ */ new Set();
|
1746
|
-
const extractDraftRelations = (data) => {
|
1747
|
-
const relations = data.connect || [];
|
1748
|
-
relations.forEach((relation) => {
|
1749
|
-
if (relation.status === "draft") {
|
1750
|
-
localDraftRelations.add(relation.id);
|
1751
|
-
}
|
1752
|
-
});
|
1753
|
-
};
|
1754
|
-
const traverseAndExtract = (data) => {
|
1755
|
-
Object.entries(data).forEach(([key, value]) => {
|
1756
|
-
if (key === "connect" && Array.isArray(value)) {
|
1757
|
-
extractDraftRelations({ connect: value });
|
1758
|
-
} else if (typeof value === "object" && value !== null) {
|
1759
|
-
traverseAndExtract(value);
|
1760
|
-
}
|
1761
|
-
});
|
1762
|
-
};
|
1763
|
-
if (!documentId || modified) {
|
1764
|
-
traverseAndExtract(formValues);
|
1765
|
-
setLocalCountOfDraftRelations(localDraftRelations.size);
|
1766
|
-
}
|
1767
|
-
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1768
|
-
React.useEffect(() => {
|
1769
|
-
if (documentId && !isListView) {
|
1770
|
-
const fetchDraftRelationsCount = async () => {
|
1771
|
-
const { data, error } = await countDraftRelations({
|
1772
|
-
collectionType,
|
1773
|
-
model,
|
1774
|
-
documentId,
|
1775
|
-
params
|
1776
|
-
});
|
1777
|
-
if (error) {
|
1778
|
-
throw error;
|
1779
|
-
}
|
1780
|
-
if (data) {
|
1781
|
-
setServerCountOfDraftRelations(data.data);
|
1782
|
-
}
|
1783
|
-
};
|
1784
|
-
fetchDraftRelationsCount();
|
1785
|
-
}
|
1786
|
-
}, [isListView, documentId, countDraftRelations, collectionType, model, params]);
|
1787
|
-
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1788
|
-
if (!schema?.options?.draftAndPublish) {
|
1761
|
+
});
|
1762
|
+
if (!primaryAction) {
|
1789
1763
|
return null;
|
1790
1764
|
}
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1795
|
-
|
1796
|
-
toggleNotification({
|
1797
|
-
type: "danger",
|
1798
|
-
message: formatMessage({
|
1799
|
-
id: "content-manager.validation.error",
|
1800
|
-
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1801
|
-
})
|
1802
|
-
});
|
1803
|
-
return;
|
1804
|
-
}
|
1805
|
-
const res = await publish(
|
1806
|
-
{
|
1807
|
-
collectionType,
|
1808
|
-
model,
|
1809
|
-
documentId,
|
1810
|
-
params
|
1811
|
-
},
|
1812
|
-
formValues
|
1813
|
-
);
|
1814
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1815
|
-
navigate({
|
1816
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1817
|
-
search: rawQuery
|
1818
|
-
});
|
1819
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1820
|
-
setErrors(formatValidationErrors(res.error));
|
1821
|
-
}
|
1822
|
-
} finally {
|
1823
|
-
setSubmitting(false);
|
1824
|
-
}
|
1825
|
-
};
|
1826
|
-
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1827
|
-
const hasDraftRelations = totalDraftRelations > 0;
|
1828
|
-
return {
|
1829
|
-
/**
|
1830
|
-
* Disabled when:
|
1831
|
-
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
1832
|
-
* - the form is submitting
|
1833
|
-
* - the active tab is the published tab
|
1834
|
-
* - the document is already published & not modified
|
1835
|
-
* - the document is being created & not modified
|
1836
|
-
* - the user doesn't have the permission to publish
|
1837
|
-
*/
|
1838
|
-
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1839
|
-
label: formatMessage({
|
1840
|
-
id: "app.utils.publish",
|
1841
|
-
defaultMessage: "Publish"
|
1842
|
-
}),
|
1843
|
-
onClick: async () => {
|
1844
|
-
if (hasDraftRelations) {
|
1845
|
-
return;
|
1846
|
-
}
|
1847
|
-
await performPublish();
|
1848
|
-
},
|
1849
|
-
dialog: hasDraftRelations ? {
|
1850
|
-
type: "dialog",
|
1851
|
-
variant: "danger",
|
1852
|
-
footer: null,
|
1853
|
-
title: formatMessage({
|
1854
|
-
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
1855
|
-
defaultMessage: "Confirmation"
|
1856
|
-
}),
|
1857
|
-
content: formatMessage(
|
1858
|
-
{
|
1859
|
-
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
1860
|
-
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
1861
|
-
},
|
1765
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, alignItems: "stretch", width: "100%", children: [
|
1766
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
1767
|
+
/* @__PURE__ */ jsx(DocumentActionButton, { ...primaryAction, variant: primaryAction.variant || "default" }),
|
1768
|
+
restActions.length > 0 ? /* @__PURE__ */ jsx(
|
1769
|
+
DocumentActionsMenu,
|
1862
1770
|
{
|
1863
|
-
|
1771
|
+
actions: restActions,
|
1772
|
+
label: formatMessage({
|
1773
|
+
id: "content-manager.containers.edit.panels.default.more-actions",
|
1774
|
+
defaultMessage: "More document actions"
|
1775
|
+
})
|
1864
1776
|
}
|
1865
|
-
)
|
1866
|
-
|
1867
|
-
|
1777
|
+
) : null
|
1778
|
+
] }),
|
1779
|
+
secondaryAction ? /* @__PURE__ */ jsx(
|
1780
|
+
DocumentActionButton,
|
1781
|
+
{
|
1782
|
+
...secondaryAction,
|
1783
|
+
variant: secondaryAction.variant || "secondary"
|
1868
1784
|
}
|
1869
|
-
|
1870
|
-
};
|
1785
|
+
) : null
|
1786
|
+
] });
|
1871
1787
|
};
|
1872
|
-
|
1873
|
-
const
|
1874
|
-
activeTab,
|
1875
|
-
documentId,
|
1876
|
-
model,
|
1877
|
-
collectionType
|
1878
|
-
}) => {
|
1879
|
-
const navigate = useNavigate();
|
1788
|
+
const DocumentActionButton = (action) => {
|
1789
|
+
const [dialogId, setDialogId] = React.useState(null);
|
1880
1790
|
const { toggleNotification } = useNotification();
|
1881
|
-
const
|
1882
|
-
|
1883
|
-
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
1889
|
-
|
1890
|
-
|
1891
|
-
|
1892
|
-
|
1893
|
-
|
1894
|
-
|
1895
|
-
|
1896
|
-
|
1897
|
-
|
1898
|
-
|
1899
|
-
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1900
|
-
* - the active tab is the published tab
|
1901
|
-
*/
|
1902
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1903
|
-
label: formatMessage({
|
1904
|
-
id: "content-manager.containers.Edit.save",
|
1905
|
-
defaultMessage: "Save"
|
1906
|
-
}),
|
1907
|
-
onClick: async () => {
|
1908
|
-
setSubmitting(true);
|
1909
|
-
try {
|
1910
|
-
if (activeTab !== "draft") {
|
1911
|
-
const { errors } = await validate();
|
1912
|
-
if (errors) {
|
1913
|
-
toggleNotification({
|
1914
|
-
type: "danger",
|
1915
|
-
message: formatMessage({
|
1916
|
-
id: "content-manager.validation.error",
|
1917
|
-
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1918
|
-
})
|
1919
|
-
});
|
1920
|
-
return;
|
1921
|
-
}
|
1922
|
-
}
|
1923
|
-
if (isCloning) {
|
1924
|
-
const res = await clone(
|
1925
|
-
{
|
1926
|
-
model,
|
1927
|
-
documentId: cloneMatch.params.origin,
|
1928
|
-
params
|
1929
|
-
},
|
1930
|
-
document
|
1931
|
-
);
|
1932
|
-
if ("data" in res) {
|
1933
|
-
navigate(
|
1934
|
-
{
|
1935
|
-
pathname: `../${res.data.documentId}`,
|
1936
|
-
search: rawQuery
|
1937
|
-
},
|
1938
|
-
{ relative: "path" }
|
1939
|
-
);
|
1940
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1941
|
-
setErrors(formatValidationErrors(res.error));
|
1942
|
-
}
|
1943
|
-
} else if (documentId || collectionType === SINGLE_TYPES) {
|
1944
|
-
const res = await update(
|
1945
|
-
{
|
1946
|
-
collectionType,
|
1947
|
-
model,
|
1948
|
-
documentId,
|
1949
|
-
params
|
1950
|
-
},
|
1951
|
-
document
|
1952
|
-
);
|
1953
|
-
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1954
|
-
setErrors(formatValidationErrors(res.error));
|
1955
|
-
} else {
|
1956
|
-
resetForm();
|
1957
|
-
}
|
1958
|
-
} else {
|
1959
|
-
const res = await create(
|
1960
|
-
{
|
1961
|
-
model,
|
1962
|
-
params
|
1963
|
-
},
|
1964
|
-
document
|
1965
|
-
);
|
1966
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1967
|
-
navigate(
|
1968
|
-
{
|
1969
|
-
pathname: `../${res.data.documentId}`,
|
1970
|
-
search: rawQuery
|
1971
|
-
},
|
1972
|
-
{ replace: true, relative: "path" }
|
1973
|
-
);
|
1974
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1975
|
-
setErrors(formatValidationErrors(res.error));
|
1976
|
-
}
|
1977
|
-
}
|
1978
|
-
} finally {
|
1979
|
-
setSubmitting(false);
|
1791
|
+
const handleClick = (action2) => async (e) => {
|
1792
|
+
const { onClick = () => false, dialog, id } = action2;
|
1793
|
+
const muteDialog = await onClick(e);
|
1794
|
+
if (dialog && !muteDialog) {
|
1795
|
+
switch (dialog.type) {
|
1796
|
+
case "notification":
|
1797
|
+
toggleNotification({
|
1798
|
+
title: dialog.title,
|
1799
|
+
message: dialog.content,
|
1800
|
+
type: dialog.status,
|
1801
|
+
timeout: dialog.timeout,
|
1802
|
+
onClose: dialog.onClose
|
1803
|
+
});
|
1804
|
+
break;
|
1805
|
+
case "dialog":
|
1806
|
+
case "modal":
|
1807
|
+
e.preventDefault();
|
1808
|
+
setDialogId(id);
|
1980
1809
|
}
|
1981
1810
|
}
|
1982
1811
|
};
|
1812
|
+
const handleClose = () => {
|
1813
|
+
setDialogId(null);
|
1814
|
+
};
|
1815
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
1816
|
+
/* @__PURE__ */ jsx(
|
1817
|
+
Button,
|
1818
|
+
{
|
1819
|
+
flex: "auto",
|
1820
|
+
startIcon: action.icon,
|
1821
|
+
disabled: action.disabled,
|
1822
|
+
onClick: handleClick(action),
|
1823
|
+
justifyContent: "center",
|
1824
|
+
variant: action.variant || "default",
|
1825
|
+
paddingTop: "7px",
|
1826
|
+
paddingBottom: "7px",
|
1827
|
+
children: action.label
|
1828
|
+
}
|
1829
|
+
),
|
1830
|
+
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
|
1831
|
+
DocumentActionConfirmDialog,
|
1832
|
+
{
|
1833
|
+
...action.dialog,
|
1834
|
+
variant: action.dialog?.variant ?? action.variant,
|
1835
|
+
isOpen: dialogId === action.id,
|
1836
|
+
onClose: handleClose
|
1837
|
+
}
|
1838
|
+
) : null,
|
1839
|
+
action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
|
1840
|
+
DocumentActionModal,
|
1841
|
+
{
|
1842
|
+
...action.dialog,
|
1843
|
+
onModalClose: handleClose,
|
1844
|
+
isOpen: dialogId === action.id
|
1845
|
+
}
|
1846
|
+
) : null
|
1847
|
+
] });
|
1983
1848
|
};
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
1988
|
-
|
1989
|
-
const UnpublishAction$1 = ({
|
1990
|
-
activeTab,
|
1991
|
-
documentId,
|
1992
|
-
model,
|
1993
|
-
collectionType,
|
1994
|
-
document
|
1849
|
+
const DocumentActionsMenu = ({
|
1850
|
+
actions: actions2,
|
1851
|
+
children,
|
1852
|
+
label,
|
1853
|
+
variant = "tertiary"
|
1995
1854
|
}) => {
|
1855
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
1856
|
+
const [dialogId, setDialogId] = React.useState(null);
|
1996
1857
|
const { formatMessage } = useIntl();
|
1997
|
-
const { schema } = useDoc();
|
1998
|
-
const canPublish = useDocumentRBAC("UnpublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1999
|
-
const { unpublish } = useDocumentActions();
|
2000
|
-
const [{ query }] = useQueryParams();
|
2001
|
-
const params = React.useMemo(() => buildValidParams(query), [query]);
|
2002
1858
|
const { toggleNotification } = useNotification();
|
2003
|
-
const
|
2004
|
-
const
|
2005
|
-
|
2006
|
-
|
2007
|
-
|
2008
|
-
|
2009
|
-
|
2010
|
-
}
|
2011
|
-
return {
|
2012
|
-
disabled: !canPublish || activeTab === "published" || document?.status !== "published" && document?.status !== "modified",
|
2013
|
-
label: formatMessage({
|
2014
|
-
id: "app.utils.unpublish",
|
2015
|
-
defaultMessage: "Unpublish"
|
2016
|
-
}),
|
2017
|
-
icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
|
2018
|
-
onClick: async () => {
|
2019
|
-
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
2020
|
-
if (!documentId) {
|
2021
|
-
console.error(
|
2022
|
-
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2023
|
-
);
|
1859
|
+
const isDisabled = actions2.every((action) => action.disabled) || actions2.length === 0;
|
1860
|
+
const handleClick = (action) => async (e) => {
|
1861
|
+
const { onClick = () => false, dialog, id } = action;
|
1862
|
+
const muteDialog = await onClick(e);
|
1863
|
+
if (dialog && !muteDialog) {
|
1864
|
+
switch (dialog.type) {
|
1865
|
+
case "notification":
|
2024
1866
|
toggleNotification({
|
2025
|
-
|
2026
|
-
|
2027
|
-
|
2028
|
-
|
2029
|
-
|
1867
|
+
title: dialog.title,
|
1868
|
+
message: dialog.content,
|
1869
|
+
type: dialog.status,
|
1870
|
+
timeout: dialog.timeout,
|
1871
|
+
onClose: dialog.onClose
|
2030
1872
|
});
|
2031
|
-
|
2032
|
-
|
1873
|
+
break;
|
1874
|
+
case "dialog":
|
1875
|
+
case "modal":
|
1876
|
+
setDialogId(id);
|
2033
1877
|
}
|
2034
|
-
|
2035
|
-
|
2036
|
-
|
2037
|
-
|
2038
|
-
|
2039
|
-
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
2048
|
-
|
2049
|
-
|
2050
|
-
|
2051
|
-
|
2052
|
-
|
1878
|
+
}
|
1879
|
+
};
|
1880
|
+
const handleClose = () => {
|
1881
|
+
setDialogId(null);
|
1882
|
+
setIsOpen(false);
|
1883
|
+
};
|
1884
|
+
return /* @__PURE__ */ jsxs(Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1885
|
+
/* @__PURE__ */ jsxs(
|
1886
|
+
Menu.Trigger,
|
1887
|
+
{
|
1888
|
+
disabled: isDisabled,
|
1889
|
+
size: "S",
|
1890
|
+
endIcon: null,
|
1891
|
+
paddingTop: "4px",
|
1892
|
+
paddingLeft: "7px",
|
1893
|
+
paddingRight: "7px",
|
1894
|
+
variant,
|
1895
|
+
children: [
|
1896
|
+
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
1897
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1898
|
+
id: "content-manager.containers.edit.panels.default.more-actions",
|
1899
|
+
defaultMessage: "More document actions"
|
2053
1900
|
}) })
|
2054
|
-
]
|
2055
|
-
|
2056
|
-
|
2057
|
-
|
2058
|
-
|
2059
|
-
|
2060
|
-
|
2061
|
-
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2062
|
-
defaultMessage: "Choose an option to unpublish the document."
|
2063
|
-
}),
|
2064
|
-
onValueChange: handleChange,
|
2065
|
-
children: [
|
2066
|
-
/* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2067
|
-
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2068
|
-
defaultMessage: "Keep draft"
|
2069
|
-
}) }),
|
2070
|
-
/* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2071
|
-
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2072
|
-
defaultMessage: "Replace draft"
|
2073
|
-
}) })
|
2074
|
-
]
|
2075
|
-
}
|
2076
|
-
)
|
2077
|
-
] }),
|
2078
|
-
onConfirm: async () => {
|
2079
|
-
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2080
|
-
console.error(
|
2081
|
-
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2082
|
-
);
|
2083
|
-
toggleNotification({
|
2084
|
-
message: formatMessage({
|
2085
|
-
id: "content-manager.actions.unpublish.error",
|
2086
|
-
defaultMessage: "An error occurred while trying to unpublish the document."
|
2087
|
-
}),
|
2088
|
-
type: "danger"
|
2089
|
-
});
|
2090
|
-
}
|
2091
|
-
await unpublish(
|
1901
|
+
]
|
1902
|
+
}
|
1903
|
+
),
|
1904
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1905
|
+
actions2.map((action) => {
|
1906
|
+
return /* @__PURE__ */ jsx(
|
1907
|
+
Menu.Item,
|
2092
1908
|
{
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
1909
|
+
disabled: action.disabled,
|
1910
|
+
onSelect: handleClick(action),
|
1911
|
+
display: "block",
|
1912
|
+
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
|
1913
|
+
/* @__PURE__ */ jsxs(
|
1914
|
+
Flex,
|
1915
|
+
{
|
1916
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1917
|
+
gap: 2,
|
1918
|
+
tag: "span",
|
1919
|
+
children: [
|
1920
|
+
/* @__PURE__ */ jsx(
|
1921
|
+
Flex,
|
1922
|
+
{
|
1923
|
+
tag: "span",
|
1924
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1925
|
+
children: action.icon
|
1926
|
+
}
|
1927
|
+
),
|
1928
|
+
action.label
|
1929
|
+
]
|
1930
|
+
}
|
1931
|
+
),
|
1932
|
+
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
|
1933
|
+
Flex,
|
1934
|
+
{
|
1935
|
+
alignItems: "center",
|
1936
|
+
background: "alternative100",
|
1937
|
+
borderStyle: "solid",
|
1938
|
+
borderColor: "alternative200",
|
1939
|
+
borderWidth: "1px",
|
1940
|
+
height: 5,
|
1941
|
+
paddingLeft: 2,
|
1942
|
+
paddingRight: 2,
|
1943
|
+
hasRadius: true,
|
1944
|
+
color: "alternative600",
|
1945
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1946
|
+
}
|
1947
|
+
)
|
1948
|
+
] })
|
2097
1949
|
},
|
2098
|
-
|
1950
|
+
action.id
|
2099
1951
|
);
|
2100
|
-
}
|
2101
|
-
|
2102
|
-
|
2103
|
-
|
1952
|
+
}),
|
1953
|
+
children
|
1954
|
+
] }),
|
1955
|
+
actions2.map((action) => {
|
1956
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
1957
|
+
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
|
1958
|
+
DocumentActionConfirmDialog,
|
1959
|
+
{
|
1960
|
+
...action.dialog,
|
1961
|
+
variant: action.variant,
|
1962
|
+
isOpen: dialogId === action.id,
|
1963
|
+
onClose: handleClose
|
1964
|
+
}
|
1965
|
+
) : null,
|
1966
|
+
action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
|
1967
|
+
DocumentActionModal,
|
1968
|
+
{
|
1969
|
+
...action.dialog,
|
1970
|
+
onModalClose: handleClose,
|
1971
|
+
isOpen: dialogId === action.id
|
1972
|
+
}
|
1973
|
+
) : null
|
1974
|
+
] }, action.id);
|
1975
|
+
})
|
1976
|
+
] });
|
1977
|
+
};
|
1978
|
+
const convertActionVariantToColor = (variant = "secondary") => {
|
1979
|
+
switch (variant) {
|
1980
|
+
case "danger":
|
1981
|
+
return "danger600";
|
1982
|
+
case "secondary":
|
1983
|
+
return void 0;
|
1984
|
+
case "success":
|
1985
|
+
return "success600";
|
1986
|
+
default:
|
1987
|
+
return "primary600";
|
1988
|
+
}
|
1989
|
+
};
|
1990
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1991
|
+
switch (variant) {
|
1992
|
+
case "danger":
|
1993
|
+
return "danger600";
|
1994
|
+
case "secondary":
|
1995
|
+
return "neutral500";
|
1996
|
+
case "success":
|
1997
|
+
return "success600";
|
1998
|
+
default:
|
1999
|
+
return "primary600";
|
2000
|
+
}
|
2001
|
+
};
|
2002
|
+
const DocumentActionConfirmDialog = ({
|
2003
|
+
onClose,
|
2004
|
+
onCancel,
|
2005
|
+
onConfirm,
|
2006
|
+
title,
|
2007
|
+
content,
|
2008
|
+
isOpen,
|
2009
|
+
variant = "secondary"
|
2010
|
+
}) => {
|
2011
|
+
const { formatMessage } = useIntl();
|
2012
|
+
const handleClose = async () => {
|
2013
|
+
if (onCancel) {
|
2014
|
+
await onCancel();
|
2015
|
+
}
|
2016
|
+
onClose();
|
2017
|
+
};
|
2018
|
+
const handleConfirm = async () => {
|
2019
|
+
if (onConfirm) {
|
2020
|
+
await onConfirm();
|
2021
|
+
}
|
2022
|
+
onClose();
|
2104
2023
|
};
|
2024
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2025
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2026
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
2027
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
2028
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
2029
|
+
id: "app.components.Button.cancel",
|
2030
|
+
defaultMessage: "Cancel"
|
2031
|
+
}) }) }),
|
2032
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
2033
|
+
id: "app.components.Button.confirm",
|
2034
|
+
defaultMessage: "Confirm"
|
2035
|
+
}) })
|
2036
|
+
] })
|
2037
|
+
] }) });
|
2105
2038
|
};
|
2106
|
-
|
2107
|
-
|
2039
|
+
const DocumentActionModal = ({
|
2040
|
+
isOpen,
|
2041
|
+
title,
|
2042
|
+
onClose,
|
2043
|
+
footer: Footer,
|
2044
|
+
content: Content,
|
2045
|
+
onModalClose
|
2046
|
+
}) => {
|
2047
|
+
const handleClose = () => {
|
2048
|
+
if (onClose) {
|
2049
|
+
onClose();
|
2050
|
+
}
|
2051
|
+
onModalClose();
|
2052
|
+
};
|
2053
|
+
return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
2054
|
+
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
|
2055
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
|
2056
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
2057
|
+
] }) });
|
2058
|
+
};
|
2059
|
+
const PublishAction$1 = ({
|
2108
2060
|
activeTab,
|
2109
2061
|
documentId,
|
2110
2062
|
model,
|
2111
2063
|
collectionType,
|
2064
|
+
meta,
|
2112
2065
|
document
|
2113
2066
|
}) => {
|
2114
|
-
const { formatMessage } = useIntl();
|
2115
2067
|
const { schema } = useDoc();
|
2116
|
-
const
|
2117
|
-
const {
|
2118
|
-
const
|
2119
|
-
const
|
2120
|
-
if (!schema?.options?.draftAndPublish) {
|
2121
|
-
return null;
|
2122
|
-
}
|
2123
|
-
return {
|
2124
|
-
disabled: !canUpdate || activeTab === "published" || document?.status !== "modified",
|
2125
|
-
label: formatMessage({
|
2126
|
-
id: "content-manager.actions.discard.label",
|
2127
|
-
defaultMessage: "Discard changes"
|
2128
|
-
}),
|
2129
|
-
icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
|
2130
|
-
position: ["panel", "table-row"],
|
2131
|
-
variant: "danger",
|
2132
|
-
dialog: {
|
2133
|
-
type: "dialog",
|
2134
|
-
title: formatMessage({
|
2135
|
-
id: "app.components.ConfirmDialog.title",
|
2136
|
-
defaultMessage: "Confirmation"
|
2137
|
-
}),
|
2138
|
-
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
2139
|
-
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2140
|
-
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2141
|
-
id: "content-manager.actions.discard.dialog.body",
|
2142
|
-
defaultMessage: "Are you sure?"
|
2143
|
-
}) })
|
2144
|
-
] }),
|
2145
|
-
onConfirm: async () => {
|
2146
|
-
await discard({
|
2147
|
-
collectionType,
|
2148
|
-
model,
|
2149
|
-
documentId,
|
2150
|
-
params
|
2151
|
-
});
|
2152
|
-
}
|
2153
|
-
}
|
2154
|
-
};
|
2155
|
-
};
|
2156
|
-
DiscardAction.type = "discard";
|
2157
|
-
const StyledCrossCircle = styled(CrossCircle)`
|
2158
|
-
path {
|
2159
|
-
fill: currentColor;
|
2160
|
-
}
|
2161
|
-
`;
|
2162
|
-
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2163
|
-
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2164
|
-
const RelativeTime = React.forwardRef(
|
2165
|
-
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
2166
|
-
const { formatRelativeTime, formatDate, formatTime } = useIntl();
|
2167
|
-
const interval = intervalToDuration({
|
2168
|
-
start: timestamp,
|
2169
|
-
end: Date.now()
|
2170
|
-
// see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
|
2171
|
-
});
|
2172
|
-
const unit = intervals.find((intervalUnit) => {
|
2173
|
-
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2174
|
-
});
|
2175
|
-
const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
|
2176
|
-
const customInterval = customIntervals.find(
|
2177
|
-
(custom) => interval[custom.unit] < custom.threshold
|
2178
|
-
);
|
2179
|
-
const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
|
2180
|
-
return /* @__PURE__ */ jsx(
|
2181
|
-
"time",
|
2182
|
-
{
|
2183
|
-
ref: forwardedRef,
|
2184
|
-
dateTime: timestamp.toISOString(),
|
2185
|
-
role: "time",
|
2186
|
-
title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
|
2187
|
-
...restProps,
|
2188
|
-
children: displayText
|
2189
|
-
}
|
2190
|
-
);
|
2191
|
-
}
|
2192
|
-
);
|
2193
|
-
const getDisplayName = ({
|
2194
|
-
firstname,
|
2195
|
-
lastname,
|
2196
|
-
username,
|
2197
|
-
email
|
2198
|
-
} = {}) => {
|
2199
|
-
if (username) {
|
2200
|
-
return username;
|
2201
|
-
}
|
2202
|
-
if (firstname) {
|
2203
|
-
return `${firstname} ${lastname ?? ""}`.trim();
|
2204
|
-
}
|
2205
|
-
return email ?? "";
|
2206
|
-
};
|
2207
|
-
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2208
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2209
|
-
const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
|
2210
|
-
return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
|
2211
|
-
};
|
2212
|
-
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2213
|
-
const { formatMessage } = useIntl();
|
2068
|
+
const navigate = useNavigate();
|
2069
|
+
const { toggleNotification } = useNotification();
|
2070
|
+
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2071
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
2214
2072
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2215
|
-
const title = isCreating ? formatMessage({
|
2216
|
-
id: "content-manager.containers.edit.title.new",
|
2217
|
-
defaultMessage: "Create an entry"
|
2218
|
-
}) : documentTitle;
|
2219
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2220
|
-
/* @__PURE__ */ jsx(BackButton, {}),
|
2221
|
-
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2222
|
-
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2223
|
-
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2224
|
-
] }),
|
2225
|
-
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2226
|
-
] });
|
2227
|
-
};
|
2228
|
-
const HeaderToolbar = () => {
|
2229
2073
|
const { formatMessage } = useIntl();
|
2230
|
-
const
|
2074
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
2075
|
+
const { publish } = useDocumentActions();
|
2231
2076
|
const [
|
2232
|
-
|
2233
|
-
|
2077
|
+
countDraftRelations,
|
2078
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2079
|
+
] = useLazyGetDraftRelationCountQuery();
|
2080
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
2081
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
2082
|
+
const [{ query, rawQuery }] = useQueryParams();
|
2083
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
2084
|
+
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
2085
|
+
const setSubmitting = useForm("PublishAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
2086
|
+
const isSubmitting = useForm("PublishAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
2087
|
+
const validate = useForm("PublishAction", (state) => state.validate);
|
2088
|
+
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
2089
|
+
const formValues = useForm("PublishAction", ({ values }) => values);
|
2090
|
+
React.useEffect(() => {
|
2091
|
+
if (isErrorDraftRelations) {
|
2092
|
+
toggleNotification({
|
2093
|
+
type: "danger",
|
2094
|
+
message: formatMessage({
|
2095
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2096
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2097
|
+
})
|
2098
|
+
});
|
2234
2099
|
}
|
2235
|
-
|
2236
|
-
|
2237
|
-
|
2238
|
-
|
2239
|
-
|
2240
|
-
|
2241
|
-
|
2242
|
-
|
2243
|
-
activeTab: status,
|
2244
|
-
model,
|
2245
|
-
documentId: id,
|
2246
|
-
document: isCloning ? void 0 : document,
|
2247
|
-
meta: isCloning ? void 0 : meta,
|
2248
|
-
collectionType
|
2249
|
-
},
|
2250
|
-
descriptions: plugins["content-manager"].apis.getHeaderActions(),
|
2251
|
-
children: (actions2) => {
|
2252
|
-
if (actions2.length > 0) {
|
2253
|
-
return /* @__PURE__ */ jsx(HeaderActions, { actions: actions2 });
|
2254
|
-
} else {
|
2255
|
-
return null;
|
2256
|
-
}
|
2100
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2101
|
+
React.useEffect(() => {
|
2102
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2103
|
+
const extractDraftRelations = (data) => {
|
2104
|
+
const relations = data.connect || [];
|
2105
|
+
relations.forEach((relation) => {
|
2106
|
+
if (relation.status === "draft") {
|
2107
|
+
localDraftRelations.add(relation.id);
|
2257
2108
|
}
|
2258
|
-
}
|
2259
|
-
|
2260
|
-
|
2261
|
-
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
documentId: id,
|
2267
|
-
document: isCloning ? void 0 : document,
|
2268
|
-
meta: isCloning ? void 0 : meta,
|
2269
|
-
collectionType
|
2270
|
-
},
|
2271
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2272
|
-
children: (actions2) => {
|
2273
|
-
const headerActions = actions2.filter((action) => {
|
2274
|
-
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2275
|
-
return positions.includes("header");
|
2276
|
-
});
|
2277
|
-
return /* @__PURE__ */ jsx(
|
2278
|
-
DocumentActionsMenu,
|
2279
|
-
{
|
2280
|
-
actions: headerActions,
|
2281
|
-
label: formatMessage({
|
2282
|
-
id: "content-manager.containers.edit.header.more-actions",
|
2283
|
-
defaultMessage: "More actions"
|
2284
|
-
}),
|
2285
|
-
children: /* @__PURE__ */ jsx(Information, { activeTab: status })
|
2286
|
-
}
|
2287
|
-
);
|
2109
|
+
});
|
2110
|
+
};
|
2111
|
+
const traverseAndExtract = (data) => {
|
2112
|
+
Object.entries(data).forEach(([key, value]) => {
|
2113
|
+
if (key === "connect" && Array.isArray(value)) {
|
2114
|
+
extractDraftRelations({ connect: value });
|
2115
|
+
} else if (typeof value === "object" && value !== null) {
|
2116
|
+
traverseAndExtract(value);
|
2288
2117
|
}
|
2118
|
+
});
|
2119
|
+
};
|
2120
|
+
if (!documentId || modified) {
|
2121
|
+
traverseAndExtract(formValues);
|
2122
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2123
|
+
}
|
2124
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2125
|
+
React.useEffect(() => {
|
2126
|
+
if (!document || !document.documentId || isListView) {
|
2127
|
+
return;
|
2128
|
+
}
|
2129
|
+
const fetchDraftRelationsCount = async () => {
|
2130
|
+
const { data, error } = await countDraftRelations({
|
2131
|
+
collectionType,
|
2132
|
+
model,
|
2133
|
+
documentId,
|
2134
|
+
params
|
2135
|
+
});
|
2136
|
+
if (error) {
|
2137
|
+
throw error;
|
2289
2138
|
}
|
2290
|
-
|
2291
|
-
|
2292
|
-
}
|
2293
|
-
|
2294
|
-
|
2295
|
-
|
2296
|
-
|
2139
|
+
if (data) {
|
2140
|
+
setServerCountOfDraftRelations(data.data);
|
2141
|
+
}
|
2142
|
+
};
|
2143
|
+
fetchDraftRelationsCount();
|
2144
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2145
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
2146
|
+
if (!schema?.options?.draftAndPublish) {
|
2297
2147
|
return null;
|
2298
2148
|
}
|
2299
|
-
const
|
2300
|
-
|
2301
|
-
|
2302
|
-
|
2303
|
-
|
2304
|
-
|
2305
|
-
|
2306
|
-
|
2307
|
-
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2149
|
+
const performPublish = async () => {
|
2150
|
+
setSubmitting(true);
|
2151
|
+
try {
|
2152
|
+
const { errors } = await validate(true, {
|
2153
|
+
status: "published"
|
2154
|
+
});
|
2155
|
+
if (errors) {
|
2156
|
+
toggleNotification({
|
2157
|
+
type: "danger",
|
2158
|
+
message: formatMessage({
|
2159
|
+
id: "content-manager.validation.error",
|
2160
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2161
|
+
})
|
2162
|
+
});
|
2163
|
+
return;
|
2164
|
+
}
|
2165
|
+
const res = await publish(
|
2311
2166
|
{
|
2312
|
-
|
2313
|
-
|
2167
|
+
collectionType,
|
2168
|
+
model,
|
2169
|
+
documentId,
|
2170
|
+
params
|
2314
2171
|
},
|
2315
|
-
|
2316
|
-
|
2317
|
-
|
2318
|
-
|
2319
|
-
|
2320
|
-
|
2172
|
+
formValues
|
2173
|
+
);
|
2174
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2175
|
+
navigate({
|
2176
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2177
|
+
search: rawQuery
|
2178
|
+
});
|
2179
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2180
|
+
setErrors(formatValidationErrors(res.error));
|
2181
|
+
}
|
2182
|
+
} finally {
|
2183
|
+
setSubmitting(false);
|
2184
|
+
}
|
2185
|
+
};
|
2186
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2187
|
+
const enableDraftRelationsCount = false;
|
2188
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
2189
|
+
return {
|
2190
|
+
/**
|
2191
|
+
* Disabled when:
|
2192
|
+
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
2193
|
+
* - the form is submitting
|
2194
|
+
* - the active tab is the published tab
|
2195
|
+
* - the document is already published & not modified
|
2196
|
+
* - the document is being created & not modified
|
2197
|
+
* - the user doesn't have the permission to publish
|
2198
|
+
*/
|
2199
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
2200
|
+
label: formatMessage({
|
2201
|
+
id: "app.utils.publish",
|
2202
|
+
defaultMessage: "Publish"
|
2203
|
+
}),
|
2204
|
+
onClick: async () => {
|
2205
|
+
await performPublish();
|
2321
2206
|
},
|
2322
|
-
{
|
2323
|
-
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2207
|
+
dialog: hasDraftRelations ? {
|
2208
|
+
type: "dialog",
|
2209
|
+
variant: "danger",
|
2210
|
+
footer: null,
|
2211
|
+
title: formatMessage({
|
2212
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2213
|
+
defaultMessage: "Confirmation"
|
2327
2214
|
}),
|
2328
|
-
|
2215
|
+
content: formatMessage(
|
2329
2216
|
{
|
2330
|
-
id:
|
2331
|
-
defaultMessage:
|
2217
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2218
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2332
2219
|
},
|
2333
2220
|
{
|
2334
|
-
|
2335
|
-
RelativeTime,
|
2336
|
-
{
|
2337
|
-
timestamp: new Date(createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME])
|
2338
|
-
}
|
2339
|
-
),
|
2340
|
-
isAnonymous: !updator,
|
2341
|
-
author: updator
|
2221
|
+
count: totalDraftRelations
|
2342
2222
|
}
|
2343
|
-
)
|
2344
|
-
|
2345
|
-
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2223
|
+
),
|
2224
|
+
onConfirm: async () => {
|
2225
|
+
await performPublish();
|
2226
|
+
}
|
2227
|
+
} : void 0
|
2228
|
+
};
|
2229
|
+
};
|
2230
|
+
PublishAction$1.type = "publish";
|
2231
|
+
const UpdateAction = ({
|
2232
|
+
activeTab,
|
2233
|
+
documentId,
|
2234
|
+
model,
|
2235
|
+
collectionType
|
2236
|
+
}) => {
|
2237
|
+
const navigate = useNavigate();
|
2238
|
+
const { toggleNotification } = useNotification();
|
2239
|
+
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2240
|
+
const cloneMatch = useMatch(CLONE_PATH);
|
2241
|
+
const isCloning = cloneMatch !== null;
|
2242
|
+
const { formatMessage } = useIntl();
|
2243
|
+
const { create, update, clone } = useDocumentActions();
|
2244
|
+
const [{ query, rawQuery }] = useQueryParams();
|
2245
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
2246
|
+
const isSubmitting = useForm("UpdateAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
2247
|
+
const modified = useForm("UpdateAction", ({ modified: modified2 }) => modified2);
|
2248
|
+
const setSubmitting = useForm("UpdateAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
2249
|
+
const document = useForm("UpdateAction", ({ values }) => values);
|
2250
|
+
const validate = useForm("UpdateAction", (state) => state.validate);
|
2251
|
+
const setErrors = useForm("UpdateAction", (state) => state.setErrors);
|
2252
|
+
const resetForm = useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
2253
|
+
return {
|
2254
|
+
/**
|
2255
|
+
* Disabled when:
|
2256
|
+
* - the form is submitting
|
2257
|
+
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
2258
|
+
* - the active tab is the published tab
|
2259
|
+
*/
|
2260
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
2261
|
+
label: formatMessage({
|
2262
|
+
id: "content-manager.containers.Edit.save",
|
2263
|
+
defaultMessage: "Save"
|
2264
|
+
}),
|
2265
|
+
onClick: async () => {
|
2266
|
+
setSubmitting(true);
|
2267
|
+
try {
|
2268
|
+
const { errors } = await validate(true, {
|
2269
|
+
status: "draft"
|
2270
|
+
});
|
2271
|
+
if (errors) {
|
2272
|
+
toggleNotification({
|
2273
|
+
type: "danger",
|
2274
|
+
message: formatMessage({
|
2275
|
+
id: "content-manager.validation.error",
|
2276
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2277
|
+
})
|
2278
|
+
});
|
2279
|
+
return;
|
2365
2280
|
}
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2387
|
-
|
2281
|
+
if (isCloning) {
|
2282
|
+
const res = await clone(
|
2283
|
+
{
|
2284
|
+
model,
|
2285
|
+
documentId: cloneMatch.params.origin,
|
2286
|
+
params
|
2287
|
+
},
|
2288
|
+
document
|
2289
|
+
);
|
2290
|
+
if ("data" in res) {
|
2291
|
+
navigate(
|
2292
|
+
{
|
2293
|
+
pathname: `../${res.data.documentId}`,
|
2294
|
+
search: rawQuery
|
2295
|
+
},
|
2296
|
+
{ relative: "path" }
|
2297
|
+
);
|
2298
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2299
|
+
setErrors(formatValidationErrors(res.error));
|
2300
|
+
}
|
2301
|
+
} else if (documentId || collectionType === SINGLE_TYPES) {
|
2302
|
+
const res = await update(
|
2303
|
+
{
|
2304
|
+
collectionType,
|
2305
|
+
model,
|
2306
|
+
documentId,
|
2307
|
+
params
|
2308
|
+
},
|
2309
|
+
document
|
2310
|
+
);
|
2311
|
+
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2312
|
+
setErrors(formatValidationErrors(res.error));
|
2313
|
+
} else {
|
2314
|
+
resetForm();
|
2315
|
+
}
|
2316
|
+
} else {
|
2317
|
+
const res = await create(
|
2318
|
+
{
|
2319
|
+
model,
|
2320
|
+
params
|
2321
|
+
},
|
2322
|
+
document
|
2323
|
+
);
|
2324
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2325
|
+
navigate(
|
2326
|
+
{
|
2327
|
+
pathname: `../${res.data.documentId}`,
|
2328
|
+
search: rawQuery
|
2329
|
+
},
|
2330
|
+
{ replace: true, relative: "path" }
|
2331
|
+
);
|
2332
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2333
|
+
setErrors(formatValidationErrors(res.error));
|
2334
|
+
}
|
2335
|
+
}
|
2336
|
+
} finally {
|
2337
|
+
setSubmitting(false);
|
2338
|
+
}
|
2388
2339
|
}
|
2389
|
-
|
2340
|
+
};
|
2390
2341
|
};
|
2391
|
-
|
2392
|
-
|
2393
|
-
|
2394
|
-
|
2395
|
-
SingleSelect,
|
2396
|
-
{
|
2397
|
-
size: "S",
|
2398
|
-
disabled: action.disabled,
|
2399
|
-
"aria-label": action.label,
|
2400
|
-
onChange: action.onSelect,
|
2401
|
-
value: action.value,
|
2402
|
-
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2403
|
-
},
|
2404
|
-
action.id
|
2405
|
-
);
|
2406
|
-
} else {
|
2407
|
-
return null;
|
2408
|
-
}
|
2409
|
-
}) });
|
2342
|
+
UpdateAction.type = "update";
|
2343
|
+
const UNPUBLISH_DRAFT_OPTIONS = {
|
2344
|
+
KEEP: "keep",
|
2345
|
+
DISCARD: "discard"
|
2410
2346
|
};
|
2411
|
-
const
|
2412
|
-
|
2347
|
+
const UnpublishAction$1 = ({
|
2348
|
+
activeTab,
|
2349
|
+
documentId,
|
2350
|
+
model,
|
2351
|
+
collectionType,
|
2352
|
+
document
|
2353
|
+
}) => {
|
2413
2354
|
const { formatMessage } = useIntl();
|
2414
|
-
|
2415
|
-
|
2416
|
-
|
2417
|
-
|
2418
|
-
|
2419
|
-
|
2420
|
-
|
2421
|
-
|
2422
|
-
|
2423
|
-
|
2355
|
+
const { schema } = useDoc();
|
2356
|
+
const canPublish = useDocumentRBAC("UnpublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
2357
|
+
const { unpublish } = useDocumentActions();
|
2358
|
+
const [{ query }] = useQueryParams();
|
2359
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
2360
|
+
const { toggleNotification } = useNotification();
|
2361
|
+
const [shouldKeepDraft, setShouldKeepDraft] = React.useState(true);
|
2362
|
+
const isDocumentModified = document?.status === "modified";
|
2363
|
+
const handleChange = (value) => {
|
2364
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
2424
2365
|
};
|
2425
|
-
|
2426
|
-
|
2427
|
-
|
2428
|
-
const navigate = useNavigate();
|
2429
|
-
const { formatMessage } = useIntl();
|
2366
|
+
if (!schema?.options?.draftAndPublish) {
|
2367
|
+
return null;
|
2368
|
+
}
|
2430
2369
|
return {
|
2370
|
+
disabled: !canPublish || activeTab === "published" || document?.status !== "published" && document?.status !== "modified",
|
2431
2371
|
label: formatMessage({
|
2432
|
-
id: "
|
2433
|
-
defaultMessage: "
|
2372
|
+
id: "app.utils.unpublish",
|
2373
|
+
defaultMessage: "Unpublish"
|
2434
2374
|
}),
|
2435
|
-
icon: /* @__PURE__ */ jsx(
|
2436
|
-
onClick: () => {
|
2437
|
-
|
2375
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2376
|
+
onClick: async () => {
|
2377
|
+
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
2378
|
+
if (!documentId) {
|
2379
|
+
console.error(
|
2380
|
+
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2381
|
+
);
|
2382
|
+
toggleNotification({
|
2383
|
+
message: formatMessage({
|
2384
|
+
id: "content-manager.actions.unpublish.error",
|
2385
|
+
defaultMessage: "An error occurred while trying to unpublish the document."
|
2386
|
+
}),
|
2387
|
+
type: "danger"
|
2388
|
+
});
|
2389
|
+
}
|
2390
|
+
return;
|
2391
|
+
}
|
2392
|
+
await unpublish({
|
2393
|
+
collectionType,
|
2394
|
+
model,
|
2395
|
+
documentId,
|
2396
|
+
params
|
2397
|
+
});
|
2438
2398
|
},
|
2439
|
-
|
2399
|
+
dialog: isDocumentModified ? {
|
2400
|
+
type: "dialog",
|
2401
|
+
title: formatMessage({
|
2402
|
+
id: "app.components.ConfirmDialog.title",
|
2403
|
+
defaultMessage: "Confirmation"
|
2404
|
+
}),
|
2405
|
+
content: /* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
|
2406
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", direction: "column", gap: 2, children: [
|
2407
|
+
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2408
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2409
|
+
id: "content-manager.actions.unpublish.dialog.body",
|
2410
|
+
defaultMessage: "Are you sure?"
|
2411
|
+
}) })
|
2412
|
+
] }),
|
2413
|
+
/* @__PURE__ */ jsxs(
|
2414
|
+
Radio.Group,
|
2415
|
+
{
|
2416
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2417
|
+
name: "discard-options",
|
2418
|
+
"aria-label": formatMessage({
|
2419
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2420
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2421
|
+
}),
|
2422
|
+
onValueChange: handleChange,
|
2423
|
+
children: [
|
2424
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2425
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2426
|
+
defaultMessage: "Keep draft"
|
2427
|
+
}) }),
|
2428
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2429
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2430
|
+
defaultMessage: "Replace draft"
|
2431
|
+
}) })
|
2432
|
+
]
|
2433
|
+
}
|
2434
|
+
)
|
2435
|
+
] }),
|
2436
|
+
onConfirm: async () => {
|
2437
|
+
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2438
|
+
console.error(
|
2439
|
+
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2440
|
+
);
|
2441
|
+
toggleNotification({
|
2442
|
+
message: formatMessage({
|
2443
|
+
id: "content-manager.actions.unpublish.error",
|
2444
|
+
defaultMessage: "An error occurred while trying to unpublish the document."
|
2445
|
+
}),
|
2446
|
+
type: "danger"
|
2447
|
+
});
|
2448
|
+
}
|
2449
|
+
await unpublish(
|
2450
|
+
{
|
2451
|
+
collectionType,
|
2452
|
+
model,
|
2453
|
+
documentId,
|
2454
|
+
params
|
2455
|
+
},
|
2456
|
+
!shouldKeepDraft
|
2457
|
+
);
|
2458
|
+
}
|
2459
|
+
} : void 0,
|
2460
|
+
variant: "danger",
|
2461
|
+
position: ["panel", "table-row"]
|
2440
2462
|
};
|
2441
2463
|
};
|
2442
|
-
|
2443
|
-
const
|
2444
|
-
|
2464
|
+
UnpublishAction$1.type = "unpublish";
|
2465
|
+
const DiscardAction = ({
|
2466
|
+
activeTab,
|
2467
|
+
documentId,
|
2468
|
+
model,
|
2469
|
+
collectionType,
|
2470
|
+
document
|
2471
|
+
}) => {
|
2445
2472
|
const { formatMessage } = useIntl();
|
2446
|
-
const
|
2447
|
-
const
|
2448
|
-
const {
|
2449
|
-
const {
|
2450
|
-
const
|
2473
|
+
const { schema } = useDoc();
|
2474
|
+
const canUpdate = useDocumentRBAC("DiscardAction", ({ canUpdate: canUpdate2 }) => canUpdate2);
|
2475
|
+
const { discard } = useDocumentActions();
|
2476
|
+
const [{ query }] = useQueryParams();
|
2477
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
2478
|
+
if (!schema?.options?.draftAndPublish) {
|
2479
|
+
return null;
|
2480
|
+
}
|
2451
2481
|
return {
|
2452
|
-
disabled: !
|
2482
|
+
disabled: !canUpdate || activeTab === "published" || document?.status !== "modified",
|
2453
2483
|
label: formatMessage({
|
2454
|
-
id: "content-manager.actions.
|
2455
|
-
defaultMessage: "
|
2484
|
+
id: "content-manager.actions.discard.label",
|
2485
|
+
defaultMessage: "Discard changes"
|
2456
2486
|
}),
|
2457
|
-
icon: /* @__PURE__ */ jsx(
|
2487
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2488
|
+
position: ["panel", "table-row"],
|
2489
|
+
variant: "danger",
|
2458
2490
|
dialog: {
|
2459
2491
|
type: "dialog",
|
2460
2492
|
title: formatMessage({
|
@@ -2464,92 +2496,90 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2464
2496
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
2465
2497
|
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2466
2498
|
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2467
|
-
id: "content-manager.actions.
|
2499
|
+
id: "content-manager.actions.discard.dialog.body",
|
2468
2500
|
defaultMessage: "Are you sure?"
|
2469
2501
|
}) })
|
2470
2502
|
] }),
|
2471
2503
|
onConfirm: async () => {
|
2472
|
-
|
2473
|
-
|
2474
|
-
|
2475
|
-
|
2476
|
-
|
2477
|
-
|
2478
|
-
|
2479
|
-
|
2480
|
-
|
2481
|
-
|
2482
|
-
|
2483
|
-
|
2484
|
-
|
2485
|
-
|
2486
|
-
|
2487
|
-
|
2488
|
-
|
2489
|
-
|
2490
|
-
|
2491
|
-
|
2492
|
-
|
2493
|
-
|
2494
|
-
|
2495
|
-
|
2496
|
-
|
2497
|
-
|
2498
|
-
|
2499
|
-
|
2500
|
-
|
2501
|
-
|
2502
|
-
|
2503
|
-
|
2504
|
-
|
2504
|
+
await discard({
|
2505
|
+
collectionType,
|
2506
|
+
model,
|
2507
|
+
documentId,
|
2508
|
+
params
|
2509
|
+
});
|
2510
|
+
}
|
2511
|
+
}
|
2512
|
+
};
|
2513
|
+
};
|
2514
|
+
DiscardAction.type = "discard";
|
2515
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2516
|
+
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2517
|
+
const RelativeTime = React.forwardRef(
|
2518
|
+
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
2519
|
+
const { formatRelativeTime, formatDate, formatTime } = useIntl();
|
2520
|
+
const interval = intervalToDuration({
|
2521
|
+
start: timestamp,
|
2522
|
+
end: Date.now()
|
2523
|
+
// see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
|
2524
|
+
});
|
2525
|
+
const unit = intervals.find((intervalUnit) => {
|
2526
|
+
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2527
|
+
});
|
2528
|
+
const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
|
2529
|
+
const customInterval = customIntervals.find(
|
2530
|
+
(custom) => interval[custom.unit] < custom.threshold
|
2531
|
+
);
|
2532
|
+
const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
|
2533
|
+
return /* @__PURE__ */ jsx(
|
2534
|
+
"time",
|
2535
|
+
{
|
2536
|
+
ref: forwardedRef,
|
2537
|
+
dateTime: timestamp.toISOString(),
|
2538
|
+
role: "time",
|
2539
|
+
title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
|
2540
|
+
...restProps,
|
2541
|
+
children: displayText
|
2505
2542
|
}
|
2506
|
-
|
2507
|
-
|
2508
|
-
|
2509
|
-
|
2543
|
+
);
|
2544
|
+
}
|
2545
|
+
);
|
2546
|
+
const getDisplayName = ({
|
2547
|
+
firstname,
|
2548
|
+
lastname,
|
2549
|
+
username,
|
2550
|
+
email
|
2551
|
+
} = {}) => {
|
2552
|
+
if (username) {
|
2553
|
+
return username;
|
2554
|
+
}
|
2555
|
+
if (firstname) {
|
2556
|
+
return `${firstname} ${lastname ?? ""}`.trim();
|
2557
|
+
}
|
2558
|
+
return email ?? "";
|
2510
2559
|
};
|
2511
|
-
|
2512
|
-
const
|
2513
|
-
const
|
2514
|
-
|
2515
|
-
const [
|
2516
|
-
{
|
2517
|
-
query: { status }
|
2518
|
-
}
|
2519
|
-
] = useQueryParams({
|
2520
|
-
status: "draft"
|
2521
|
-
});
|
2522
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2523
|
-
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2524
|
-
const props = {
|
2525
|
-
activeTab: status,
|
2526
|
-
model,
|
2527
|
-
documentId: id,
|
2528
|
-
document: isCloning ? void 0 : document,
|
2529
|
-
meta: isCloning ? void 0 : meta,
|
2530
|
-
collectionType
|
2531
|
-
};
|
2532
|
-
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2533
|
-
DescriptionComponentRenderer,
|
2534
|
-
{
|
2535
|
-
props,
|
2536
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2537
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2538
|
-
}
|
2539
|
-
) });
|
2560
|
+
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2561
|
+
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2562
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2563
|
+
return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
|
2540
2564
|
};
|
2541
|
-
const
|
2565
|
+
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2542
2566
|
const { formatMessage } = useIntl();
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
|
2549
|
-
|
2567
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2568
|
+
const title = isCreating ? formatMessage({
|
2569
|
+
id: "content-manager.containers.edit.title.new",
|
2570
|
+
defaultMessage: "Create an entry"
|
2571
|
+
}) : documentTitle;
|
2572
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2573
|
+
/* @__PURE__ */ jsx(BackButton, {}),
|
2574
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2575
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2576
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2577
|
+
] }),
|
2578
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2579
|
+
] });
|
2550
2580
|
};
|
2551
|
-
|
2552
|
-
const
|
2581
|
+
const HeaderToolbar = () => {
|
2582
|
+
const { formatMessage } = useIntl();
|
2553
2583
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2554
2584
|
const [
|
2555
2585
|
{
|
@@ -2557,355 +2587,432 @@ const ActionsPanelContent = () => {
|
|
2557
2587
|
}
|
2558
2588
|
] = useQueryParams();
|
2559
2589
|
const { model, id, document, meta, collectionType } = useDoc();
|
2560
|
-
const plugins = useStrapiApp("
|
2561
|
-
|
2562
|
-
activeTab: status,
|
2563
|
-
model,
|
2564
|
-
documentId: id,
|
2565
|
-
document: isCloning ? void 0 : document,
|
2566
|
-
meta: isCloning ? void 0 : meta,
|
2567
|
-
collectionType
|
2568
|
-
};
|
2569
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2590
|
+
const plugins = useStrapiApp("HeaderToolbar", (state) => state.plugins);
|
2591
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
2570
2592
|
/* @__PURE__ */ jsx(
|
2571
2593
|
DescriptionComponentRenderer,
|
2572
2594
|
{
|
2573
|
-
props
|
2574
|
-
|
2575
|
-
|
2595
|
+
props: {
|
2596
|
+
activeTab: status,
|
2597
|
+
model,
|
2598
|
+
documentId: id,
|
2599
|
+
document: isCloning ? void 0 : document,
|
2600
|
+
meta: isCloning ? void 0 : meta,
|
2601
|
+
collectionType
|
2602
|
+
},
|
2603
|
+
descriptions: plugins["content-manager"].apis.getHeaderActions(),
|
2604
|
+
children: (actions2) => {
|
2605
|
+
if (actions2.length > 0) {
|
2606
|
+
return /* @__PURE__ */ jsx(HeaderActions, { actions: actions2 });
|
2607
|
+
} else {
|
2608
|
+
return null;
|
2609
|
+
}
|
2610
|
+
}
|
2576
2611
|
}
|
2577
2612
|
),
|
2578
|
-
/* @__PURE__ */ jsx(
|
2613
|
+
/* @__PURE__ */ jsx(
|
2614
|
+
DescriptionComponentRenderer,
|
2615
|
+
{
|
2616
|
+
props: {
|
2617
|
+
activeTab: status,
|
2618
|
+
model,
|
2619
|
+
documentId: id,
|
2620
|
+
document: isCloning ? void 0 : document,
|
2621
|
+
meta: isCloning ? void 0 : meta,
|
2622
|
+
collectionType
|
2623
|
+
},
|
2624
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2625
|
+
children: (actions2) => {
|
2626
|
+
const headerActions = actions2.filter((action) => {
|
2627
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2628
|
+
return positions.includes("header");
|
2629
|
+
});
|
2630
|
+
return /* @__PURE__ */ jsx(
|
2631
|
+
DocumentActionsMenu,
|
2632
|
+
{
|
2633
|
+
actions: headerActions,
|
2634
|
+
label: formatMessage({
|
2635
|
+
id: "content-manager.containers.edit.header.more-actions",
|
2636
|
+
defaultMessage: "More actions"
|
2637
|
+
}),
|
2638
|
+
children: /* @__PURE__ */ jsx(Information, { activeTab: status })
|
2639
|
+
}
|
2640
|
+
);
|
2641
|
+
}
|
2642
|
+
}
|
2643
|
+
)
|
2579
2644
|
] });
|
2580
2645
|
};
|
2581
|
-
const
|
2582
|
-
|
2583
|
-
|
2646
|
+
const Information = ({ activeTab }) => {
|
2647
|
+
const { formatMessage } = useIntl();
|
2648
|
+
const { document, meta } = useDoc();
|
2649
|
+
if (!document || !document.id) {
|
2650
|
+
return null;
|
2651
|
+
}
|
2652
|
+
const createAndUpdateDocument = activeTab === "draft" ? document : meta?.availableStatus.find((status) => status.publishedAt === null);
|
2653
|
+
const publishDocument = activeTab === "published" ? document : meta?.availableStatus.find((status) => status.publishedAt !== null);
|
2654
|
+
const creator = createAndUpdateDocument?.[CREATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[CREATED_BY_ATTRIBUTE_NAME]) : null;
|
2655
|
+
const updator = createAndUpdateDocument?.[UPDATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[UPDATED_BY_ATTRIBUTE_NAME]) : null;
|
2656
|
+
const information = [
|
2584
2657
|
{
|
2585
|
-
|
2586
|
-
|
2587
|
-
|
2588
|
-
|
2589
|
-
borderColor: "neutral150",
|
2590
|
-
hasRadius: true,
|
2591
|
-
paddingBottom: 4,
|
2592
|
-
paddingLeft: 4,
|
2593
|
-
paddingRight: 4,
|
2594
|
-
paddingTop: 4,
|
2595
|
-
shadow: "tableShadow",
|
2596
|
-
gap: 3,
|
2597
|
-
direction: "column",
|
2598
|
-
justifyContent: "stretch",
|
2599
|
-
alignItems: "flex-start",
|
2600
|
-
children: [
|
2601
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2602
|
-
children
|
2603
|
-
]
|
2604
|
-
}
|
2605
|
-
);
|
2606
|
-
});
|
2607
|
-
const HOOKS = {
|
2608
|
-
/**
|
2609
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2610
|
-
* @constant
|
2611
|
-
* @type {string}
|
2612
|
-
*/
|
2613
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2614
|
-
/**
|
2615
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2616
|
-
* @constant
|
2617
|
-
* @type {string}
|
2618
|
-
*/
|
2619
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2620
|
-
/**
|
2621
|
-
* Hook that allows to mutate the CM's edit view layout
|
2622
|
-
* @constant
|
2623
|
-
* @type {string}
|
2624
|
-
*/
|
2625
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2626
|
-
/**
|
2627
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2628
|
-
* @constant
|
2629
|
-
* @type {string}
|
2630
|
-
*/
|
2631
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2632
|
-
};
|
2633
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2634
|
-
endpoints: (builder) => ({
|
2635
|
-
getContentTypeConfiguration: builder.query({
|
2636
|
-
query: (uid) => ({
|
2637
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2638
|
-
method: "GET"
|
2658
|
+
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2659
|
+
label: formatMessage({
|
2660
|
+
id: "content-manager.containers.edit.information.last-published.label",
|
2661
|
+
defaultMessage: "Published"
|
2639
2662
|
}),
|
2640
|
-
|
2641
|
-
|
2642
|
-
|
2643
|
-
|
2644
|
-
|
2645
|
-
|
2646
|
-
|
2647
|
-
|
2648
|
-
|
2649
|
-
|
2650
|
-
|
2651
|
-
|
2652
|
-
|
2653
|
-
|
2654
|
-
|
2655
|
-
|
2663
|
+
value: formatMessage(
|
2664
|
+
{
|
2665
|
+
id: "content-manager.containers.edit.information.last-published.value",
|
2666
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2667
|
+
},
|
2668
|
+
{
|
2669
|
+
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
2670
|
+
isAnonymous: !publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME],
|
2671
|
+
author: publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME] ? getDisplayName(publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME]) : null
|
2672
|
+
}
|
2673
|
+
)
|
2674
|
+
},
|
2675
|
+
{
|
2676
|
+
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2677
|
+
label: formatMessage({
|
2678
|
+
id: "content-manager.containers.edit.information.last-draft.label",
|
2679
|
+
defaultMessage: "Updated"
|
2680
|
+
}),
|
2681
|
+
value: formatMessage(
|
2682
|
+
{
|
2683
|
+
id: "content-manager.containers.edit.information.last-draft.value",
|
2684
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2685
|
+
},
|
2686
|
+
{
|
2687
|
+
time: /* @__PURE__ */ jsx(
|
2688
|
+
RelativeTime,
|
2689
|
+
{
|
2690
|
+
timestamp: new Date(createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME])
|
2691
|
+
}
|
2692
|
+
),
|
2693
|
+
isAnonymous: !updator,
|
2694
|
+
author: updator
|
2695
|
+
}
|
2696
|
+
)
|
2697
|
+
},
|
2698
|
+
{
|
2699
|
+
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2700
|
+
label: formatMessage({
|
2701
|
+
id: "content-manager.containers.edit.information.document.label",
|
2702
|
+
defaultMessage: "Created"
|
2656
2703
|
}),
|
2657
|
-
|
2658
|
-
|
2659
|
-
|
2660
|
-
|
2661
|
-
|
2662
|
-
{
|
2663
|
-
|
2664
|
-
|
2665
|
-
|
2666
|
-
|
2667
|
-
|
2668
|
-
|
2669
|
-
|
2670
|
-
|
2671
|
-
}
|
2672
|
-
|
2673
|
-
|
2674
|
-
|
2675
|
-
|
2676
|
-
|
2677
|
-
|
2678
|
-
|
2679
|
-
|
2680
|
-
|
2681
|
-
|
2682
|
-
|
2683
|
-
|
2684
|
-
|
2685
|
-
|
2704
|
+
value: formatMessage(
|
2705
|
+
{
|
2706
|
+
id: "content-manager.containers.edit.information.document.value",
|
2707
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2708
|
+
},
|
2709
|
+
{
|
2710
|
+
time: /* @__PURE__ */ jsx(
|
2711
|
+
RelativeTime,
|
2712
|
+
{
|
2713
|
+
timestamp: new Date(createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME])
|
2714
|
+
}
|
2715
|
+
),
|
2716
|
+
isAnonymous: !creator,
|
2717
|
+
author: creator
|
2718
|
+
}
|
2719
|
+
)
|
2720
|
+
}
|
2721
|
+
].filter((info) => info.isDisplayed);
|
2722
|
+
return /* @__PURE__ */ jsx(
|
2723
|
+
Flex,
|
2724
|
+
{
|
2725
|
+
borderWidth: "1px 0 0 0",
|
2726
|
+
borderStyle: "solid",
|
2727
|
+
borderColor: "neutral150",
|
2728
|
+
direction: "column",
|
2729
|
+
marginTop: 2,
|
2730
|
+
tag: "dl",
|
2731
|
+
padding: 5,
|
2732
|
+
gap: 3,
|
2733
|
+
alignItems: "flex-start",
|
2734
|
+
marginLeft: "-0.4rem",
|
2735
|
+
marginRight: "-0.4rem",
|
2736
|
+
width: "calc(100% + 8px)",
|
2737
|
+
children: information.map((info) => /* @__PURE__ */ jsxs(Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
|
2738
|
+
/* @__PURE__ */ jsx(Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
|
2739
|
+
/* @__PURE__ */ jsx(Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
|
2740
|
+
] }, info.label))
|
2741
|
+
}
|
2686
2742
|
);
|
2687
|
-
return {
|
2688
|
-
name: mainFieldName,
|
2689
|
-
type: mainFieldType ?? "string"
|
2690
|
-
};
|
2691
|
-
};
|
2692
|
-
const DEFAULT_SETTINGS = {
|
2693
|
-
bulkable: false,
|
2694
|
-
filterable: false,
|
2695
|
-
searchable: false,
|
2696
|
-
pagination: false,
|
2697
|
-
defaultSortBy: "",
|
2698
|
-
defaultSortOrder: "asc",
|
2699
|
-
mainField: "id",
|
2700
|
-
pageSize: 10
|
2701
2743
|
};
|
2702
|
-
const
|
2703
|
-
const
|
2704
|
-
const
|
2705
|
-
|
2706
|
-
|
2707
|
-
|
2708
|
-
|
2709
|
-
|
2710
|
-
|
2711
|
-
|
2712
|
-
error,
|
2713
|
-
isFetching: isFetchingConfigs
|
2714
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2715
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2716
|
-
React.useEffect(() => {
|
2717
|
-
if (error) {
|
2718
|
-
toggleNotification({
|
2719
|
-
type: "danger",
|
2720
|
-
message: formatAPIError(error)
|
2721
|
-
});
|
2744
|
+
const HeaderActions = ({ actions: actions2 }) => {
|
2745
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2746
|
+
const handleClick = (action) => async (e) => {
|
2747
|
+
if (!("options" in action)) {
|
2748
|
+
const { onClick = () => false, dialog, id } = action;
|
2749
|
+
const muteDialog = await onClick(e);
|
2750
|
+
if (dialog && !muteDialog) {
|
2751
|
+
e.preventDefault();
|
2752
|
+
setDialogId(id);
|
2753
|
+
}
|
2722
2754
|
}
|
2723
|
-
}, [error, formatAPIError, toggleNotification]);
|
2724
|
-
const editLayout = React.useMemo(
|
2725
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2726
|
-
layout: [],
|
2727
|
-
components: {},
|
2728
|
-
metadatas: {},
|
2729
|
-
options: {},
|
2730
|
-
settings: DEFAULT_SETTINGS
|
2731
|
-
},
|
2732
|
-
[data, isLoading, schemas, schema, components]
|
2733
|
-
);
|
2734
|
-
const listLayout = React.useMemo(() => {
|
2735
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2736
|
-
layout: [],
|
2737
|
-
metadatas: {},
|
2738
|
-
options: {},
|
2739
|
-
settings: DEFAULT_SETTINGS
|
2740
|
-
};
|
2741
|
-
}, [data, isLoading, schemas, schema, components]);
|
2742
|
-
const { layout: edit } = React.useMemo(
|
2743
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2744
|
-
layout: editLayout,
|
2745
|
-
query
|
2746
|
-
}),
|
2747
|
-
[editLayout, query, runHookWaterfall]
|
2748
|
-
);
|
2749
|
-
return {
|
2750
|
-
error,
|
2751
|
-
isLoading,
|
2752
|
-
edit,
|
2753
|
-
list: listLayout
|
2754
2755
|
};
|
2755
|
-
|
2756
|
-
|
2757
|
-
|
2758
|
-
return
|
2759
|
-
|
2760
|
-
|
2761
|
-
|
2762
|
-
|
2763
|
-
|
2764
|
-
|
2765
|
-
|
2766
|
-
|
2767
|
-
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
schemas
|
2772
|
-
).reduce((panels, row) => {
|
2773
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2774
|
-
panels.push([row]);
|
2775
|
-
currentPanelIndex += 2;
|
2756
|
+
const handleClose = () => {
|
2757
|
+
setDialogId(null);
|
2758
|
+
};
|
2759
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2760
|
+
if (action.options) {
|
2761
|
+
return /* @__PURE__ */ jsx(
|
2762
|
+
SingleSelect,
|
2763
|
+
{
|
2764
|
+
size: "S",
|
2765
|
+
onChange: action.onSelect,
|
2766
|
+
"aria-label": action.label,
|
2767
|
+
...action,
|
2768
|
+
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2769
|
+
},
|
2770
|
+
action.id
|
2771
|
+
);
|
2776
2772
|
} else {
|
2777
|
-
if (
|
2778
|
-
|
2773
|
+
if (action.type === "icon") {
|
2774
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2775
|
+
/* @__PURE__ */ jsx(
|
2776
|
+
IconButton,
|
2777
|
+
{
|
2778
|
+
disabled: action.disabled,
|
2779
|
+
label: action.label,
|
2780
|
+
size: "S",
|
2781
|
+
onClick: handleClick(action),
|
2782
|
+
children: action.icon
|
2783
|
+
}
|
2784
|
+
),
|
2785
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2786
|
+
HeaderActionDialog,
|
2787
|
+
{
|
2788
|
+
...action.dialog,
|
2789
|
+
isOpen: dialogId === action.id,
|
2790
|
+
onClose: handleClose
|
2791
|
+
}
|
2792
|
+
) : null
|
2793
|
+
] }, action.id);
|
2779
2794
|
}
|
2780
|
-
panels[currentPanelIndex].push(row);
|
2781
2795
|
}
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
}
|
2800
|
-
|
2801
|
-
|
2802
|
-
|
2803
|
-
|
2804
|
-
|
2805
|
-
|
2806
|
-
|
2807
|
-
|
2796
|
+
}) });
|
2797
|
+
};
|
2798
|
+
const HeaderActionDialog = ({
|
2799
|
+
onClose,
|
2800
|
+
onCancel,
|
2801
|
+
title,
|
2802
|
+
content: Content,
|
2803
|
+
isOpen
|
2804
|
+
}) => {
|
2805
|
+
const handleClose = async () => {
|
2806
|
+
if (onCancel) {
|
2807
|
+
await onCancel();
|
2808
|
+
}
|
2809
|
+
onClose();
|
2810
|
+
};
|
2811
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2812
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2813
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2814
|
+
] }) });
|
2815
|
+
};
|
2816
|
+
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2817
|
+
const navigate = useNavigate();
|
2818
|
+
const { formatMessage } = useIntl();
|
2819
|
+
return {
|
2820
|
+
label: formatMessage({
|
2821
|
+
id: "app.links.configure-view",
|
2822
|
+
defaultMessage: "Configure the view"
|
2823
|
+
}),
|
2824
|
+
icon: /* @__PURE__ */ jsx(ListPlus, {}),
|
2825
|
+
onClick: () => {
|
2826
|
+
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2808
2827
|
},
|
2809
|
-
|
2810
|
-
|
2828
|
+
position: "header"
|
2829
|
+
};
|
2830
|
+
};
|
2831
|
+
ConfigureTheViewAction.type = "configure-the-view";
|
2832
|
+
const EditTheModelAction = ({ model }) => {
|
2833
|
+
const navigate = useNavigate();
|
2834
|
+
const { formatMessage } = useIntl();
|
2811
2835
|
return {
|
2812
|
-
|
2813
|
-
|
2814
|
-
|
2815
|
-
|
2816
|
-
|
2817
|
-
|
2836
|
+
label: formatMessage({
|
2837
|
+
id: "content-manager.link-to-ctb",
|
2838
|
+
defaultMessage: "Edit the model"
|
2839
|
+
}),
|
2840
|
+
icon: /* @__PURE__ */ jsx(Pencil, {}),
|
2841
|
+
onClick: () => {
|
2842
|
+
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2818
2843
|
},
|
2819
|
-
|
2820
|
-
...schema?.options,
|
2821
|
-
...schema?.pluginOptions,
|
2822
|
-
...data.contentType.options
|
2823
|
-
}
|
2844
|
+
position: "header"
|
2824
2845
|
};
|
2825
2846
|
};
|
2826
|
-
|
2827
|
-
|
2828
|
-
|
2829
|
-
|
2830
|
-
|
2831
|
-
|
2847
|
+
EditTheModelAction.type = "edit-the-model";
|
2848
|
+
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2849
|
+
const navigate = useNavigate();
|
2850
|
+
const { formatMessage } = useIntl();
|
2851
|
+
const listViewPathMatch = useMatch(LIST_PATH);
|
2852
|
+
const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
|
2853
|
+
const { delete: deleteAction } = useDocumentActions();
|
2854
|
+
const { toggleNotification } = useNotification();
|
2855
|
+
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2856
|
+
const isLocalized = document?.locale != null;
|
2857
|
+
return {
|
2858
|
+
disabled: !canDelete || !document,
|
2859
|
+
label: formatMessage(
|
2860
|
+
{
|
2861
|
+
id: "content-manager.actions.delete.label",
|
2862
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2863
|
+
},
|
2864
|
+
{ isLocalized }
|
2865
|
+
),
|
2866
|
+
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2867
|
+
dialog: {
|
2868
|
+
type: "dialog",
|
2869
|
+
title: formatMessage({
|
2870
|
+
id: "app.components.ConfirmDialog.title",
|
2871
|
+
defaultMessage: "Confirmation"
|
2872
|
+
}),
|
2873
|
+
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
2874
|
+
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2875
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2876
|
+
id: "content-manager.actions.delete.dialog.body",
|
2877
|
+
defaultMessage: "Are you sure?"
|
2878
|
+
}) })
|
2879
|
+
] }),
|
2880
|
+
onConfirm: async () => {
|
2881
|
+
if (!listViewPathMatch) {
|
2882
|
+
setSubmitting(true);
|
2883
|
+
}
|
2884
|
+
try {
|
2885
|
+
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2886
|
+
console.error(
|
2887
|
+
"You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2888
|
+
);
|
2889
|
+
toggleNotification({
|
2890
|
+
message: formatMessage({
|
2891
|
+
id: "content-manager.actions.delete.error",
|
2892
|
+
defaultMessage: "An error occurred while trying to delete the document."
|
2893
|
+
}),
|
2894
|
+
type: "danger"
|
2895
|
+
});
|
2896
|
+
return;
|
2897
|
+
}
|
2898
|
+
const res = await deleteAction({
|
2899
|
+
documentId,
|
2900
|
+
model,
|
2901
|
+
collectionType,
|
2902
|
+
params: {
|
2903
|
+
locale: "*"
|
2904
|
+
}
|
2905
|
+
});
|
2906
|
+
if (!("error" in res)) {
|
2907
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2908
|
+
}
|
2909
|
+
} finally {
|
2910
|
+
if (!listViewPathMatch) {
|
2911
|
+
setSubmitting(false);
|
2912
|
+
}
|
2913
|
+
}
|
2832
2914
|
}
|
2833
|
-
const { edit: metadata } = metadatas[field.name];
|
2834
|
-
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2835
|
-
return {
|
2836
|
-
attribute,
|
2837
|
-
disabled: !metadata.editable,
|
2838
|
-
hint: metadata.description,
|
2839
|
-
label: metadata.label ?? "",
|
2840
|
-
name: field.name,
|
2841
|
-
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
2842
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2843
|
-
schemas,
|
2844
|
-
components: components?.schemas ?? {}
|
2845
|
-
}),
|
2846
|
-
placeholder: metadata.placeholder ?? "",
|
2847
|
-
required: attribute.required ?? false,
|
2848
|
-
size: field.size,
|
2849
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
2850
|
-
visible: metadata.visible ?? true,
|
2851
|
-
type: attribute.type
|
2852
|
-
};
|
2853
|
-
}).filter((field) => field !== null)
|
2854
|
-
);
|
2855
|
-
};
|
2856
|
-
const formatListLayout = (data, {
|
2857
|
-
schemas,
|
2858
|
-
schema,
|
2859
|
-
components
|
2860
|
-
}) => {
|
2861
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2862
|
-
(acc, [attribute, metadata]) => {
|
2863
|
-
return {
|
2864
|
-
...acc,
|
2865
|
-
[attribute]: metadata.list
|
2866
|
-
};
|
2867
2915
|
},
|
2868
|
-
|
2869
|
-
|
2870
|
-
|
2871
|
-
|
2872
|
-
|
2873
|
-
|
2874
|
-
|
2875
|
-
|
2876
|
-
|
2877
|
-
|
2878
|
-
|
2879
|
-
|
2880
|
-
|
2881
|
-
|
2882
|
-
|
2883
|
-
|
2884
|
-
|
2916
|
+
variant: "danger",
|
2917
|
+
position: ["header", "table-row"]
|
2918
|
+
};
|
2919
|
+
};
|
2920
|
+
DeleteAction$1.type = "delete";
|
2921
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2922
|
+
const Panels = () => {
|
2923
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2924
|
+
const [
|
2925
|
+
{
|
2926
|
+
query: { status }
|
2927
|
+
}
|
2928
|
+
] = useQueryParams({
|
2929
|
+
status: "draft"
|
2930
|
+
});
|
2931
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2932
|
+
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2933
|
+
const props = {
|
2934
|
+
activeTab: status,
|
2935
|
+
model,
|
2936
|
+
documentId: id,
|
2937
|
+
document: isCloning ? void 0 : document,
|
2938
|
+
meta: isCloning ? void 0 : meta,
|
2939
|
+
collectionType
|
2940
|
+
};
|
2941
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2942
|
+
DescriptionComponentRenderer,
|
2943
|
+
{
|
2944
|
+
props,
|
2945
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2946
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2885
2947
|
}
|
2948
|
+
) });
|
2949
|
+
};
|
2950
|
+
const ActionsPanel = () => {
|
2951
|
+
const { formatMessage } = useIntl();
|
2952
|
+
return {
|
2953
|
+
title: formatMessage({
|
2954
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2955
|
+
defaultMessage: "Entry"
|
2956
|
+
}),
|
2957
|
+
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2886
2958
|
};
|
2887
2959
|
};
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2960
|
+
ActionsPanel.type = "actions";
|
2961
|
+
const ActionsPanelContent = () => {
|
2962
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2963
|
+
const [
|
2964
|
+
{
|
2965
|
+
query: { status = "draft" }
|
2893
2966
|
}
|
2894
|
-
|
2895
|
-
|
2896
|
-
|
2897
|
-
|
2898
|
-
|
2899
|
-
|
2900
|
-
|
2901
|
-
|
2902
|
-
|
2903
|
-
|
2904
|
-
|
2905
|
-
|
2906
|
-
|
2907
|
-
|
2967
|
+
] = useQueryParams();
|
2968
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2969
|
+
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2970
|
+
const props = {
|
2971
|
+
activeTab: status,
|
2972
|
+
model,
|
2973
|
+
documentId: id,
|
2974
|
+
document: isCloning ? void 0 : document,
|
2975
|
+
meta: isCloning ? void 0 : meta,
|
2976
|
+
collectionType
|
2977
|
+
};
|
2978
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2979
|
+
/* @__PURE__ */ jsx(
|
2980
|
+
DescriptionComponentRenderer,
|
2981
|
+
{
|
2982
|
+
props,
|
2983
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2984
|
+
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2985
|
+
}
|
2986
|
+
),
|
2987
|
+
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2988
|
+
] });
|
2908
2989
|
};
|
2990
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
2991
|
+
return /* @__PURE__ */ jsxs(
|
2992
|
+
Flex,
|
2993
|
+
{
|
2994
|
+
ref,
|
2995
|
+
tag: "aside",
|
2996
|
+
"aria-labelledby": "additional-information",
|
2997
|
+
background: "neutral0",
|
2998
|
+
borderColor: "neutral150",
|
2999
|
+
hasRadius: true,
|
3000
|
+
paddingBottom: 4,
|
3001
|
+
paddingLeft: 4,
|
3002
|
+
paddingRight: 4,
|
3003
|
+
paddingTop: 4,
|
3004
|
+
shadow: "tableShadow",
|
3005
|
+
gap: 3,
|
3006
|
+
direction: "column",
|
3007
|
+
justifyContent: "stretch",
|
3008
|
+
alignItems: "flex-start",
|
3009
|
+
children: [
|
3010
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
3011
|
+
children
|
3012
|
+
]
|
3013
|
+
}
|
3014
|
+
);
|
3015
|
+
});
|
2909
3016
|
const ConfirmBulkActionDialog = ({
|
2910
3017
|
onToggleDialog,
|
2911
3018
|
isOpen = false,
|
@@ -2944,6 +3051,7 @@ const ConfirmDialogPublishAll = ({
|
|
2944
3051
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2945
3052
|
const { model, schema } = useDoc();
|
2946
3053
|
const [{ query }] = useQueryParams();
|
3054
|
+
const enableDraftRelationsCount = false;
|
2947
3055
|
const {
|
2948
3056
|
data: countDraftRelations = 0,
|
2949
3057
|
isLoading,
|
@@ -2955,7 +3063,7 @@ const ConfirmDialogPublishAll = ({
|
|
2955
3063
|
locale: query?.plugins?.i18n?.locale
|
2956
3064
|
},
|
2957
3065
|
{
|
2958
|
-
skip:
|
3066
|
+
skip: !enableDraftRelationsCount
|
2959
3067
|
}
|
2960
3068
|
);
|
2961
3069
|
React.useEffect(() => {
|
@@ -3140,7 +3248,7 @@ const SelectedEntriesTableContent = ({
|
|
3140
3248
|
status: row.status
|
3141
3249
|
}
|
3142
3250
|
) }),
|
3143
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3251
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3144
3252
|
IconButton,
|
3145
3253
|
{
|
3146
3254
|
tag: Link,
|
@@ -3163,9 +3271,10 @@ const SelectedEntriesTableContent = ({
|
|
3163
3271
|
),
|
3164
3272
|
target: "_blank",
|
3165
3273
|
marginLeft: "auto",
|
3166
|
-
|
3274
|
+
variant: "ghost",
|
3275
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3167
3276
|
}
|
3168
|
-
) })
|
3277
|
+
) }) })
|
3169
3278
|
] }, row.id)) })
|
3170
3279
|
] });
|
3171
3280
|
};
|
@@ -3900,7 +4009,7 @@ const index = {
|
|
3900
4009
|
app.router.addRoute({
|
3901
4010
|
path: "content-manager/*",
|
3902
4011
|
lazy: async () => {
|
3903
|
-
const { Layout } = await import("./layout-
|
4012
|
+
const { Layout } = await import("./layout-2CfjL0T9.mjs");
|
3904
4013
|
return {
|
3905
4014
|
Component: Layout
|
3906
4015
|
};
|
@@ -3917,7 +4026,7 @@ const index = {
|
|
3917
4026
|
async registerTrads({ locales }) {
|
3918
4027
|
const importedTrads = await Promise.all(
|
3919
4028
|
locales.map((locale) => {
|
3920
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-
|
4029
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-DKV44jRb.mjs"), "./translations/es.json": () => import("./es-CeXiYflN.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr-CD9VFbPM.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-CtsUxOvk.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
|
3921
4030
|
return {
|
3922
4031
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3923
4032
|
locale
|
@@ -3945,7 +4054,8 @@ export {
|
|
3945
4054
|
InjectionZone as I,
|
3946
4055
|
useDocument as J,
|
3947
4056
|
index as K,
|
3948
|
-
|
4057
|
+
useContentManagerContext as L,
|
4058
|
+
useDocumentActions as M,
|
3949
4059
|
Panels as P,
|
3950
4060
|
RelativeTime as R,
|
3951
4061
|
SINGLE_TYPES as S,
|
@@ -3977,4 +4087,4 @@ export {
|
|
3977
4087
|
capitalise as y,
|
3978
4088
|
useUpdateContentTypeConfigurationMutation as z
|
3979
4089
|
};
|
3980
|
-
//# sourceMappingURL=index-
|
4090
|
+
//# sourceMappingURL=index-wnqzm4Q8.mjs.map
|