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