@strapi/content-manager 5.0.0-rc.2 → 5.0.0-rc.20
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-Bv-IXOYu.js → ComponentConfigurationPage-DnnZJc1F.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-Bv-IXOYu.js.map → ComponentConfigurationPage-DnnZJc1F.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BxJCkKZV.mjs → ComponentConfigurationPage-hLMNf7KI.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-BxJCkKZV.mjs.map → ComponentConfigurationPage-hLMNf7KI.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-QZl5zOz-.js → EditConfigurationPage-CpLj5gYZ.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-QZl5zOz-.js.map → EditConfigurationPage-CpLj5gYZ.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-BGwHNypQ.mjs → EditConfigurationPage-Dh6sq-G4.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-BGwHNypQ.mjs.map → EditConfigurationPage-Dh6sq-G4.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-CtdtssrH.mjs → EditViewPage-BU1ugeVi.mjs} +19 -8
- package/dist/_chunks/EditViewPage-BU1ugeVi.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-DxKueadW.js → EditViewPage-D2QVRr_2.js} +19 -8
- package/dist/_chunks/EditViewPage-D2QVRr_2.js.map +1 -0
- package/dist/_chunks/{Field-BPw8fE3W.js → Field-BEDX9i_V.js} +120 -92
- package/dist/_chunks/Field-BEDX9i_V.js.map +1 -0
- package/dist/_chunks/{Field-BU7_nR4F.mjs → Field-VSPY6uzs.mjs} +118 -90
- package/dist/_chunks/Field-VSPY6uzs.mjs.map +1 -0
- package/dist/_chunks/{Form-ffghBTPI.mjs → Form-05Oaes1N.mjs} +35 -16
- package/dist/_chunks/Form-05Oaes1N.mjs.map +1 -0
- package/dist/_chunks/{Form-DtvmbGdZ.js → Form-DCaY8xBX.js} +35 -16
- package/dist/_chunks/Form-DCaY8xBX.js.map +1 -0
- package/dist/_chunks/{History-D6PRyNcx.mjs → History-BqO2G3MV.mjs} +4 -4
- package/dist/_chunks/{History-D6PRyNcx.mjs.map → History-BqO2G3MV.mjs.map} +1 -1
- package/dist/_chunks/{History-CSr8y9KM.js → History-BrJ1tUvt.js} +4 -4
- package/dist/_chunks/{History-CSr8y9KM.js.map → History-BrJ1tUvt.js.map} +1 -1
- package/dist/_chunks/{ListConfigurationPage-BC9bCi9k.mjs → ListConfigurationPage-C6rsFlme.mjs} +14 -4
- package/dist/_chunks/ListConfigurationPage-C6rsFlme.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DsmAQ3YM.js → ListConfigurationPage-Eane5LKE.js} +14 -4
- package/dist/_chunks/ListConfigurationPage-Eane5LKE.js.map +1 -0
- package/dist/_chunks/{ListViewPage-DqAIb_ie.js → ListViewPage-Coj-RPsx.js} +49 -40
- package/dist/_chunks/ListViewPage-Coj-RPsx.js.map +1 -0
- package/dist/_chunks/{ListViewPage-B1GyNqfn.mjs → ListViewPage-yE_zYhcI.mjs} +47 -38
- package/dist/_chunks/ListViewPage-yE_zYhcI.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-xjvn5XwY.js → NoContentTypePage-BDJ0dshy.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-xjvn5XwY.js.map → NoContentTypePage-BDJ0dshy.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-CJ-HJriz.mjs → NoContentTypePage-NW_FSVdY.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CJ-HJriz.mjs.map → NoContentTypePage-NW_FSVdY.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DObTkKmZ.js → NoPermissionsPage-BOtb5FTM.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DObTkKmZ.js.map → NoPermissionsPage-BOtb5FTM.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage--afHbbbD.mjs → NoPermissionsPage-h0I3ImsX.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage--afHbbbD.mjs.map → NoPermissionsPage-h0I3ImsX.mjs.map} +1 -1
- package/dist/_chunks/{Relations-t4Q0DpqW.js → Relations-CVh0DOKv.js} +4 -4
- package/dist/_chunks/{Relations-t4Q0DpqW.js.map → Relations-CVh0DOKv.js.map} +1 -1
- package/dist/_chunks/{Relations-heq-nLGU.mjs → Relations-FP0uWpBz.mjs} +4 -4
- package/dist/_chunks/{Relations-heq-nLGU.mjs.map → Relations-FP0uWpBz.mjs.map} +1 -1
- package/dist/_chunks/{en-uOUIxfcQ.js → en-BlhnxQfj.js} +7 -6
- package/dist/_chunks/{en-uOUIxfcQ.js.map → en-BlhnxQfj.js.map} +1 -1
- package/dist/_chunks/{en-BrCTWlZv.mjs → en-C8YBvRrK.mjs} +7 -6
- package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-C8YBvRrK.mjs.map} +1 -1
- package/dist/_chunks/{index-BcQ8cRyl.mjs → index-CPCHQ3X_.mjs} +1927 -1765
- package/dist/_chunks/index-CPCHQ3X_.mjs.map +1 -0
- package/dist/_chunks/{index-1zxclxo_.js → index-DTKVhcla.js} +1907 -1745
- package/dist/_chunks/index-DTKVhcla.js.map +1 -0
- package/dist/_chunks/{layout-Jl9mJFJZ.mjs → layout-B4UhJ8MJ.mjs} +22 -9
- package/dist/_chunks/layout-B4UhJ8MJ.mjs.map +1 -0
- package/dist/_chunks/{layout-tVvbqota.js → layout-CWgZzMYf.js} +21 -8
- package/dist/_chunks/layout-CWgZzMYf.js.map +1 -0
- package/dist/_chunks/{relations-f4Pv7Kgo.mjs → relations-B83Ge9a7.mjs} +2 -2
- package/dist/_chunks/{relations-f4Pv7Kgo.mjs.map → relations-B83Ge9a7.mjs.map} +1 -1
- package/dist/_chunks/{relations-CK2Jd0HM.js → relations-D81a_2zw.js} +2 -2
- package/dist/_chunks/{relations-CK2Jd0HM.js.map → relations-D81a_2zw.js.map} +1 -1
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +5 -4
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +30 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/pages/EditView/components/Header.d.ts +10 -11
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +19 -17
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +147 -82
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +148 -83
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +2 -1
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/package.json +11 -11
- package/dist/_chunks/EditViewPage-CtdtssrH.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-DxKueadW.js.map +0 -1
- package/dist/_chunks/Field-BPw8fE3W.js.map +0 -1
- package/dist/_chunks/Field-BU7_nR4F.mjs.map +0 -1
- package/dist/_chunks/Form-DtvmbGdZ.js.map +0 -1
- package/dist/_chunks/Form-ffghBTPI.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-BC9bCi9k.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DsmAQ3YM.js.map +0 -1
- package/dist/_chunks/ListViewPage-B1GyNqfn.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-DqAIb_ie.js.map +0 -1
- package/dist/_chunks/index-1zxclxo_.js.map +0 -1
- package/dist/_chunks/index-BcQ8cRyl.mjs.map +0 -1
- package/dist/_chunks/layout-Jl9mJFJZ.mjs.map +0 -1
- package/dist/_chunks/layout-tVvbqota.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
@@ -6,10 +6,10 @@ const React = require("react");
|
|
6
6
|
const designSystem = require("@strapi/design-system");
|
7
7
|
const reactIntl = require("react-intl");
|
8
8
|
const reactRouterDom = require("react-router-dom");
|
9
|
-
const styledComponents = require("styled-components");
|
10
9
|
const yup = require("yup");
|
11
10
|
const pipe = require("lodash/fp/pipe");
|
12
11
|
const dateFns = require("date-fns");
|
12
|
+
const styledComponents = require("styled-components");
|
13
13
|
const qs = require("qs");
|
14
14
|
const toolkit = require("@reduxjs/toolkit");
|
15
15
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
@@ -179,7 +179,8 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
|
179
179
|
"Document",
|
180
180
|
"InitialData",
|
181
181
|
"HistoryVersion",
|
182
|
-
"Relations"
|
182
|
+
"Relations",
|
183
|
+
"UidAvailability"
|
183
184
|
]
|
184
185
|
});
|
185
186
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -209,7 +210,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
209
210
|
params
|
210
211
|
}
|
211
212
|
}),
|
212
|
-
invalidatesTags: (_result, _error, { model }) => [
|
213
|
+
invalidatesTags: (_result, _error, { model }) => [
|
214
|
+
{ type: "Document", id: `${model}_LIST` },
|
215
|
+
{ type: "UidAvailability", id: model }
|
216
|
+
]
|
213
217
|
}),
|
214
218
|
/**
|
215
219
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -226,7 +230,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
226
230
|
}),
|
227
231
|
invalidatesTags: (result, _error, { model }) => [
|
228
232
|
{ type: "Document", id: `${model}_LIST` },
|
229
|
-
"Relations"
|
233
|
+
"Relations",
|
234
|
+
{ type: "UidAvailability", id: model }
|
230
235
|
]
|
231
236
|
}),
|
232
237
|
deleteDocument: builder.mutation({
|
@@ -267,7 +272,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
267
272
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
268
273
|
},
|
269
274
|
{ type: "Document", id: `${model}_LIST` },
|
270
|
-
"Relations"
|
275
|
+
"Relations",
|
276
|
+
{ type: "UidAvailability", id: model }
|
271
277
|
];
|
272
278
|
}
|
273
279
|
}),
|
@@ -285,6 +291,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
285
291
|
}),
|
286
292
|
providesTags: (result, _error, arg) => {
|
287
293
|
return [
|
294
|
+
{ type: "Document", id: `ALL_LIST` },
|
288
295
|
{ type: "Document", id: `${arg.model}_LIST` },
|
289
296
|
...result?.results.map(({ documentId }) => ({
|
290
297
|
type: "Document",
|
@@ -323,6 +330,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
323
330
|
{
|
324
331
|
type: "Document",
|
325
332
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
333
|
+
},
|
334
|
+
// Make it easy to invalidate all individual documents queries for a model
|
335
|
+
{
|
336
|
+
type: "Document",
|
337
|
+
id: `${model}_ALL_ITEMS`
|
326
338
|
}
|
327
339
|
];
|
328
340
|
}
|
@@ -386,8 +398,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
386
398
|
type: "Document",
|
387
399
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
388
400
|
},
|
389
|
-
"Relations"
|
401
|
+
"Relations",
|
402
|
+
{ type: "UidAvailability", id: model }
|
390
403
|
];
|
404
|
+
},
|
405
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
406
|
+
const patchResult = dispatch(
|
407
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
408
|
+
Object.assign(draft.data, data);
|
409
|
+
})
|
410
|
+
);
|
411
|
+
try {
|
412
|
+
await queryFulfilled;
|
413
|
+
} catch {
|
414
|
+
patchResult.undo();
|
415
|
+
}
|
391
416
|
}
|
392
417
|
}),
|
393
418
|
unpublishDocument: builder.mutation({
|
@@ -457,7 +482,7 @@ const buildValidParams = (query) => {
|
|
457
482
|
const isBaseQueryError = (error) => {
|
458
483
|
return error.name !== void 0;
|
459
484
|
};
|
460
|
-
const createYupSchema = (attributes = {}, components = {}) => {
|
485
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
461
486
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
462
487
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
463
488
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
@@ -470,7 +495,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
470
495
|
addMinValidation,
|
471
496
|
addMaxValidation,
|
472
497
|
addRegexValidation
|
473
|
-
].map((fn) => fn(attribute));
|
498
|
+
].map((fn) => fn(attribute, options));
|
474
499
|
const transformSchema = pipe__default.default(...validations);
|
475
500
|
switch (attribute.type) {
|
476
501
|
case "component": {
|
@@ -571,6 +596,14 @@ const createAttributeSchema = (attribute) => {
|
|
571
596
|
if (!value || typeof value === "string" && value.length === 0) {
|
572
597
|
return true;
|
573
598
|
}
|
599
|
+
if (typeof value === "object") {
|
600
|
+
try {
|
601
|
+
JSON.stringify(value);
|
602
|
+
return true;
|
603
|
+
} catch (err) {
|
604
|
+
return false;
|
605
|
+
}
|
606
|
+
}
|
574
607
|
try {
|
575
608
|
JSON.parse(value);
|
576
609
|
return true;
|
@@ -589,13 +622,7 @@ const createAttributeSchema = (attribute) => {
|
|
589
622
|
return yup__namespace.mixed();
|
590
623
|
}
|
591
624
|
};
|
592
|
-
const
|
593
|
-
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
594
|
-
return schema.min(1, strapiAdmin.translatedErrors.required);
|
595
|
-
}
|
596
|
-
if (attribute.required && attribute.type !== "relation") {
|
597
|
-
return schema.required(strapiAdmin.translatedErrors.required);
|
598
|
-
}
|
625
|
+
const nullableSchema = (schema) => {
|
599
626
|
return schema?.nullable ? schema.nullable() : (
|
600
627
|
// In some cases '.nullable' will not be available on the schema.
|
601
628
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -603,7 +630,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
603
630
|
schema
|
604
631
|
);
|
605
632
|
};
|
606
|
-
const
|
633
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
634
|
+
if (options.status === "draft") {
|
635
|
+
return nullableSchema(schema);
|
636
|
+
}
|
637
|
+
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
638
|
+
return schema.min(1, strapiAdmin.translatedErrors.required);
|
639
|
+
}
|
640
|
+
if (attribute.required && attribute.type !== "relation") {
|
641
|
+
return schema.required(strapiAdmin.translatedErrors.required);
|
642
|
+
}
|
643
|
+
return nullableSchema(schema);
|
644
|
+
};
|
645
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
646
|
+
if (options.status === "draft") {
|
647
|
+
return schema;
|
648
|
+
}
|
607
649
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
608
650
|
return schema.min(attribute.minLength, {
|
609
651
|
...strapiAdmin.translatedErrors.minLength,
|
@@ -625,11 +667,11 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
625
667
|
}
|
626
668
|
return schema;
|
627
669
|
};
|
628
|
-
const addMinValidation = (attribute) => (schema) => {
|
670
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
629
671
|
if ("min" in attribute) {
|
630
672
|
const min = toInteger(attribute.min);
|
631
673
|
if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
|
632
|
-
if (!attribute.required && "test" in schema && min) {
|
674
|
+
if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
|
633
675
|
return schema.test(
|
634
676
|
"custom-min",
|
635
677
|
{
|
@@ -768,19 +810,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
768
810
|
}, {});
|
769
811
|
return componentsByKey;
|
770
812
|
};
|
771
|
-
const
|
813
|
+
const HOOKS = {
|
814
|
+
/**
|
815
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
816
|
+
* @constant
|
817
|
+
* @type {string}
|
818
|
+
*/
|
819
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
820
|
+
/**
|
821
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
822
|
+
* @constant
|
823
|
+
* @type {string}
|
824
|
+
*/
|
825
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
826
|
+
/**
|
827
|
+
* Hook that allows to mutate the CM's edit view layout
|
828
|
+
* @constant
|
829
|
+
* @type {string}
|
830
|
+
*/
|
831
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
832
|
+
/**
|
833
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
834
|
+
* @constant
|
835
|
+
* @type {string}
|
836
|
+
*/
|
837
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
838
|
+
};
|
839
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
840
|
+
endpoints: (builder) => ({
|
841
|
+
getContentTypeConfiguration: builder.query({
|
842
|
+
query: (uid) => ({
|
843
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
844
|
+
method: "GET"
|
845
|
+
}),
|
846
|
+
transformResponse: (response) => response.data,
|
847
|
+
providesTags: (_result, _error, uid) => [
|
848
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
849
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
850
|
+
]
|
851
|
+
}),
|
852
|
+
getAllContentTypeSettings: builder.query({
|
853
|
+
query: () => "/content-manager/content-types-settings",
|
854
|
+
transformResponse: (response) => response.data,
|
855
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
856
|
+
}),
|
857
|
+
updateContentTypeConfiguration: builder.mutation({
|
858
|
+
query: ({ uid, ...body }) => ({
|
859
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
860
|
+
method: "PUT",
|
861
|
+
data: body
|
862
|
+
}),
|
863
|
+
transformResponse: (response) => response.data,
|
864
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
865
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
866
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
867
|
+
// Is this necessary?
|
868
|
+
{ type: "InitialData" }
|
869
|
+
]
|
870
|
+
})
|
871
|
+
})
|
872
|
+
});
|
873
|
+
const {
|
874
|
+
useGetContentTypeConfigurationQuery,
|
875
|
+
useGetAllContentTypeSettingsQuery,
|
876
|
+
useUpdateContentTypeConfigurationMutation
|
877
|
+
} = contentTypesApi;
|
878
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
879
|
+
const { type } = attribute;
|
880
|
+
if (type === "relation") {
|
881
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
882
|
+
}
|
883
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
884
|
+
};
|
885
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
886
|
+
if (!mainFieldName) {
|
887
|
+
return void 0;
|
888
|
+
}
|
889
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
890
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
891
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
892
|
+
);
|
893
|
+
return {
|
894
|
+
name: mainFieldName,
|
895
|
+
type: mainFieldType ?? "string"
|
896
|
+
};
|
897
|
+
};
|
898
|
+
const DEFAULT_SETTINGS = {
|
899
|
+
bulkable: false,
|
900
|
+
filterable: false,
|
901
|
+
searchable: false,
|
902
|
+
pagination: false,
|
903
|
+
defaultSortBy: "",
|
904
|
+
defaultSortOrder: "asc",
|
905
|
+
mainField: "id",
|
906
|
+
pageSize: 10
|
907
|
+
};
|
908
|
+
const useDocumentLayout = (model) => {
|
909
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
910
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
911
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
772
912
|
const { toggleNotification } = strapiAdmin.useNotification();
|
773
913
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
914
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
774
915
|
const {
|
775
|
-
|
776
|
-
isLoading:
|
777
|
-
|
778
|
-
|
779
|
-
} =
|
780
|
-
|
781
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
782
|
-
});
|
783
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
916
|
+
data,
|
917
|
+
isLoading: isLoadingConfigs,
|
918
|
+
error,
|
919
|
+
isFetching: isFetchingConfigs
|
920
|
+
} = useGetContentTypeConfigurationQuery(model);
|
921
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
784
922
|
React__namespace.useEffect(() => {
|
785
923
|
if (error) {
|
786
924
|
toggleNotification({
|
@@ -788,388 +926,642 @@ const useDocument = (args, opts) => {
|
|
788
926
|
message: formatAPIError(error)
|
789
927
|
});
|
790
928
|
}
|
791
|
-
}, [
|
792
|
-
const
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
(document) => {
|
800
|
-
if (!validationSchema) {
|
801
|
-
throw new Error(
|
802
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
803
|
-
);
|
804
|
-
}
|
805
|
-
try {
|
806
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
807
|
-
return null;
|
808
|
-
} catch (error2) {
|
809
|
-
if (error2 instanceof yup.ValidationError) {
|
810
|
-
return strapiAdmin.getYupValidationErrors(error2);
|
811
|
-
}
|
812
|
-
throw error2;
|
813
|
-
}
|
929
|
+
}, [error, formatAPIError, toggleNotification]);
|
930
|
+
const editLayout = React__namespace.useMemo(
|
931
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
932
|
+
layout: [],
|
933
|
+
components: {},
|
934
|
+
metadatas: {},
|
935
|
+
options: {},
|
936
|
+
settings: DEFAULT_SETTINGS
|
814
937
|
},
|
815
|
-
[
|
938
|
+
[data, isLoading, schemas, schema, components]
|
939
|
+
);
|
940
|
+
const listLayout = React__namespace.useMemo(() => {
|
941
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
942
|
+
layout: [],
|
943
|
+
metadatas: {},
|
944
|
+
options: {},
|
945
|
+
settings: DEFAULT_SETTINGS
|
946
|
+
};
|
947
|
+
}, [data, isLoading, schemas, schema, components]);
|
948
|
+
const { layout: edit } = React__namespace.useMemo(
|
949
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
950
|
+
layout: editLayout,
|
951
|
+
query
|
952
|
+
}),
|
953
|
+
[editLayout, query, runHookWaterfall]
|
816
954
|
);
|
817
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
818
955
|
return {
|
819
|
-
|
820
|
-
document: data?.data,
|
821
|
-
meta: data?.meta,
|
956
|
+
error,
|
822
957
|
isLoading,
|
823
|
-
|
824
|
-
|
825
|
-
};
|
826
|
-
};
|
827
|
-
const useDoc = () => {
|
828
|
-
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
829
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
830
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
831
|
-
if (!collectionType) {
|
832
|
-
throw new Error("Could not find collectionType in url params");
|
833
|
-
}
|
834
|
-
if (!slug) {
|
835
|
-
throw new Error("Could not find model in url params");
|
836
|
-
}
|
837
|
-
return {
|
838
|
-
collectionType,
|
839
|
-
model: slug,
|
840
|
-
id: origin || id === "create" ? void 0 : id,
|
841
|
-
...useDocument(
|
842
|
-
{ documentId: origin || id, model: slug, collectionType, params },
|
843
|
-
{
|
844
|
-
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
845
|
-
}
|
846
|
-
)
|
958
|
+
edit,
|
959
|
+
list: listLayout
|
847
960
|
};
|
848
961
|
};
|
849
|
-
const
|
850
|
-
|
851
|
-
|
852
|
-
}
|
853
|
-
return Object.keys(trad).reduce((acc, current) => {
|
854
|
-
acc[`${pluginId}.${current}`] = trad[current];
|
855
|
-
return acc;
|
856
|
-
}, {});
|
857
|
-
};
|
858
|
-
const getTranslation = (id) => `content-manager.${id}`;
|
859
|
-
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
860
|
-
id: "notification.error",
|
861
|
-
defaultMessage: "An error occurred, please try again"
|
962
|
+
const useDocLayout = () => {
|
963
|
+
const { model } = useDoc();
|
964
|
+
return useDocumentLayout(model);
|
862
965
|
};
|
863
|
-
const
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
const
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
message: formatAPIError(res.error)
|
883
|
-
});
|
884
|
-
return { error: res.error };
|
885
|
-
}
|
886
|
-
toggleNotification({
|
887
|
-
type: "success",
|
888
|
-
message: formatMessage({
|
889
|
-
id: getTranslation("success.record.delete"),
|
890
|
-
defaultMessage: "Deleted document"
|
891
|
-
})
|
892
|
-
});
|
893
|
-
trackUsage("didDeleteEntry", trackerProperty);
|
894
|
-
return res.data;
|
895
|
-
} catch (err) {
|
896
|
-
toggleNotification({
|
897
|
-
type: "danger",
|
898
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
899
|
-
});
|
900
|
-
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
901
|
-
throw err;
|
966
|
+
const formatEditLayout = (data, {
|
967
|
+
schemas,
|
968
|
+
schema,
|
969
|
+
components
|
970
|
+
}) => {
|
971
|
+
let currentPanelIndex = 0;
|
972
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
973
|
+
data.contentType.layouts.edit,
|
974
|
+
schema?.attributes,
|
975
|
+
data.contentType.metadatas,
|
976
|
+
{ configurations: data.components, schemas: components },
|
977
|
+
schemas
|
978
|
+
).reduce((panels, row) => {
|
979
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
980
|
+
panels.push([row]);
|
981
|
+
currentPanelIndex += 2;
|
982
|
+
} else {
|
983
|
+
if (!panels[currentPanelIndex]) {
|
984
|
+
panels.push([]);
|
902
985
|
}
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
const
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
});
|
921
|
-
return { error: res.error };
|
986
|
+
panels[currentPanelIndex].push(row);
|
987
|
+
}
|
988
|
+
return panels;
|
989
|
+
}, []);
|
990
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
991
|
+
(acc, [uid, configuration]) => {
|
992
|
+
acc[uid] = {
|
993
|
+
layout: convertEditLayoutToFieldLayouts(
|
994
|
+
configuration.layouts.edit,
|
995
|
+
components[uid].attributes,
|
996
|
+
configuration.metadatas,
|
997
|
+
{ configurations: data.components, schemas: components }
|
998
|
+
),
|
999
|
+
settings: {
|
1000
|
+
...configuration.settings,
|
1001
|
+
icon: components[uid].info.icon,
|
1002
|
+
displayName: components[uid].info.displayName
|
922
1003
|
}
|
923
|
-
|
924
|
-
|
925
|
-
title: formatMessage({
|
926
|
-
id: getTranslation("success.records.delete"),
|
927
|
-
defaultMessage: "Successfully deleted."
|
928
|
-
}),
|
929
|
-
message: ""
|
930
|
-
});
|
931
|
-
trackUsage("didBulkDeleteEntries");
|
932
|
-
return res.data;
|
933
|
-
} catch (err) {
|
934
|
-
toggleNotification({
|
935
|
-
type: "danger",
|
936
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
937
|
-
});
|
938
|
-
trackUsage("didNotBulkDeleteEntries");
|
939
|
-
throw err;
|
940
|
-
}
|
1004
|
+
};
|
1005
|
+
return acc;
|
941
1006
|
},
|
942
|
-
|
1007
|
+
{}
|
943
1008
|
);
|
944
|
-
const
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
model,
|
951
|
-
documentId,
|
952
|
-
params
|
953
|
-
});
|
954
|
-
if ("error" in res) {
|
955
|
-
toggleNotification({
|
956
|
-
type: "danger",
|
957
|
-
message: formatAPIError(res.error)
|
958
|
-
});
|
959
|
-
return { error: res.error };
|
960
|
-
}
|
961
|
-
toggleNotification({
|
962
|
-
type: "success",
|
963
|
-
message: formatMessage({
|
964
|
-
id: "content-manager.success.record.discard",
|
965
|
-
defaultMessage: "Changes discarded"
|
966
|
-
})
|
967
|
-
});
|
968
|
-
return res.data;
|
969
|
-
} catch (err) {
|
970
|
-
toggleNotification({
|
971
|
-
type: "danger",
|
972
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
973
|
-
});
|
974
|
-
throw err;
|
975
|
-
}
|
1009
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1010
|
+
(acc, [attribute, metadata]) => {
|
1011
|
+
return {
|
1012
|
+
...acc,
|
1013
|
+
[attribute]: metadata.edit
|
1014
|
+
};
|
976
1015
|
},
|
977
|
-
|
1016
|
+
{}
|
978
1017
|
);
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
model,
|
987
|
-
documentId,
|
988
|
-
data,
|
989
|
-
params
|
990
|
-
});
|
991
|
-
if ("error" in res) {
|
992
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
993
|
-
return { error: res.error };
|
994
|
-
}
|
995
|
-
trackUsage("didPublishEntry");
|
996
|
-
toggleNotification({
|
997
|
-
type: "success",
|
998
|
-
message: formatMessage({
|
999
|
-
id: getTranslation("success.record.publish"),
|
1000
|
-
defaultMessage: "Published document"
|
1001
|
-
})
|
1002
|
-
});
|
1003
|
-
return res.data;
|
1004
|
-
} catch (err) {
|
1005
|
-
toggleNotification({
|
1006
|
-
type: "danger",
|
1007
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1008
|
-
});
|
1009
|
-
throw err;
|
1010
|
-
}
|
1018
|
+
return {
|
1019
|
+
layout: panelledEditAttributes,
|
1020
|
+
components: componentEditAttributes,
|
1021
|
+
metadatas: editMetadatas,
|
1022
|
+
settings: {
|
1023
|
+
...data.contentType.settings,
|
1024
|
+
displayName: schema?.info.displayName
|
1011
1025
|
},
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
return { error: res.error };
|
1026
|
-
}
|
1027
|
-
toggleNotification({
|
1028
|
-
type: "success",
|
1029
|
-
message: formatMessage({
|
1030
|
-
id: getTranslation("success.record.publish"),
|
1031
|
-
defaultMessage: "Published document"
|
1032
|
-
})
|
1033
|
-
});
|
1034
|
-
return res.data;
|
1035
|
-
} catch (err) {
|
1036
|
-
toggleNotification({
|
1037
|
-
type: "danger",
|
1038
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1039
|
-
});
|
1040
|
-
throw err;
|
1026
|
+
options: {
|
1027
|
+
...schema?.options,
|
1028
|
+
...schema?.pluginOptions,
|
1029
|
+
...data.contentType.options
|
1030
|
+
}
|
1031
|
+
};
|
1032
|
+
};
|
1033
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1034
|
+
return rows.map(
|
1035
|
+
(row) => row.map((field) => {
|
1036
|
+
const attribute = attributes[field.name];
|
1037
|
+
if (!attribute) {
|
1038
|
+
return null;
|
1041
1039
|
}
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1040
|
+
const { edit: metadata } = metadatas[field.name];
|
1041
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1042
|
+
return {
|
1043
|
+
attribute,
|
1044
|
+
disabled: !metadata.editable,
|
1045
|
+
hint: metadata.description,
|
1046
|
+
label: metadata.label ?? "",
|
1047
|
+
name: field.name,
|
1048
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1049
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1050
|
+
schemas,
|
1051
|
+
components: components?.schemas ?? {}
|
1052
|
+
}),
|
1053
|
+
placeholder: metadata.placeholder ?? "",
|
1054
|
+
required: attribute.required ?? false,
|
1055
|
+
size: field.size,
|
1056
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1057
|
+
visible: metadata.visible ?? true,
|
1058
|
+
type: attribute.type
|
1059
|
+
};
|
1060
|
+
}).filter((field) => field !== null)
|
1050
1061
|
);
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1062
|
+
};
|
1063
|
+
const formatListLayout = (data, {
|
1064
|
+
schemas,
|
1065
|
+
schema,
|
1066
|
+
components
|
1067
|
+
}) => {
|
1068
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1069
|
+
(acc, [attribute, metadata]) => {
|
1070
|
+
return {
|
1071
|
+
...acc,
|
1072
|
+
[attribute]: metadata.list
|
1073
|
+
};
|
1074
|
+
},
|
1075
|
+
{}
|
1076
|
+
);
|
1077
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1078
|
+
data.contentType.layouts.list,
|
1079
|
+
schema?.attributes,
|
1080
|
+
listMetadatas,
|
1081
|
+
{ configurations: data.components, schemas: components },
|
1082
|
+
schemas
|
1083
|
+
);
|
1084
|
+
return {
|
1085
|
+
layout: listAttributes,
|
1086
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1087
|
+
metadatas: listMetadatas,
|
1088
|
+
options: {
|
1089
|
+
...schema?.options,
|
1090
|
+
...schema?.pluginOptions,
|
1091
|
+
...data.contentType.options
|
1092
|
+
}
|
1093
|
+
};
|
1094
|
+
};
|
1095
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1096
|
+
return columns.map((name) => {
|
1097
|
+
const attribute = attributes[name];
|
1098
|
+
if (!attribute) {
|
1099
|
+
return null;
|
1100
|
+
}
|
1101
|
+
const metadata = metadatas[name];
|
1102
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1103
|
+
return {
|
1104
|
+
attribute,
|
1105
|
+
label: metadata.label ?? "",
|
1106
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1107
|
+
schemas,
|
1108
|
+
components: components?.schemas ?? {}
|
1109
|
+
}),
|
1110
|
+
name,
|
1111
|
+
searchable: metadata.searchable ?? true,
|
1112
|
+
sortable: metadata.sortable ?? true
|
1113
|
+
};
|
1114
|
+
}).filter((field) => field !== null);
|
1115
|
+
};
|
1116
|
+
const useDocument = (args, opts) => {
|
1117
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1118
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1119
|
+
const {
|
1120
|
+
currentData: data,
|
1121
|
+
isLoading: isLoadingDocument,
|
1122
|
+
isFetching: isFetchingDocument,
|
1123
|
+
error
|
1124
|
+
} = useGetDocumentQuery(args, {
|
1125
|
+
...opts,
|
1126
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1127
|
+
});
|
1128
|
+
const {
|
1129
|
+
components,
|
1130
|
+
schema,
|
1131
|
+
schemas,
|
1132
|
+
isLoading: isLoadingSchema
|
1133
|
+
} = useContentTypeSchema(args.model);
|
1134
|
+
React__namespace.useEffect(() => {
|
1135
|
+
if (error) {
|
1136
|
+
toggleNotification({
|
1137
|
+
type: "danger",
|
1138
|
+
message: formatAPIError(error)
|
1139
|
+
});
|
1140
|
+
}
|
1141
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1142
|
+
const validationSchema = React__namespace.useMemo(() => {
|
1143
|
+
if (!schema) {
|
1144
|
+
return null;
|
1145
|
+
}
|
1146
|
+
return createYupSchema(schema.attributes, components);
|
1147
|
+
}, [schema, components]);
|
1148
|
+
const validate = React__namespace.useCallback(
|
1149
|
+
(document) => {
|
1150
|
+
if (!validationSchema) {
|
1151
|
+
throw new Error(
|
1152
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1153
|
+
);
|
1154
|
+
}
|
1155
|
+
try {
|
1156
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1157
|
+
return null;
|
1158
|
+
} catch (error2) {
|
1159
|
+
if (error2 instanceof yup.ValidationError) {
|
1160
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
1067
1161
|
}
|
1068
|
-
|
1069
|
-
toggleNotification({
|
1070
|
-
type: "success",
|
1071
|
-
message: formatMessage({
|
1072
|
-
id: getTranslation("success.record.save"),
|
1073
|
-
defaultMessage: "Saved document"
|
1074
|
-
})
|
1075
|
-
});
|
1076
|
-
return res.data;
|
1077
|
-
} catch (err) {
|
1078
|
-
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1079
|
-
toggleNotification({
|
1080
|
-
type: "danger",
|
1081
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1082
|
-
});
|
1083
|
-
throw err;
|
1162
|
+
throw error2;
|
1084
1163
|
}
|
1085
1164
|
},
|
1086
|
-
[
|
1165
|
+
[validationSchema]
|
1087
1166
|
);
|
1088
|
-
const
|
1089
|
-
|
1090
|
-
|
1167
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1168
|
+
return {
|
1169
|
+
components,
|
1170
|
+
document: data?.data,
|
1171
|
+
meta: data?.meta,
|
1172
|
+
isLoading,
|
1173
|
+
schema,
|
1174
|
+
schemas,
|
1175
|
+
validate
|
1176
|
+
};
|
1177
|
+
};
|
1178
|
+
const useDoc = () => {
|
1179
|
+
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
1180
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
1181
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1182
|
+
if (!collectionType) {
|
1183
|
+
throw new Error("Could not find collectionType in url params");
|
1184
|
+
}
|
1185
|
+
if (!slug) {
|
1186
|
+
throw new Error("Could not find model in url params");
|
1187
|
+
}
|
1188
|
+
return {
|
1189
|
+
collectionType,
|
1190
|
+
model: slug,
|
1191
|
+
id: origin || id === "create" ? void 0 : id,
|
1192
|
+
...useDocument(
|
1193
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1194
|
+
{
|
1195
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1196
|
+
}
|
1197
|
+
)
|
1198
|
+
};
|
1199
|
+
};
|
1200
|
+
const useContentManagerContext = () => {
|
1201
|
+
const {
|
1202
|
+
collectionType,
|
1203
|
+
model,
|
1204
|
+
id,
|
1205
|
+
components,
|
1206
|
+
isLoading: isLoadingDoc,
|
1207
|
+
schema,
|
1208
|
+
schemas
|
1209
|
+
} = useDoc();
|
1210
|
+
const layout = useDocumentLayout(model);
|
1211
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1212
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1213
|
+
const slug = model;
|
1214
|
+
const isCreatingEntry = id === "create";
|
1215
|
+
useContentTypeSchema();
|
1216
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1217
|
+
const error = layout.error;
|
1218
|
+
return {
|
1219
|
+
error,
|
1220
|
+
isLoading,
|
1221
|
+
// Base metadata
|
1222
|
+
model,
|
1223
|
+
collectionType,
|
1224
|
+
id,
|
1225
|
+
slug,
|
1226
|
+
isCreatingEntry,
|
1227
|
+
isSingleType,
|
1228
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1229
|
+
// All schema infos
|
1230
|
+
components,
|
1231
|
+
contentType: schema,
|
1232
|
+
contentTypes: schemas,
|
1233
|
+
// Form state
|
1234
|
+
form,
|
1235
|
+
// layout infos
|
1236
|
+
layout
|
1237
|
+
};
|
1238
|
+
};
|
1239
|
+
const prefixPluginTranslations = (trad, pluginId) => {
|
1240
|
+
if (!pluginId) {
|
1241
|
+
throw new TypeError("pluginId can't be empty");
|
1242
|
+
}
|
1243
|
+
return Object.keys(trad).reduce((acc, current) => {
|
1244
|
+
acc[`${pluginId}.${current}`] = trad[current];
|
1245
|
+
return acc;
|
1246
|
+
}, {});
|
1247
|
+
};
|
1248
|
+
const getTranslation = (id) => `content-manager.${id}`;
|
1249
|
+
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
1250
|
+
id: "notification.error",
|
1251
|
+
defaultMessage: "An error occurred, please try again"
|
1252
|
+
};
|
1253
|
+
const useDocumentActions = () => {
|
1254
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1255
|
+
const { formatMessage } = reactIntl.useIntl();
|
1256
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
1257
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1258
|
+
const navigate = reactRouterDom.useNavigate();
|
1259
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
1260
|
+
const [deleteDocument] = useDeleteDocumentMutation();
|
1261
|
+
const _delete = React__namespace.useCallback(
|
1262
|
+
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
1091
1263
|
try {
|
1092
|
-
trackUsage("
|
1093
|
-
const res = await
|
1264
|
+
trackUsage("willDeleteEntry", trackerProperty);
|
1265
|
+
const res = await deleteDocument({
|
1094
1266
|
collectionType,
|
1095
1267
|
model,
|
1096
1268
|
documentId,
|
1097
|
-
params
|
1098
|
-
data: {
|
1099
|
-
discardDraft
|
1100
|
-
}
|
1269
|
+
params
|
1101
1270
|
});
|
1102
1271
|
if ("error" in res) {
|
1103
|
-
toggleNotification({
|
1272
|
+
toggleNotification({
|
1273
|
+
type: "danger",
|
1274
|
+
message: formatAPIError(res.error)
|
1275
|
+
});
|
1104
1276
|
return { error: res.error };
|
1105
1277
|
}
|
1106
|
-
trackUsage("didUnpublishEntry");
|
1107
1278
|
toggleNotification({
|
1108
1279
|
type: "success",
|
1109
1280
|
message: formatMessage({
|
1110
|
-
id: getTranslation("success.record.
|
1111
|
-
defaultMessage: "
|
1281
|
+
id: getTranslation("success.record.delete"),
|
1282
|
+
defaultMessage: "Deleted document"
|
1112
1283
|
})
|
1113
1284
|
});
|
1285
|
+
trackUsage("didDeleteEntry", trackerProperty);
|
1114
1286
|
return res.data;
|
1115
1287
|
} catch (err) {
|
1116
1288
|
toggleNotification({
|
1117
1289
|
type: "danger",
|
1118
1290
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1119
1291
|
});
|
1292
|
+
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
1120
1293
|
throw err;
|
1121
1294
|
}
|
1122
1295
|
},
|
1123
|
-
[trackUsage,
|
1296
|
+
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
1124
1297
|
);
|
1125
|
-
const [
|
1126
|
-
const
|
1298
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1299
|
+
const deleteMany = React__namespace.useCallback(
|
1127
1300
|
async ({ model, documentIds, params }) => {
|
1128
1301
|
try {
|
1129
|
-
trackUsage("
|
1130
|
-
const res = await
|
1302
|
+
trackUsage("willBulkDeleteEntries");
|
1303
|
+
const res = await deleteManyDocuments({
|
1131
1304
|
model,
|
1132
1305
|
documentIds,
|
1133
1306
|
params
|
1134
1307
|
});
|
1135
1308
|
if ("error" in res) {
|
1136
|
-
toggleNotification({
|
1309
|
+
toggleNotification({
|
1310
|
+
type: "danger",
|
1311
|
+
message: formatAPIError(res.error)
|
1312
|
+
});
|
1137
1313
|
return { error: res.error };
|
1138
1314
|
}
|
1139
|
-
trackUsage("didBulkUnpublishEntries");
|
1140
1315
|
toggleNotification({
|
1141
1316
|
type: "success",
|
1142
1317
|
title: formatMessage({
|
1143
|
-
id: getTranslation("success.records.
|
1144
|
-
defaultMessage: "Successfully
|
1318
|
+
id: getTranslation("success.records.delete"),
|
1319
|
+
defaultMessage: "Successfully deleted."
|
1145
1320
|
}),
|
1146
1321
|
message: ""
|
1147
1322
|
});
|
1323
|
+
trackUsage("didBulkDeleteEntries");
|
1148
1324
|
return res.data;
|
1149
1325
|
} catch (err) {
|
1150
1326
|
toggleNotification({
|
1151
1327
|
type: "danger",
|
1152
1328
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1153
1329
|
});
|
1154
|
-
trackUsage("
|
1330
|
+
trackUsage("didNotBulkDeleteEntries");
|
1155
1331
|
throw err;
|
1156
1332
|
}
|
1157
1333
|
},
|
1158
|
-
[trackUsage,
|
1334
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1159
1335
|
);
|
1160
|
-
const [
|
1161
|
-
const
|
1162
|
-
async ({ model, params }
|
1336
|
+
const [discardDocument] = useDiscardDocumentMutation();
|
1337
|
+
const discard = React__namespace.useCallback(
|
1338
|
+
async ({ collectionType, model, documentId, params }) => {
|
1163
1339
|
try {
|
1164
|
-
const res = await
|
1340
|
+
const res = await discardDocument({
|
1341
|
+
collectionType,
|
1165
1342
|
model,
|
1166
|
-
|
1343
|
+
documentId,
|
1167
1344
|
params
|
1168
1345
|
});
|
1169
1346
|
if ("error" in res) {
|
1170
|
-
toggleNotification({
|
1171
|
-
|
1172
|
-
|
1347
|
+
toggleNotification({
|
1348
|
+
type: "danger",
|
1349
|
+
message: formatAPIError(res.error)
|
1350
|
+
});
|
1351
|
+
return { error: res.error };
|
1352
|
+
}
|
1353
|
+
toggleNotification({
|
1354
|
+
type: "success",
|
1355
|
+
message: formatMessage({
|
1356
|
+
id: "content-manager.success.record.discard",
|
1357
|
+
defaultMessage: "Changes discarded"
|
1358
|
+
})
|
1359
|
+
});
|
1360
|
+
return res.data;
|
1361
|
+
} catch (err) {
|
1362
|
+
toggleNotification({
|
1363
|
+
type: "danger",
|
1364
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1365
|
+
});
|
1366
|
+
throw err;
|
1367
|
+
}
|
1368
|
+
},
|
1369
|
+
[discardDocument, formatAPIError, formatMessage, toggleNotification]
|
1370
|
+
);
|
1371
|
+
const [publishDocument] = usePublishDocumentMutation();
|
1372
|
+
const publish = React__namespace.useCallback(
|
1373
|
+
async ({ collectionType, model, documentId, params }, data) => {
|
1374
|
+
try {
|
1375
|
+
trackUsage("willPublishEntry");
|
1376
|
+
const res = await publishDocument({
|
1377
|
+
collectionType,
|
1378
|
+
model,
|
1379
|
+
documentId,
|
1380
|
+
data,
|
1381
|
+
params
|
1382
|
+
});
|
1383
|
+
if ("error" in res) {
|
1384
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1385
|
+
return { error: res.error };
|
1386
|
+
}
|
1387
|
+
trackUsage("didPublishEntry");
|
1388
|
+
toggleNotification({
|
1389
|
+
type: "success",
|
1390
|
+
message: formatMessage({
|
1391
|
+
id: getTranslation("success.record.publish"),
|
1392
|
+
defaultMessage: "Published document"
|
1393
|
+
})
|
1394
|
+
});
|
1395
|
+
return res.data;
|
1396
|
+
} catch (err) {
|
1397
|
+
toggleNotification({
|
1398
|
+
type: "danger",
|
1399
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1400
|
+
});
|
1401
|
+
throw err;
|
1402
|
+
}
|
1403
|
+
},
|
1404
|
+
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1405
|
+
);
|
1406
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1407
|
+
const publishMany = React__namespace.useCallback(
|
1408
|
+
async ({ model, documentIds, params }) => {
|
1409
|
+
try {
|
1410
|
+
const res = await publishManyDocuments({
|
1411
|
+
model,
|
1412
|
+
documentIds,
|
1413
|
+
params
|
1414
|
+
});
|
1415
|
+
if ("error" in res) {
|
1416
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1417
|
+
return { error: res.error };
|
1418
|
+
}
|
1419
|
+
toggleNotification({
|
1420
|
+
type: "success",
|
1421
|
+
message: formatMessage({
|
1422
|
+
id: getTranslation("success.record.publish"),
|
1423
|
+
defaultMessage: "Published document"
|
1424
|
+
})
|
1425
|
+
});
|
1426
|
+
return res.data;
|
1427
|
+
} catch (err) {
|
1428
|
+
toggleNotification({
|
1429
|
+
type: "danger",
|
1430
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1431
|
+
});
|
1432
|
+
throw err;
|
1433
|
+
}
|
1434
|
+
},
|
1435
|
+
[
|
1436
|
+
// trackUsage,
|
1437
|
+
publishManyDocuments,
|
1438
|
+
toggleNotification,
|
1439
|
+
formatMessage,
|
1440
|
+
formatAPIError
|
1441
|
+
]
|
1442
|
+
);
|
1443
|
+
const [updateDocument] = useUpdateDocumentMutation();
|
1444
|
+
const update = React__namespace.useCallback(
|
1445
|
+
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
1446
|
+
try {
|
1447
|
+
trackUsage("willEditEntry", trackerProperty);
|
1448
|
+
const res = await updateDocument({
|
1449
|
+
collectionType,
|
1450
|
+
model,
|
1451
|
+
documentId,
|
1452
|
+
data,
|
1453
|
+
params
|
1454
|
+
});
|
1455
|
+
if ("error" in res) {
|
1456
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1457
|
+
trackUsage("didNotEditEntry", { error: res.error, ...trackerProperty });
|
1458
|
+
return { error: res.error };
|
1459
|
+
}
|
1460
|
+
trackUsage("didEditEntry", trackerProperty);
|
1461
|
+
toggleNotification({
|
1462
|
+
type: "success",
|
1463
|
+
message: formatMessage({
|
1464
|
+
id: getTranslation("success.record.save"),
|
1465
|
+
defaultMessage: "Saved document"
|
1466
|
+
})
|
1467
|
+
});
|
1468
|
+
return res.data;
|
1469
|
+
} catch (err) {
|
1470
|
+
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1471
|
+
toggleNotification({
|
1472
|
+
type: "danger",
|
1473
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1474
|
+
});
|
1475
|
+
throw err;
|
1476
|
+
}
|
1477
|
+
},
|
1478
|
+
[trackUsage, updateDocument, toggleNotification, formatMessage, formatAPIError]
|
1479
|
+
);
|
1480
|
+
const [unpublishDocument] = useUnpublishDocumentMutation();
|
1481
|
+
const unpublish = React__namespace.useCallback(
|
1482
|
+
async ({ collectionType, model, documentId, params }, discardDraft = false) => {
|
1483
|
+
try {
|
1484
|
+
trackUsage("willUnpublishEntry");
|
1485
|
+
const res = await unpublishDocument({
|
1486
|
+
collectionType,
|
1487
|
+
model,
|
1488
|
+
documentId,
|
1489
|
+
params,
|
1490
|
+
data: {
|
1491
|
+
discardDraft
|
1492
|
+
}
|
1493
|
+
});
|
1494
|
+
if ("error" in res) {
|
1495
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1496
|
+
return { error: res.error };
|
1497
|
+
}
|
1498
|
+
trackUsage("didUnpublishEntry");
|
1499
|
+
toggleNotification({
|
1500
|
+
type: "success",
|
1501
|
+
message: formatMessage({
|
1502
|
+
id: getTranslation("success.record.unpublish"),
|
1503
|
+
defaultMessage: "Unpublished document"
|
1504
|
+
})
|
1505
|
+
});
|
1506
|
+
return res.data;
|
1507
|
+
} catch (err) {
|
1508
|
+
toggleNotification({
|
1509
|
+
type: "danger",
|
1510
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1511
|
+
});
|
1512
|
+
throw err;
|
1513
|
+
}
|
1514
|
+
},
|
1515
|
+
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1516
|
+
);
|
1517
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1518
|
+
const unpublishMany = React__namespace.useCallback(
|
1519
|
+
async ({ model, documentIds, params }) => {
|
1520
|
+
try {
|
1521
|
+
trackUsage("willBulkUnpublishEntries");
|
1522
|
+
const res = await unpublishManyDocuments({
|
1523
|
+
model,
|
1524
|
+
documentIds,
|
1525
|
+
params
|
1526
|
+
});
|
1527
|
+
if ("error" in res) {
|
1528
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1529
|
+
return { error: res.error };
|
1530
|
+
}
|
1531
|
+
trackUsage("didBulkUnpublishEntries");
|
1532
|
+
toggleNotification({
|
1533
|
+
type: "success",
|
1534
|
+
title: formatMessage({
|
1535
|
+
id: getTranslation("success.records.unpublish"),
|
1536
|
+
defaultMessage: "Successfully unpublished."
|
1537
|
+
}),
|
1538
|
+
message: ""
|
1539
|
+
});
|
1540
|
+
return res.data;
|
1541
|
+
} catch (err) {
|
1542
|
+
toggleNotification({
|
1543
|
+
type: "danger",
|
1544
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1545
|
+
});
|
1546
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1547
|
+
throw err;
|
1548
|
+
}
|
1549
|
+
},
|
1550
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1551
|
+
);
|
1552
|
+
const [createDocument] = useCreateDocumentMutation();
|
1553
|
+
const create = React__namespace.useCallback(
|
1554
|
+
async ({ model, params }, data, trackerProperty) => {
|
1555
|
+
try {
|
1556
|
+
const res = await createDocument({
|
1557
|
+
model,
|
1558
|
+
data,
|
1559
|
+
params
|
1560
|
+
});
|
1561
|
+
if ("error" in res) {
|
1562
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1563
|
+
trackUsage("didNotCreateEntry", { error: res.error, ...trackerProperty });
|
1564
|
+
return { error: res.error };
|
1173
1565
|
}
|
1174
1566
|
trackUsage("didCreateEntry", trackerProperty);
|
1175
1567
|
toggleNotification({
|
@@ -1179,6 +1571,7 @@ const useDocumentActions = () => {
|
|
1179
1571
|
defaultMessage: "Saved document"
|
1180
1572
|
})
|
1181
1573
|
});
|
1574
|
+
setCurrentStep("contentManager.success");
|
1182
1575
|
return res.data;
|
1183
1576
|
} catch (err) {
|
1184
1577
|
toggleNotification({
|
@@ -1218,7 +1611,7 @@ const useDocumentActions = () => {
|
|
1218
1611
|
throw err;
|
1219
1612
|
}
|
1220
1613
|
},
|
1221
|
-
[autoCloneDocument,
|
1614
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1222
1615
|
);
|
1223
1616
|
const [cloneDocument] = useCloneDocumentMutation();
|
1224
1617
|
const clone = React__namespace.useCallback(
|
@@ -1244,6 +1637,7 @@ const useDocumentActions = () => {
|
|
1244
1637
|
defaultMessage: "Cloned document"
|
1245
1638
|
})
|
1246
1639
|
});
|
1640
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1247
1641
|
return res.data;
|
1248
1642
|
} catch (err) {
|
1249
1643
|
toggleNotification({
|
@@ -1254,7 +1648,7 @@ const useDocumentActions = () => {
|
|
1254
1648
|
throw err;
|
1255
1649
|
}
|
1256
1650
|
},
|
1257
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1651
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1258
1652
|
);
|
1259
1653
|
const [getDoc] = useLazyGetDocumentQuery();
|
1260
1654
|
const getDocument = React__namespace.useCallback(
|
@@ -1280,7 +1674,7 @@ const useDocumentActions = () => {
|
|
1280
1674
|
};
|
1281
1675
|
};
|
1282
1676
|
const ProtectedHistoryPage = React.lazy(
|
1283
|
-
() => Promise.resolve().then(() => require("./History-
|
1677
|
+
() => Promise.resolve().then(() => require("./History-BrJ1tUvt.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1284
1678
|
);
|
1285
1679
|
const routes$1 = [
|
1286
1680
|
{
|
@@ -1293,31 +1687,31 @@ const routes$1 = [
|
|
1293
1687
|
}
|
1294
1688
|
];
|
1295
1689
|
const ProtectedEditViewPage = React.lazy(
|
1296
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1690
|
+
() => Promise.resolve().then(() => require("./EditViewPage-D2QVRr_2.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1297
1691
|
);
|
1298
1692
|
const ProtectedListViewPage = React.lazy(
|
1299
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1693
|
+
() => Promise.resolve().then(() => require("./ListViewPage-Coj-RPsx.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1300
1694
|
);
|
1301
1695
|
const ProtectedListConfiguration = React.lazy(
|
1302
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1696
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-Eane5LKE.js")).then((mod) => ({
|
1303
1697
|
default: mod.ProtectedListConfiguration
|
1304
1698
|
}))
|
1305
1699
|
);
|
1306
1700
|
const ProtectedEditConfigurationPage = React.lazy(
|
1307
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1701
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-CpLj5gYZ.js")).then((mod) => ({
|
1308
1702
|
default: mod.ProtectedEditConfigurationPage
|
1309
1703
|
}))
|
1310
1704
|
);
|
1311
1705
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1312
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1706
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-DnnZJc1F.js")).then((mod) => ({
|
1313
1707
|
default: mod.ProtectedComponentConfigurationPage
|
1314
1708
|
}))
|
1315
1709
|
);
|
1316
1710
|
const NoPermissions = React.lazy(
|
1317
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1711
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-BOtb5FTM.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1318
1712
|
);
|
1319
1713
|
const NoContentType = React.lazy(
|
1320
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1714
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-BDJ0dshy.js")).then((mod) => ({ default: mod.NoContentType }))
|
1321
1715
|
);
|
1322
1716
|
const CollectionTypePages = () => {
|
1323
1717
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1360,1064 +1754,746 @@ const routes = [
|
|
1360
1754
|
Component: NoPermissions
|
1361
1755
|
},
|
1362
1756
|
{
|
1363
|
-
path: "no-content-types",
|
1364
|
-
Component: NoContentType
|
1365
|
-
},
|
1366
|
-
...routes$1
|
1367
|
-
];
|
1368
|
-
const DocumentActions = ({ actions: actions2 }) => {
|
1369
|
-
const { formatMessage } = reactIntl.useIntl();
|
1370
|
-
const [primaryAction, secondaryAction, ...restActions] = actions2.filter((action) => {
|
1371
|
-
if (action.position === void 0) {
|
1372
|
-
return true;
|
1373
|
-
}
|
1374
|
-
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
1375
|
-
return positions.includes("panel");
|
1376
|
-
});
|
1377
|
-
if (!primaryAction) {
|
1378
|
-
return null;
|
1379
|
-
}
|
1380
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, alignItems: "stretch", width: "100%", children: [
|
1381
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
1382
|
-
/* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...primaryAction, variant: primaryAction.variant || "default" }),
|
1383
|
-
restActions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
1384
|
-
DocumentActionsMenu,
|
1385
|
-
{
|
1386
|
-
actions: restActions,
|
1387
|
-
label: formatMessage({
|
1388
|
-
id: "content-manager.containers.edit.panels.default.more-actions",
|
1389
|
-
defaultMessage: "More document actions"
|
1390
|
-
})
|
1391
|
-
}
|
1392
|
-
) : null
|
1393
|
-
] }),
|
1394
|
-
secondaryAction ? /* @__PURE__ */ jsxRuntime.jsx(
|
1395
|
-
DocumentActionButton,
|
1396
|
-
{
|
1397
|
-
...secondaryAction,
|
1398
|
-
variant: secondaryAction.variant || "secondary"
|
1399
|
-
}
|
1400
|
-
) : null
|
1401
|
-
] });
|
1402
|
-
};
|
1403
|
-
const DocumentActionButton = (action) => {
|
1404
|
-
const [dialogId, setDialogId] = React__namespace.useState(null);
|
1405
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
1406
|
-
const handleClick = (action2) => async (e) => {
|
1407
|
-
const { onClick = () => false, dialog, id } = action2;
|
1408
|
-
const muteDialog = await onClick(e);
|
1409
|
-
if (dialog && !muteDialog) {
|
1410
|
-
switch (dialog.type) {
|
1411
|
-
case "notification":
|
1412
|
-
toggleNotification({
|
1413
|
-
title: dialog.title,
|
1414
|
-
message: dialog.content,
|
1415
|
-
type: dialog.status,
|
1416
|
-
timeout: dialog.timeout,
|
1417
|
-
onClose: dialog.onClose
|
1418
|
-
});
|
1419
|
-
break;
|
1420
|
-
case "dialog":
|
1421
|
-
case "modal":
|
1422
|
-
e.preventDefault();
|
1423
|
-
setDialogId(id);
|
1424
|
-
}
|
1425
|
-
}
|
1426
|
-
};
|
1427
|
-
const handleClose = () => {
|
1428
|
-
setDialogId(null);
|
1429
|
-
};
|
1430
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
1431
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1432
|
-
designSystem.Button,
|
1433
|
-
{
|
1434
|
-
flex: 1,
|
1435
|
-
startIcon: action.icon,
|
1436
|
-
disabled: action.disabled,
|
1437
|
-
onClick: handleClick(action),
|
1438
|
-
justifyContent: "center",
|
1439
|
-
variant: action.variant || "default",
|
1440
|
-
children: action.label
|
1441
|
-
}
|
1442
|
-
),
|
1443
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1444
|
-
DocumentActionConfirmDialog,
|
1445
|
-
{
|
1446
|
-
...action.dialog,
|
1447
|
-
variant: action.dialog?.variant ?? action.variant,
|
1448
|
-
isOpen: dialogId === action.id,
|
1449
|
-
onClose: handleClose
|
1450
|
-
}
|
1451
|
-
) : null,
|
1452
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1453
|
-
DocumentActionModal,
|
1454
|
-
{
|
1455
|
-
...action.dialog,
|
1456
|
-
onModalClose: handleClose,
|
1457
|
-
isOpen: dialogId === action.id
|
1458
|
-
}
|
1459
|
-
) : null
|
1460
|
-
] });
|
1461
|
-
};
|
1462
|
-
const DocumentActionsMenu = ({
|
1463
|
-
actions: actions2,
|
1464
|
-
children,
|
1465
|
-
label,
|
1466
|
-
variant = "tertiary"
|
1467
|
-
}) => {
|
1468
|
-
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
1469
|
-
const [dialogId, setDialogId] = React__namespace.useState(null);
|
1470
|
-
const { formatMessage } = reactIntl.useIntl();
|
1471
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
1472
|
-
const isDisabled = actions2.every((action) => action.disabled) || actions2.length === 0;
|
1473
|
-
const handleClick = (action) => async (e) => {
|
1474
|
-
const { onClick = () => false, dialog, id } = action;
|
1475
|
-
const muteDialog = await onClick(e);
|
1476
|
-
if (dialog && !muteDialog) {
|
1477
|
-
switch (dialog.type) {
|
1478
|
-
case "notification":
|
1479
|
-
toggleNotification({
|
1480
|
-
title: dialog.title,
|
1481
|
-
message: dialog.content,
|
1482
|
-
type: dialog.status,
|
1483
|
-
timeout: dialog.timeout,
|
1484
|
-
onClose: dialog.onClose
|
1485
|
-
});
|
1486
|
-
break;
|
1487
|
-
case "dialog":
|
1488
|
-
case "modal":
|
1489
|
-
setDialogId(id);
|
1490
|
-
}
|
1491
|
-
}
|
1492
|
-
};
|
1493
|
-
const handleClose = () => {
|
1494
|
-
setDialogId(null);
|
1495
|
-
setIsOpen(false);
|
1496
|
-
};
|
1497
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1498
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
1499
|
-
designSystem.Menu.Trigger,
|
1500
|
-
{
|
1501
|
-
disabled: isDisabled,
|
1502
|
-
size: "S",
|
1503
|
-
endIcon: null,
|
1504
|
-
paddingTop: "7px",
|
1505
|
-
paddingLeft: "9px",
|
1506
|
-
paddingRight: "9px",
|
1507
|
-
variant,
|
1508
|
-
children: [
|
1509
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
1510
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1511
|
-
id: "content-manager.containers.edit.panels.default.more-actions",
|
1512
|
-
defaultMessage: "More document actions"
|
1513
|
-
}) })
|
1514
|
-
]
|
1515
|
-
}
|
1516
|
-
),
|
1517
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1518
|
-
actions2.map((action) => {
|
1519
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
1520
|
-
designSystem.Menu.Item,
|
1521
|
-
{
|
1522
|
-
disabled: action.disabled,
|
1523
|
-
onSelect: handleClick(action),
|
1524
|
-
display: "block",
|
1525
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
1526
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
|
1527
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
|
1528
|
-
action.label
|
1529
|
-
] }),
|
1530
|
-
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1531
|
-
designSystem.Flex,
|
1532
|
-
{
|
1533
|
-
alignItems: "center",
|
1534
|
-
background: "alternative100",
|
1535
|
-
borderStyle: "solid",
|
1536
|
-
borderColor: "alternative200",
|
1537
|
-
borderWidth: "1px",
|
1538
|
-
height: 5,
|
1539
|
-
paddingLeft: 2,
|
1540
|
-
paddingRight: 2,
|
1541
|
-
hasRadius: true,
|
1542
|
-
color: "alternative600",
|
1543
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1544
|
-
}
|
1545
|
-
)
|
1546
|
-
] })
|
1547
|
-
},
|
1548
|
-
action.id
|
1549
|
-
);
|
1550
|
-
}),
|
1551
|
-
children
|
1552
|
-
] }),
|
1553
|
-
actions2.map((action) => {
|
1554
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
1555
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1556
|
-
DocumentActionConfirmDialog,
|
1557
|
-
{
|
1558
|
-
...action.dialog,
|
1559
|
-
variant: action.variant,
|
1560
|
-
isOpen: dialogId === action.id,
|
1561
|
-
onClose: handleClose
|
1562
|
-
}
|
1563
|
-
) : null,
|
1564
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1565
|
-
DocumentActionModal,
|
1566
|
-
{
|
1567
|
-
...action.dialog,
|
1568
|
-
onModalClose: handleClose,
|
1569
|
-
isOpen: dialogId === action.id
|
1570
|
-
}
|
1571
|
-
) : null
|
1572
|
-
] }, action.id);
|
1573
|
-
})
|
1574
|
-
] });
|
1575
|
-
};
|
1576
|
-
const convertActionVariantToColor = (variant = "secondary") => {
|
1577
|
-
switch (variant) {
|
1578
|
-
case "danger":
|
1579
|
-
return "danger600";
|
1580
|
-
case "secondary":
|
1581
|
-
return void 0;
|
1582
|
-
case "success":
|
1583
|
-
return "success600";
|
1584
|
-
default:
|
1585
|
-
return "primary600";
|
1586
|
-
}
|
1587
|
-
};
|
1588
|
-
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1589
|
-
switch (variant) {
|
1590
|
-
case "danger":
|
1591
|
-
return "danger600";
|
1592
|
-
case "secondary":
|
1593
|
-
return "neutral500";
|
1594
|
-
case "success":
|
1595
|
-
return "success600";
|
1596
|
-
default:
|
1597
|
-
return "primary600";
|
1598
|
-
}
|
1599
|
-
};
|
1600
|
-
const DocumentActionConfirmDialog = ({
|
1601
|
-
onClose,
|
1602
|
-
onCancel,
|
1603
|
-
onConfirm,
|
1604
|
-
title,
|
1605
|
-
content,
|
1606
|
-
isOpen,
|
1607
|
-
variant = "secondary"
|
1608
|
-
}) => {
|
1609
|
-
const { formatMessage } = reactIntl.useIntl();
|
1610
|
-
const handleClose = async () => {
|
1611
|
-
if (onCancel) {
|
1612
|
-
await onCancel();
|
1613
|
-
}
|
1614
|
-
onClose();
|
1615
|
-
};
|
1616
|
-
const handleConfirm = async () => {
|
1617
|
-
if (onConfirm) {
|
1618
|
-
await onConfirm();
|
1619
|
-
}
|
1620
|
-
onClose();
|
1621
|
-
};
|
1622
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
1623
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
1624
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
1625
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
1626
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
|
1627
|
-
id: "app.components.Button.cancel",
|
1628
|
-
defaultMessage: "Cancel"
|
1629
|
-
}) }) }),
|
1630
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
|
1631
|
-
id: "app.components.Button.confirm",
|
1632
|
-
defaultMessage: "Confirm"
|
1633
|
-
}) })
|
1634
|
-
] })
|
1635
|
-
] }) });
|
1636
|
-
};
|
1637
|
-
const DocumentActionModal = ({
|
1638
|
-
isOpen,
|
1639
|
-
title,
|
1640
|
-
onClose,
|
1641
|
-
footer: Footer,
|
1642
|
-
content: Content,
|
1643
|
-
onModalClose
|
1644
|
-
}) => {
|
1645
|
-
const handleClose = () => {
|
1646
|
-
if (onClose) {
|
1647
|
-
onClose();
|
1648
|
-
}
|
1649
|
-
onModalClose();
|
1650
|
-
};
|
1651
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
|
1652
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
|
1653
|
-
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
|
1654
|
-
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
1655
|
-
] }) });
|
1656
|
-
};
|
1657
|
-
const PublishAction$1 = ({
|
1658
|
-
activeTab,
|
1659
|
-
documentId,
|
1660
|
-
model,
|
1661
|
-
collectionType,
|
1662
|
-
meta,
|
1663
|
-
document
|
1664
|
-
}) => {
|
1665
|
-
const { schema } = useDoc();
|
1666
|
-
const navigate = reactRouterDom.useNavigate();
|
1667
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
1668
|
-
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
1669
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
1670
|
-
const { formatMessage } = reactIntl.useIntl();
|
1671
|
-
const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
|
1672
|
-
"PublishAction",
|
1673
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1674
|
-
);
|
1675
|
-
const { publish } = useDocumentActions();
|
1676
|
-
const [
|
1677
|
-
countDraftRelations,
|
1678
|
-
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
1679
|
-
] = useLazyGetDraftRelationCountQuery();
|
1680
|
-
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
1681
|
-
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1682
|
-
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1683
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1684
|
-
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
1685
|
-
const setSubmitting = strapiAdmin.useForm("PublishAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
1686
|
-
const isSubmitting = strapiAdmin.useForm("PublishAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
1687
|
-
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1688
|
-
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1689
|
-
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
1690
|
-
React__namespace.useEffect(() => {
|
1691
|
-
if (isErrorDraftRelations) {
|
1692
|
-
toggleNotification({
|
1693
|
-
type: "danger",
|
1694
|
-
message: formatMessage({
|
1695
|
-
id: getTranslation("error.records.fetch-draft-relatons"),
|
1696
|
-
defaultMessage: "An error occurred while fetching draft relations on this document."
|
1697
|
-
})
|
1698
|
-
});
|
1699
|
-
}
|
1700
|
-
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
1701
|
-
React__namespace.useEffect(() => {
|
1702
|
-
const localDraftRelations = /* @__PURE__ */ new Set();
|
1703
|
-
const extractDraftRelations = (data) => {
|
1704
|
-
const relations = data.connect || [];
|
1705
|
-
relations.forEach((relation) => {
|
1706
|
-
if (relation.status === "draft") {
|
1707
|
-
localDraftRelations.add(relation.id);
|
1708
|
-
}
|
1709
|
-
});
|
1710
|
-
};
|
1711
|
-
const traverseAndExtract = (data) => {
|
1712
|
-
Object.entries(data).forEach(([key, value]) => {
|
1713
|
-
if (key === "connect" && Array.isArray(value)) {
|
1714
|
-
extractDraftRelations({ connect: value });
|
1715
|
-
} else if (typeof value === "object" && value !== null) {
|
1716
|
-
traverseAndExtract(value);
|
1717
|
-
}
|
1718
|
-
});
|
1719
|
-
};
|
1720
|
-
if (!documentId || modified) {
|
1721
|
-
traverseAndExtract(formValues);
|
1722
|
-
setLocalCountOfDraftRelations(localDraftRelations.size);
|
1723
|
-
}
|
1724
|
-
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1725
|
-
React__namespace.useEffect(() => {
|
1726
|
-
if (documentId) {
|
1727
|
-
const fetchDraftRelationsCount = async () => {
|
1728
|
-
const { data, error } = await countDraftRelations({
|
1729
|
-
collectionType,
|
1730
|
-
model,
|
1731
|
-
documentId,
|
1732
|
-
params
|
1733
|
-
});
|
1734
|
-
if (error) {
|
1735
|
-
throw error;
|
1736
|
-
}
|
1737
|
-
if (data) {
|
1738
|
-
setServerCountOfDraftRelations(data.data);
|
1739
|
-
}
|
1740
|
-
};
|
1741
|
-
fetchDraftRelationsCount();
|
1757
|
+
path: "no-content-types",
|
1758
|
+
Component: NoContentType
|
1759
|
+
},
|
1760
|
+
...routes$1
|
1761
|
+
];
|
1762
|
+
const DocumentActions = ({ actions: actions2 }) => {
|
1763
|
+
const { formatMessage } = reactIntl.useIntl();
|
1764
|
+
const [primaryAction, secondaryAction, ...restActions] = actions2.filter((action) => {
|
1765
|
+
if (action.position === void 0) {
|
1766
|
+
return true;
|
1742
1767
|
}
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1768
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
1769
|
+
return positions.includes("panel");
|
1770
|
+
});
|
1771
|
+
if (!primaryAction) {
|
1746
1772
|
return null;
|
1747
1773
|
}
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
toggleNotification({
|
1754
|
-
type: "danger",
|
1755
|
-
message: formatMessage({
|
1756
|
-
id: "content-manager.validation.error",
|
1757
|
-
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1758
|
-
})
|
1759
|
-
});
|
1760
|
-
return;
|
1761
|
-
}
|
1762
|
-
const res = await publish(
|
1763
|
-
{
|
1764
|
-
collectionType,
|
1765
|
-
model,
|
1766
|
-
documentId,
|
1767
|
-
params
|
1768
|
-
},
|
1769
|
-
formValues
|
1770
|
-
);
|
1771
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1772
|
-
navigate({
|
1773
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1774
|
-
search: rawQuery
|
1775
|
-
});
|
1776
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1777
|
-
setErrors(formatValidationErrors(res.error));
|
1778
|
-
}
|
1779
|
-
} finally {
|
1780
|
-
setSubmitting(false);
|
1781
|
-
}
|
1782
|
-
};
|
1783
|
-
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1784
|
-
const hasDraftRelations = totalDraftRelations > 0;
|
1785
|
-
return {
|
1786
|
-
/**
|
1787
|
-
* Disabled when:
|
1788
|
-
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
1789
|
-
* - the form is submitting
|
1790
|
-
* - the active tab is the published tab
|
1791
|
-
* - the document is already published & not modified
|
1792
|
-
* - the document is being created & not modified
|
1793
|
-
* - the user doesn't have the permission to publish
|
1794
|
-
* - the user doesn't have the permission to create a new document
|
1795
|
-
* - the user doesn't have the permission to update the document
|
1796
|
-
*/
|
1797
|
-
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
|
1798
|
-
label: formatMessage({
|
1799
|
-
id: "app.utils.publish",
|
1800
|
-
defaultMessage: "Publish"
|
1801
|
-
}),
|
1802
|
-
onClick: async () => {
|
1803
|
-
if (hasDraftRelations) {
|
1804
|
-
return;
|
1805
|
-
}
|
1806
|
-
await performPublish();
|
1807
|
-
},
|
1808
|
-
dialog: hasDraftRelations ? {
|
1809
|
-
type: "dialog",
|
1810
|
-
variant: "danger",
|
1811
|
-
footer: null,
|
1812
|
-
title: formatMessage({
|
1813
|
-
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
1814
|
-
defaultMessage: "Confirmation"
|
1815
|
-
}),
|
1816
|
-
content: formatMessage(
|
1817
|
-
{
|
1818
|
-
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
1819
|
-
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
1820
|
-
},
|
1774
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, alignItems: "stretch", width: "100%", children: [
|
1775
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
1776
|
+
/* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...primaryAction, variant: primaryAction.variant || "default" }),
|
1777
|
+
restActions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
1778
|
+
DocumentActionsMenu,
|
1821
1779
|
{
|
1822
|
-
|
1780
|
+
actions: restActions,
|
1781
|
+
label: formatMessage({
|
1782
|
+
id: "content-manager.containers.edit.panels.default.more-actions",
|
1783
|
+
defaultMessage: "More document actions"
|
1784
|
+
})
|
1823
1785
|
}
|
1824
|
-
)
|
1825
|
-
|
1826
|
-
|
1786
|
+
) : null
|
1787
|
+
] }),
|
1788
|
+
secondaryAction ? /* @__PURE__ */ jsxRuntime.jsx(
|
1789
|
+
DocumentActionButton,
|
1790
|
+
{
|
1791
|
+
...secondaryAction,
|
1792
|
+
variant: secondaryAction.variant || "secondary"
|
1827
1793
|
}
|
1828
|
-
|
1829
|
-
};
|
1794
|
+
) : null
|
1795
|
+
] });
|
1830
1796
|
};
|
1831
|
-
|
1832
|
-
const
|
1833
|
-
activeTab,
|
1834
|
-
documentId,
|
1835
|
-
model,
|
1836
|
-
collectionType
|
1837
|
-
}) => {
|
1838
|
-
const navigate = reactRouterDom.useNavigate();
|
1797
|
+
const DocumentActionButton = (action) => {
|
1798
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
1839
1799
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1840
|
-
const
|
1841
|
-
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
|
1846
|
-
canUpdate: canUpdate2
|
1847
|
-
}));
|
1848
|
-
const { create, update, clone } = useDocumentActions();
|
1849
|
-
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1850
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1851
|
-
const isSubmitting = strapiAdmin.useForm("UpdateAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
1852
|
-
const modified = strapiAdmin.useForm("UpdateAction", ({ modified: modified2 }) => modified2);
|
1853
|
-
const setSubmitting = strapiAdmin.useForm("UpdateAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
1854
|
-
const document = strapiAdmin.useForm("UpdateAction", ({ values }) => values);
|
1855
|
-
const validate = strapiAdmin.useForm("UpdateAction", (state) => state.validate);
|
1856
|
-
const setErrors = strapiAdmin.useForm("UpdateAction", (state) => state.setErrors);
|
1857
|
-
const resetForm = strapiAdmin.useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
1858
|
-
return {
|
1859
|
-
/**
|
1860
|
-
* Disabled when:
|
1861
|
-
* - the form is submitting
|
1862
|
-
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1863
|
-
* - the active tab is the published tab
|
1864
|
-
* - the user doesn't have the permission to create a new document
|
1865
|
-
* - the user doesn't have the permission to update the document
|
1866
|
-
*/
|
1867
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
|
1868
|
-
label: formatMessage({
|
1869
|
-
id: "content-manager.containers.Edit.save",
|
1870
|
-
defaultMessage: "Save"
|
1871
|
-
}),
|
1872
|
-
onClick: async () => {
|
1873
|
-
setSubmitting(true);
|
1874
|
-
try {
|
1875
|
-
const { errors } = await validate();
|
1876
|
-
if (errors) {
|
1800
|
+
const handleClick = (action2) => async (e) => {
|
1801
|
+
const { onClick = () => false, dialog, id } = action2;
|
1802
|
+
const muteDialog = await onClick(e);
|
1803
|
+
if (dialog && !muteDialog) {
|
1804
|
+
switch (dialog.type) {
|
1805
|
+
case "notification":
|
1877
1806
|
toggleNotification({
|
1878
|
-
|
1879
|
-
message:
|
1880
|
-
|
1881
|
-
|
1882
|
-
|
1807
|
+
title: dialog.title,
|
1808
|
+
message: dialog.content,
|
1809
|
+
type: dialog.status,
|
1810
|
+
timeout: dialog.timeout,
|
1811
|
+
onClose: dialog.onClose
|
1883
1812
|
});
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
1889
|
-
model,
|
1890
|
-
documentId: cloneMatch.params.origin,
|
1891
|
-
params
|
1892
|
-
},
|
1893
|
-
document
|
1894
|
-
);
|
1895
|
-
if ("data" in res) {
|
1896
|
-
navigate(
|
1897
|
-
{
|
1898
|
-
pathname: `../${res.data.documentId}`,
|
1899
|
-
search: rawQuery
|
1900
|
-
},
|
1901
|
-
{ relative: "path" }
|
1902
|
-
);
|
1903
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1904
|
-
setErrors(formatValidationErrors(res.error));
|
1905
|
-
}
|
1906
|
-
} else if (documentId || collectionType === SINGLE_TYPES) {
|
1907
|
-
const res = await update(
|
1908
|
-
{
|
1909
|
-
collectionType,
|
1910
|
-
model,
|
1911
|
-
documentId,
|
1912
|
-
params
|
1913
|
-
},
|
1914
|
-
document
|
1915
|
-
);
|
1916
|
-
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1917
|
-
setErrors(formatValidationErrors(res.error));
|
1918
|
-
} else {
|
1919
|
-
resetForm();
|
1920
|
-
}
|
1921
|
-
} else {
|
1922
|
-
const res = await create(
|
1923
|
-
{
|
1924
|
-
model,
|
1925
|
-
params
|
1926
|
-
},
|
1927
|
-
document
|
1928
|
-
);
|
1929
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1930
|
-
navigate(
|
1931
|
-
{
|
1932
|
-
pathname: `../${res.data.documentId}`,
|
1933
|
-
search: rawQuery
|
1934
|
-
},
|
1935
|
-
{ replace: true, relative: "path" }
|
1936
|
-
);
|
1937
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1938
|
-
setErrors(formatValidationErrors(res.error));
|
1939
|
-
}
|
1940
|
-
}
|
1941
|
-
} finally {
|
1942
|
-
setSubmitting(false);
|
1813
|
+
break;
|
1814
|
+
case "dialog":
|
1815
|
+
case "modal":
|
1816
|
+
e.preventDefault();
|
1817
|
+
setDialogId(id);
|
1943
1818
|
}
|
1944
1819
|
}
|
1945
1820
|
};
|
1821
|
+
const handleClose = () => {
|
1822
|
+
setDialogId(null);
|
1823
|
+
};
|
1824
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
1825
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1826
|
+
designSystem.Button,
|
1827
|
+
{
|
1828
|
+
flex: "auto",
|
1829
|
+
startIcon: action.icon,
|
1830
|
+
disabled: action.disabled,
|
1831
|
+
onClick: handleClick(action),
|
1832
|
+
justifyContent: "center",
|
1833
|
+
variant: action.variant || "default",
|
1834
|
+
paddingTop: "7px",
|
1835
|
+
paddingBottom: "7px",
|
1836
|
+
children: action.label
|
1837
|
+
}
|
1838
|
+
),
|
1839
|
+
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1840
|
+
DocumentActionConfirmDialog,
|
1841
|
+
{
|
1842
|
+
...action.dialog,
|
1843
|
+
variant: action.dialog?.variant ?? action.variant,
|
1844
|
+
isOpen: dialogId === action.id,
|
1845
|
+
onClose: handleClose
|
1846
|
+
}
|
1847
|
+
) : null,
|
1848
|
+
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1849
|
+
DocumentActionModal,
|
1850
|
+
{
|
1851
|
+
...action.dialog,
|
1852
|
+
onModalClose: handleClose,
|
1853
|
+
isOpen: dialogId === action.id
|
1854
|
+
}
|
1855
|
+
) : null
|
1856
|
+
] });
|
1946
1857
|
};
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
1950
|
-
|
1951
|
-
|
1952
|
-
const UnpublishAction$1 = ({
|
1953
|
-
activeTab,
|
1954
|
-
documentId,
|
1955
|
-
model,
|
1956
|
-
collectionType,
|
1957
|
-
document
|
1858
|
+
const DocumentActionsMenu = ({
|
1859
|
+
actions: actions2,
|
1860
|
+
children,
|
1861
|
+
label,
|
1862
|
+
variant = "tertiary"
|
1958
1863
|
}) => {
|
1864
|
+
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
1865
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
1959
1866
|
const { formatMessage } = reactIntl.useIntl();
|
1960
|
-
const { schema } = useDoc();
|
1961
|
-
const canPublish = useDocumentRBAC("UnpublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1962
|
-
const { unpublish } = useDocumentActions();
|
1963
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
1964
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1965
1867
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1966
|
-
const
|
1967
|
-
const
|
1968
|
-
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1973
|
-
}
|
1974
|
-
return {
|
1975
|
-
disabled: !canPublish || activeTab === "published" || document?.status !== "published" && document?.status !== "modified",
|
1976
|
-
label: formatMessage({
|
1977
|
-
id: "app.utils.unpublish",
|
1978
|
-
defaultMessage: "Unpublish"
|
1979
|
-
}),
|
1980
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
|
1981
|
-
onClick: async () => {
|
1982
|
-
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1983
|
-
if (!documentId) {
|
1984
|
-
console.error(
|
1985
|
-
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
1986
|
-
);
|
1868
|
+
const isDisabled = actions2.every((action) => action.disabled) || actions2.length === 0;
|
1869
|
+
const handleClick = (action) => async (e) => {
|
1870
|
+
const { onClick = () => false, dialog, id } = action;
|
1871
|
+
const muteDialog = await onClick(e);
|
1872
|
+
if (dialog && !muteDialog) {
|
1873
|
+
switch (dialog.type) {
|
1874
|
+
case "notification":
|
1987
1875
|
toggleNotification({
|
1988
|
-
|
1989
|
-
|
1990
|
-
|
1991
|
-
|
1992
|
-
|
1876
|
+
title: dialog.title,
|
1877
|
+
message: dialog.content,
|
1878
|
+
type: dialog.status,
|
1879
|
+
timeout: dialog.timeout,
|
1880
|
+
onClose: dialog.onClose
|
1993
1881
|
});
|
1994
|
-
|
1995
|
-
|
1882
|
+
break;
|
1883
|
+
case "dialog":
|
1884
|
+
case "modal":
|
1885
|
+
setDialogId(id);
|
1996
1886
|
}
|
1997
|
-
|
1998
|
-
|
1999
|
-
|
2000
|
-
|
2001
|
-
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
2007
|
-
|
2008
|
-
|
2009
|
-
|
2010
|
-
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2015
|
-
|
1887
|
+
}
|
1888
|
+
};
|
1889
|
+
const handleClose = () => {
|
1890
|
+
setDialogId(null);
|
1891
|
+
setIsOpen(false);
|
1892
|
+
};
|
1893
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1894
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
1895
|
+
designSystem.Menu.Trigger,
|
1896
|
+
{
|
1897
|
+
disabled: isDisabled,
|
1898
|
+
size: "S",
|
1899
|
+
endIcon: null,
|
1900
|
+
paddingTop: "4px",
|
1901
|
+
paddingLeft: "7px",
|
1902
|
+
paddingRight: "7px",
|
1903
|
+
variant,
|
1904
|
+
children: [
|
1905
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
1906
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1907
|
+
id: "content-manager.containers.edit.panels.default.more-actions",
|
1908
|
+
defaultMessage: "More document actions"
|
2016
1909
|
}) })
|
2017
|
-
]
|
2018
|
-
|
2019
|
-
|
2020
|
-
|
2021
|
-
|
2022
|
-
|
2023
|
-
|
2024
|
-
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2025
|
-
defaultMessage: "Choose an option to unpublish the document."
|
2026
|
-
}),
|
2027
|
-
onValueChange: handleChange,
|
2028
|
-
children: [
|
2029
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2030
|
-
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2031
|
-
defaultMessage: "Keep draft"
|
2032
|
-
}) }),
|
2033
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2034
|
-
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2035
|
-
defaultMessage: "Replace draft"
|
2036
|
-
}) })
|
2037
|
-
]
|
2038
|
-
}
|
2039
|
-
)
|
2040
|
-
] }),
|
2041
|
-
onConfirm: async () => {
|
2042
|
-
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2043
|
-
console.error(
|
2044
|
-
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2045
|
-
);
|
2046
|
-
toggleNotification({
|
2047
|
-
message: formatMessage({
|
2048
|
-
id: "content-manager.actions.unpublish.error",
|
2049
|
-
defaultMessage: "An error occurred while trying to unpublish the document."
|
2050
|
-
}),
|
2051
|
-
type: "danger"
|
2052
|
-
});
|
2053
|
-
}
|
2054
|
-
await unpublish(
|
1910
|
+
]
|
1911
|
+
}
|
1912
|
+
),
|
1913
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1914
|
+
actions2.map((action) => {
|
1915
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
1916
|
+
designSystem.Menu.Item,
|
2055
1917
|
{
|
2056
|
-
|
2057
|
-
|
2058
|
-
|
2059
|
-
|
1918
|
+
disabled: action.disabled,
|
1919
|
+
onSelect: handleClick(action),
|
1920
|
+
display: "block",
|
1921
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
1922
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
1923
|
+
designSystem.Flex,
|
1924
|
+
{
|
1925
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1926
|
+
gap: 2,
|
1927
|
+
tag: "span",
|
1928
|
+
children: [
|
1929
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1930
|
+
designSystem.Flex,
|
1931
|
+
{
|
1932
|
+
tag: "span",
|
1933
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1934
|
+
children: action.icon
|
1935
|
+
}
|
1936
|
+
),
|
1937
|
+
action.label
|
1938
|
+
]
|
1939
|
+
}
|
1940
|
+
),
|
1941
|
+
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1942
|
+
designSystem.Flex,
|
1943
|
+
{
|
1944
|
+
alignItems: "center",
|
1945
|
+
background: "alternative100",
|
1946
|
+
borderStyle: "solid",
|
1947
|
+
borderColor: "alternative200",
|
1948
|
+
borderWidth: "1px",
|
1949
|
+
height: 5,
|
1950
|
+
paddingLeft: 2,
|
1951
|
+
paddingRight: 2,
|
1952
|
+
hasRadius: true,
|
1953
|
+
color: "alternative600",
|
1954
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1955
|
+
}
|
1956
|
+
)
|
1957
|
+
] })
|
2060
1958
|
},
|
2061
|
-
|
1959
|
+
action.id
|
2062
1960
|
);
|
2063
|
-
}
|
2064
|
-
|
2065
|
-
|
2066
|
-
|
1961
|
+
}),
|
1962
|
+
children
|
1963
|
+
] }),
|
1964
|
+
actions2.map((action) => {
|
1965
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
1966
|
+
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1967
|
+
DocumentActionConfirmDialog,
|
1968
|
+
{
|
1969
|
+
...action.dialog,
|
1970
|
+
variant: action.variant,
|
1971
|
+
isOpen: dialogId === action.id,
|
1972
|
+
onClose: handleClose
|
1973
|
+
}
|
1974
|
+
) : null,
|
1975
|
+
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1976
|
+
DocumentActionModal,
|
1977
|
+
{
|
1978
|
+
...action.dialog,
|
1979
|
+
onModalClose: handleClose,
|
1980
|
+
isOpen: dialogId === action.id
|
1981
|
+
}
|
1982
|
+
) : null
|
1983
|
+
] }, action.id);
|
1984
|
+
})
|
1985
|
+
] });
|
1986
|
+
};
|
1987
|
+
const convertActionVariantToColor = (variant = "secondary") => {
|
1988
|
+
switch (variant) {
|
1989
|
+
case "danger":
|
1990
|
+
return "danger600";
|
1991
|
+
case "secondary":
|
1992
|
+
return void 0;
|
1993
|
+
case "success":
|
1994
|
+
return "success600";
|
1995
|
+
default:
|
1996
|
+
return "primary600";
|
1997
|
+
}
|
1998
|
+
};
|
1999
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
2000
|
+
switch (variant) {
|
2001
|
+
case "danger":
|
2002
|
+
return "danger600";
|
2003
|
+
case "secondary":
|
2004
|
+
return "neutral500";
|
2005
|
+
case "success":
|
2006
|
+
return "success600";
|
2007
|
+
default:
|
2008
|
+
return "primary600";
|
2009
|
+
}
|
2010
|
+
};
|
2011
|
+
const DocumentActionConfirmDialog = ({
|
2012
|
+
onClose,
|
2013
|
+
onCancel,
|
2014
|
+
onConfirm,
|
2015
|
+
title,
|
2016
|
+
content,
|
2017
|
+
isOpen,
|
2018
|
+
variant = "secondary"
|
2019
|
+
}) => {
|
2020
|
+
const { formatMessage } = reactIntl.useIntl();
|
2021
|
+
const handleClose = async () => {
|
2022
|
+
if (onCancel) {
|
2023
|
+
await onCancel();
|
2024
|
+
}
|
2025
|
+
onClose();
|
2026
|
+
};
|
2027
|
+
const handleConfirm = async () => {
|
2028
|
+
if (onConfirm) {
|
2029
|
+
await onConfirm();
|
2030
|
+
}
|
2031
|
+
onClose();
|
2032
|
+
};
|
2033
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2034
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2035
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
2036
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
2037
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
2038
|
+
id: "app.components.Button.cancel",
|
2039
|
+
defaultMessage: "Cancel"
|
2040
|
+
}) }) }),
|
2041
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
2042
|
+
id: "app.components.Button.confirm",
|
2043
|
+
defaultMessage: "Confirm"
|
2044
|
+
}) })
|
2045
|
+
] })
|
2046
|
+
] }) });
|
2047
|
+
};
|
2048
|
+
const DocumentActionModal = ({
|
2049
|
+
isOpen,
|
2050
|
+
title,
|
2051
|
+
onClose,
|
2052
|
+
footer: Footer,
|
2053
|
+
content: Content,
|
2054
|
+
onModalClose
|
2055
|
+
}) => {
|
2056
|
+
const handleClose = () => {
|
2057
|
+
if (onClose) {
|
2058
|
+
onClose();
|
2059
|
+
}
|
2060
|
+
onModalClose();
|
2067
2061
|
};
|
2062
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
|
2063
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
|
2064
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
|
2065
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
2066
|
+
] }) });
|
2068
2067
|
};
|
2069
|
-
|
2070
|
-
const DiscardAction = ({
|
2068
|
+
const PublishAction$1 = ({
|
2071
2069
|
activeTab,
|
2072
2070
|
documentId,
|
2073
2071
|
model,
|
2074
2072
|
collectionType,
|
2073
|
+
meta,
|
2075
2074
|
document
|
2076
2075
|
}) => {
|
2077
|
-
const { formatMessage } = reactIntl.useIntl();
|
2078
2076
|
const { schema } = useDoc();
|
2079
|
-
const
|
2080
|
-
const {
|
2081
|
-
const
|
2082
|
-
const
|
2083
|
-
if (!schema?.options?.draftAndPublish) {
|
2084
|
-
return null;
|
2085
|
-
}
|
2086
|
-
return {
|
2087
|
-
disabled: !canUpdate || activeTab === "published" || document?.status !== "modified",
|
2088
|
-
label: formatMessage({
|
2089
|
-
id: "content-manager.actions.discard.label",
|
2090
|
-
defaultMessage: "Discard changes"
|
2091
|
-
}),
|
2092
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
|
2093
|
-
position: ["panel", "table-row"],
|
2094
|
-
variant: "danger",
|
2095
|
-
dialog: {
|
2096
|
-
type: "dialog",
|
2097
|
-
title: formatMessage({
|
2098
|
-
id: "app.components.ConfirmDialog.title",
|
2099
|
-
defaultMessage: "Confirmation"
|
2100
|
-
}),
|
2101
|
-
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2102
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2103
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2104
|
-
id: "content-manager.actions.discard.dialog.body",
|
2105
|
-
defaultMessage: "Are you sure?"
|
2106
|
-
}) })
|
2107
|
-
] }),
|
2108
|
-
onConfirm: async () => {
|
2109
|
-
await discard({
|
2110
|
-
collectionType,
|
2111
|
-
model,
|
2112
|
-
documentId,
|
2113
|
-
params
|
2114
|
-
});
|
2115
|
-
}
|
2116
|
-
}
|
2117
|
-
};
|
2118
|
-
};
|
2119
|
-
DiscardAction.type = "discard";
|
2120
|
-
const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
|
2121
|
-
path {
|
2122
|
-
fill: currentColor;
|
2123
|
-
}
|
2124
|
-
`;
|
2125
|
-
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2126
|
-
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2127
|
-
const RelativeTime = React__namespace.forwardRef(
|
2128
|
-
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
2129
|
-
const { formatRelativeTime, formatDate, formatTime } = reactIntl.useIntl();
|
2130
|
-
const interval = dateFns.intervalToDuration({
|
2131
|
-
start: timestamp,
|
2132
|
-
end: Date.now()
|
2133
|
-
// see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
|
2134
|
-
});
|
2135
|
-
const unit = intervals.find((intervalUnit) => {
|
2136
|
-
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2137
|
-
});
|
2138
|
-
const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
|
2139
|
-
const customInterval = customIntervals.find(
|
2140
|
-
(custom) => interval[custom.unit] < custom.threshold
|
2141
|
-
);
|
2142
|
-
const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
|
2143
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
2144
|
-
"time",
|
2145
|
-
{
|
2146
|
-
ref: forwardedRef,
|
2147
|
-
dateTime: timestamp.toISOString(),
|
2148
|
-
role: "time",
|
2149
|
-
title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
|
2150
|
-
...restProps,
|
2151
|
-
children: displayText
|
2152
|
-
}
|
2153
|
-
);
|
2154
|
-
}
|
2155
|
-
);
|
2156
|
-
const getDisplayName = ({
|
2157
|
-
firstname,
|
2158
|
-
lastname,
|
2159
|
-
username,
|
2160
|
-
email
|
2161
|
-
} = {}) => {
|
2162
|
-
if (username) {
|
2163
|
-
return username;
|
2164
|
-
}
|
2165
|
-
if (firstname) {
|
2166
|
-
return `${firstname} ${lastname ?? ""}`.trim();
|
2167
|
-
}
|
2168
|
-
return email ?? "";
|
2169
|
-
};
|
2170
|
-
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2171
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2172
|
-
const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
|
2173
|
-
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) }) });
|
2174
|
-
};
|
2175
|
-
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2176
|
-
const { formatMessage } = reactIntl.useIntl();
|
2077
|
+
const navigate = reactRouterDom.useNavigate();
|
2078
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2079
|
+
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2080
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
2177
2081
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2178
|
-
const title = isCreating ? formatMessage({
|
2179
|
-
id: "content-manager.containers.edit.title.new",
|
2180
|
-
defaultMessage: "Create an entry"
|
2181
|
-
}) : documentTitle;
|
2182
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2183
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
|
2184
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2185
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2186
|
-
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2187
|
-
] }),
|
2188
|
-
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2189
|
-
] });
|
2190
|
-
};
|
2191
|
-
const HeaderToolbar = () => {
|
2192
2082
|
const { formatMessage } = reactIntl.useIntl();
|
2193
|
-
const
|
2083
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
2084
|
+
const { publish } = useDocumentActions();
|
2194
2085
|
const [
|
2195
|
-
|
2196
|
-
|
2086
|
+
countDraftRelations,
|
2087
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2088
|
+
] = useLazyGetDraftRelationCountQuery();
|
2089
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
2090
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
2091
|
+
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
2092
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2093
|
+
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
2094
|
+
const setSubmitting = strapiAdmin.useForm("PublishAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
2095
|
+
const isSubmitting = strapiAdmin.useForm("PublishAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
2096
|
+
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
2097
|
+
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
2098
|
+
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
2099
|
+
React__namespace.useEffect(() => {
|
2100
|
+
if (isErrorDraftRelations) {
|
2101
|
+
toggleNotification({
|
2102
|
+
type: "danger",
|
2103
|
+
message: formatMessage({
|
2104
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2105
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2106
|
+
})
|
2107
|
+
});
|
2197
2108
|
}
|
2198
|
-
|
2199
|
-
|
2200
|
-
|
2201
|
-
|
2202
|
-
|
2203
|
-
|
2204
|
-
|
2205
|
-
|
2206
|
-
activeTab: status,
|
2207
|
-
model,
|
2208
|
-
documentId: id,
|
2209
|
-
document: isCloning ? void 0 : document,
|
2210
|
-
meta: isCloning ? void 0 : meta,
|
2211
|
-
collectionType
|
2212
|
-
},
|
2213
|
-
descriptions: plugins["content-manager"].apis.getHeaderActions(),
|
2214
|
-
children: (actions2) => {
|
2215
|
-
if (actions2.length > 0) {
|
2216
|
-
return /* @__PURE__ */ jsxRuntime.jsx(HeaderActions, { actions: actions2 });
|
2217
|
-
} else {
|
2218
|
-
return null;
|
2219
|
-
}
|
2109
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2110
|
+
React__namespace.useEffect(() => {
|
2111
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2112
|
+
const extractDraftRelations = (data) => {
|
2113
|
+
const relations = data.connect || [];
|
2114
|
+
relations.forEach((relation) => {
|
2115
|
+
if (relation.status === "draft") {
|
2116
|
+
localDraftRelations.add(relation.id);
|
2220
2117
|
}
|
2221
|
-
}
|
2222
|
-
|
2223
|
-
|
2224
|
-
|
2225
|
-
|
2226
|
-
|
2227
|
-
|
2228
|
-
|
2229
|
-
documentId: id,
|
2230
|
-
document: isCloning ? void 0 : document,
|
2231
|
-
meta: isCloning ? void 0 : meta,
|
2232
|
-
collectionType
|
2233
|
-
},
|
2234
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2235
|
-
children: (actions2) => {
|
2236
|
-
const headerActions = actions2.filter((action) => {
|
2237
|
-
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2238
|
-
return positions.includes("header");
|
2239
|
-
});
|
2240
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
2241
|
-
DocumentActionsMenu,
|
2242
|
-
{
|
2243
|
-
actions: headerActions,
|
2244
|
-
label: formatMessage({
|
2245
|
-
id: "content-manager.containers.edit.header.more-actions",
|
2246
|
-
defaultMessage: "More actions"
|
2247
|
-
}),
|
2248
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(Information, { activeTab: status })
|
2249
|
-
}
|
2250
|
-
);
|
2118
|
+
});
|
2119
|
+
};
|
2120
|
+
const traverseAndExtract = (data) => {
|
2121
|
+
Object.entries(data).forEach(([key, value]) => {
|
2122
|
+
if (key === "connect" && Array.isArray(value)) {
|
2123
|
+
extractDraftRelations({ connect: value });
|
2124
|
+
} else if (typeof value === "object" && value !== null) {
|
2125
|
+
traverseAndExtract(value);
|
2251
2126
|
}
|
2127
|
+
});
|
2128
|
+
};
|
2129
|
+
if (!documentId || modified) {
|
2130
|
+
traverseAndExtract(formValues);
|
2131
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2132
|
+
}
|
2133
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2134
|
+
React__namespace.useEffect(() => {
|
2135
|
+
if (!document || !document.documentId || isListView) {
|
2136
|
+
return;
|
2137
|
+
}
|
2138
|
+
const fetchDraftRelationsCount = async () => {
|
2139
|
+
const { data, error } = await countDraftRelations({
|
2140
|
+
collectionType,
|
2141
|
+
model,
|
2142
|
+
documentId,
|
2143
|
+
params
|
2144
|
+
});
|
2145
|
+
if (error) {
|
2146
|
+
throw error;
|
2147
|
+
}
|
2148
|
+
if (data) {
|
2149
|
+
setServerCountOfDraftRelations(data.data);
|
2252
2150
|
}
|
2253
|
-
|
2254
|
-
|
2255
|
-
};
|
2256
|
-
const
|
2257
|
-
|
2258
|
-
const { document, meta } = useDoc();
|
2259
|
-
if (!document || !document.id) {
|
2151
|
+
};
|
2152
|
+
fetchDraftRelationsCount();
|
2153
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2154
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
2155
|
+
if (!schema?.options?.draftAndPublish) {
|
2260
2156
|
return null;
|
2261
2157
|
}
|
2262
|
-
const
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
2267
|
-
|
2268
|
-
|
2269
|
-
|
2270
|
-
|
2271
|
-
|
2272
|
-
|
2273
|
-
|
2158
|
+
const performPublish = async () => {
|
2159
|
+
setSubmitting(true);
|
2160
|
+
try {
|
2161
|
+
const { errors } = await validate();
|
2162
|
+
if (errors) {
|
2163
|
+
toggleNotification({
|
2164
|
+
type: "danger",
|
2165
|
+
message: formatMessage({
|
2166
|
+
id: "content-manager.validation.error",
|
2167
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2168
|
+
})
|
2169
|
+
});
|
2170
|
+
return;
|
2171
|
+
}
|
2172
|
+
const res = await publish(
|
2274
2173
|
{
|
2275
|
-
|
2276
|
-
|
2174
|
+
collectionType,
|
2175
|
+
model,
|
2176
|
+
documentId,
|
2177
|
+
params
|
2277
2178
|
},
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2179
|
+
formValues
|
2180
|
+
);
|
2181
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2182
|
+
navigate({
|
2183
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2184
|
+
search: rawQuery
|
2185
|
+
});
|
2186
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2187
|
+
setErrors(formatValidationErrors(res.error));
|
2188
|
+
}
|
2189
|
+
} finally {
|
2190
|
+
setSubmitting(false);
|
2191
|
+
}
|
2192
|
+
};
|
2193
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2194
|
+
const enableDraftRelationsCount = false;
|
2195
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
2196
|
+
return {
|
2197
|
+
/**
|
2198
|
+
* Disabled when:
|
2199
|
+
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
2200
|
+
* - the form is submitting
|
2201
|
+
* - the active tab is the published tab
|
2202
|
+
* - the document is already published & not modified
|
2203
|
+
* - the document is being created & not modified
|
2204
|
+
* - the user doesn't have the permission to publish
|
2205
|
+
*/
|
2206
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
2207
|
+
label: formatMessage({
|
2208
|
+
id: "app.utils.publish",
|
2209
|
+
defaultMessage: "Publish"
|
2210
|
+
}),
|
2211
|
+
onClick: async () => {
|
2212
|
+
await performPublish();
|
2284
2213
|
},
|
2285
|
-
{
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2214
|
+
dialog: hasDraftRelations ? {
|
2215
|
+
type: "dialog",
|
2216
|
+
variant: "danger",
|
2217
|
+
footer: null,
|
2218
|
+
title: formatMessage({
|
2219
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2220
|
+
defaultMessage: "Confirmation"
|
2290
2221
|
}),
|
2291
|
-
|
2222
|
+
content: formatMessage(
|
2292
2223
|
{
|
2293
|
-
id:
|
2294
|
-
defaultMessage:
|
2224
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2225
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2295
2226
|
},
|
2296
2227
|
{
|
2297
|
-
|
2298
|
-
RelativeTime,
|
2299
|
-
{
|
2300
|
-
timestamp: new Date(createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME])
|
2301
|
-
}
|
2302
|
-
),
|
2303
|
-
isAnonymous: !updator,
|
2304
|
-
author: updator
|
2228
|
+
count: totalDraftRelations
|
2305
2229
|
}
|
2306
|
-
)
|
2307
|
-
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2315
|
-
|
2316
|
-
|
2317
|
-
|
2318
|
-
|
2319
|
-
|
2320
|
-
|
2321
|
-
|
2230
|
+
),
|
2231
|
+
onConfirm: async () => {
|
2232
|
+
await performPublish();
|
2233
|
+
}
|
2234
|
+
} : void 0
|
2235
|
+
};
|
2236
|
+
};
|
2237
|
+
PublishAction$1.type = "publish";
|
2238
|
+
const UpdateAction = ({
|
2239
|
+
activeTab,
|
2240
|
+
documentId,
|
2241
|
+
model,
|
2242
|
+
collectionType
|
2243
|
+
}) => {
|
2244
|
+
const navigate = reactRouterDom.useNavigate();
|
2245
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2246
|
+
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2247
|
+
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
2248
|
+
const isCloning = cloneMatch !== null;
|
2249
|
+
const { formatMessage } = reactIntl.useIntl();
|
2250
|
+
const { create, update, clone } = useDocumentActions();
|
2251
|
+
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
2252
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2253
|
+
const isSubmitting = strapiAdmin.useForm("UpdateAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
2254
|
+
const modified = strapiAdmin.useForm("UpdateAction", ({ modified: modified2 }) => modified2);
|
2255
|
+
const setSubmitting = strapiAdmin.useForm("UpdateAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
2256
|
+
const document = strapiAdmin.useForm("UpdateAction", ({ values }) => values);
|
2257
|
+
const validate = strapiAdmin.useForm("UpdateAction", (state) => state.validate);
|
2258
|
+
const setErrors = strapiAdmin.useForm("UpdateAction", (state) => state.setErrors);
|
2259
|
+
const resetForm = strapiAdmin.useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
2260
|
+
return {
|
2261
|
+
/**
|
2262
|
+
* Disabled when:
|
2263
|
+
* - the form is submitting
|
2264
|
+
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
2265
|
+
* - the active tab is the published tab
|
2266
|
+
*/
|
2267
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
2268
|
+
label: formatMessage({
|
2269
|
+
id: "content-manager.containers.Edit.save",
|
2270
|
+
defaultMessage: "Save"
|
2271
|
+
}),
|
2272
|
+
onClick: async () => {
|
2273
|
+
setSubmitting(true);
|
2274
|
+
try {
|
2275
|
+
if (activeTab !== "draft") {
|
2276
|
+
const { errors } = await validate();
|
2277
|
+
if (errors) {
|
2278
|
+
toggleNotification({
|
2279
|
+
type: "danger",
|
2280
|
+
message: formatMessage({
|
2281
|
+
id: "content-manager.validation.error",
|
2282
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2283
|
+
})
|
2284
|
+
});
|
2285
|
+
return;
|
2286
|
+
}
|
2287
|
+
}
|
2288
|
+
if (isCloning) {
|
2289
|
+
const res = await clone(
|
2322
2290
|
{
|
2323
|
-
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2327
|
-
|
2291
|
+
model,
|
2292
|
+
documentId: cloneMatch.params.origin,
|
2293
|
+
params
|
2294
|
+
},
|
2295
|
+
document
|
2296
|
+
);
|
2297
|
+
if ("data" in res) {
|
2298
|
+
navigate(
|
2299
|
+
{
|
2300
|
+
pathname: `../${res.data.documentId}`,
|
2301
|
+
search: rawQuery
|
2302
|
+
},
|
2303
|
+
{ relative: "path" }
|
2304
|
+
);
|
2305
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2306
|
+
setErrors(formatValidationErrors(res.error));
|
2307
|
+
}
|
2308
|
+
} else if (documentId || collectionType === SINGLE_TYPES) {
|
2309
|
+
const res = await update(
|
2310
|
+
{
|
2311
|
+
collectionType,
|
2312
|
+
model,
|
2313
|
+
documentId,
|
2314
|
+
params
|
2315
|
+
},
|
2316
|
+
document
|
2317
|
+
);
|
2318
|
+
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2319
|
+
setErrors(formatValidationErrors(res.error));
|
2320
|
+
} else {
|
2321
|
+
resetForm();
|
2322
|
+
}
|
2323
|
+
} else {
|
2324
|
+
const res = await create(
|
2325
|
+
{
|
2326
|
+
model,
|
2327
|
+
params
|
2328
|
+
},
|
2329
|
+
document
|
2330
|
+
);
|
2331
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2332
|
+
navigate(
|
2333
|
+
{
|
2334
|
+
pathname: `../${res.data.documentId}`,
|
2335
|
+
search: rawQuery
|
2336
|
+
},
|
2337
|
+
{ replace: true, relative: "path" }
|
2338
|
+
);
|
2339
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2340
|
+
setErrors(formatValidationErrors(res.error));
|
2341
|
+
}
|
2328
2342
|
}
|
2329
|
-
|
2330
|
-
|
2331
|
-
|
2332
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
2333
|
-
designSystem.Flex,
|
2334
|
-
{
|
2335
|
-
borderWidth: "1px 0 0 0",
|
2336
|
-
borderStyle: "solid",
|
2337
|
-
borderColor: "neutral150",
|
2338
|
-
direction: "column",
|
2339
|
-
marginTop: 2,
|
2340
|
-
tag: "dl",
|
2341
|
-
padding: 5,
|
2342
|
-
gap: 3,
|
2343
|
-
alignItems: "flex-start",
|
2344
|
-
marginLeft: "-0.4rem",
|
2345
|
-
marginRight: "-0.4rem",
|
2346
|
-
width: "calc(100% + 8px)",
|
2347
|
-
children: information.map((info) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
|
2348
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
|
2349
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
|
2350
|
-
] }, info.label))
|
2343
|
+
} finally {
|
2344
|
+
setSubmitting(false);
|
2345
|
+
}
|
2351
2346
|
}
|
2352
|
-
|
2347
|
+
};
|
2353
2348
|
};
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2358
|
-
designSystem.SingleSelect,
|
2359
|
-
{
|
2360
|
-
size: "S",
|
2361
|
-
disabled: action.disabled,
|
2362
|
-
"aria-label": action.label,
|
2363
|
-
onChange: action.onSelect,
|
2364
|
-
value: action.value,
|
2365
|
-
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2366
|
-
},
|
2367
|
-
action.id
|
2368
|
-
);
|
2369
|
-
} else {
|
2370
|
-
return null;
|
2371
|
-
}
|
2372
|
-
}) });
|
2349
|
+
UpdateAction.type = "update";
|
2350
|
+
const UNPUBLISH_DRAFT_OPTIONS = {
|
2351
|
+
KEEP: "keep",
|
2352
|
+
DISCARD: "discard"
|
2373
2353
|
};
|
2374
|
-
const
|
2375
|
-
|
2354
|
+
const UnpublishAction$1 = ({
|
2355
|
+
activeTab,
|
2356
|
+
documentId,
|
2357
|
+
model,
|
2358
|
+
collectionType,
|
2359
|
+
document
|
2360
|
+
}) => {
|
2376
2361
|
const { formatMessage } = reactIntl.useIntl();
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2362
|
+
const { schema } = useDoc();
|
2363
|
+
const canPublish = useDocumentRBAC("UnpublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
2364
|
+
const { unpublish } = useDocumentActions();
|
2365
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
2366
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2367
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2368
|
+
const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
|
2369
|
+
const isDocumentModified = document?.status === "modified";
|
2370
|
+
const handleChange = (value) => {
|
2371
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
2387
2372
|
};
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2391
|
-
const navigate = reactRouterDom.useNavigate();
|
2392
|
-
const { formatMessage } = reactIntl.useIntl();
|
2373
|
+
if (!schema?.options?.draftAndPublish) {
|
2374
|
+
return null;
|
2375
|
+
}
|
2393
2376
|
return {
|
2377
|
+
disabled: !canPublish || activeTab === "published" || document?.status !== "published" && document?.status !== "modified",
|
2394
2378
|
label: formatMessage({
|
2395
|
-
id: "
|
2396
|
-
defaultMessage: "
|
2379
|
+
id: "app.utils.unpublish",
|
2380
|
+
defaultMessage: "Unpublish"
|
2397
2381
|
}),
|
2398
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.
|
2399
|
-
onClick: () => {
|
2400
|
-
|
2382
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2383
|
+
onClick: async () => {
|
2384
|
+
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
2385
|
+
if (!documentId) {
|
2386
|
+
console.error(
|
2387
|
+
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2388
|
+
);
|
2389
|
+
toggleNotification({
|
2390
|
+
message: formatMessage({
|
2391
|
+
id: "content-manager.actions.unpublish.error",
|
2392
|
+
defaultMessage: "An error occurred while trying to unpublish the document."
|
2393
|
+
}),
|
2394
|
+
type: "danger"
|
2395
|
+
});
|
2396
|
+
}
|
2397
|
+
return;
|
2398
|
+
}
|
2399
|
+
await unpublish({
|
2400
|
+
collectionType,
|
2401
|
+
model,
|
2402
|
+
documentId,
|
2403
|
+
params
|
2404
|
+
});
|
2401
2405
|
},
|
2402
|
-
|
2406
|
+
dialog: isDocumentModified ? {
|
2407
|
+
type: "dialog",
|
2408
|
+
title: formatMessage({
|
2409
|
+
id: "app.components.ConfirmDialog.title",
|
2410
|
+
defaultMessage: "Confirmation"
|
2411
|
+
}),
|
2412
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
|
2413
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
|
2414
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2415
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2416
|
+
id: "content-manager.actions.unpublish.dialog.body",
|
2417
|
+
defaultMessage: "Are you sure?"
|
2418
|
+
}) })
|
2419
|
+
] }),
|
2420
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
2421
|
+
designSystem.Radio.Group,
|
2422
|
+
{
|
2423
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2424
|
+
name: "discard-options",
|
2425
|
+
"aria-label": formatMessage({
|
2426
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2427
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2428
|
+
}),
|
2429
|
+
onValueChange: handleChange,
|
2430
|
+
children: [
|
2431
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2432
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2433
|
+
defaultMessage: "Keep draft"
|
2434
|
+
}) }),
|
2435
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2436
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2437
|
+
defaultMessage: "Replace draft"
|
2438
|
+
}) })
|
2439
|
+
]
|
2440
|
+
}
|
2441
|
+
)
|
2442
|
+
] }),
|
2443
|
+
onConfirm: async () => {
|
2444
|
+
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2445
|
+
console.error(
|
2446
|
+
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2447
|
+
);
|
2448
|
+
toggleNotification({
|
2449
|
+
message: formatMessage({
|
2450
|
+
id: "content-manager.actions.unpublish.error",
|
2451
|
+
defaultMessage: "An error occurred while trying to unpublish the document."
|
2452
|
+
}),
|
2453
|
+
type: "danger"
|
2454
|
+
});
|
2455
|
+
}
|
2456
|
+
await unpublish(
|
2457
|
+
{
|
2458
|
+
collectionType,
|
2459
|
+
model,
|
2460
|
+
documentId,
|
2461
|
+
params
|
2462
|
+
},
|
2463
|
+
!shouldKeepDraft
|
2464
|
+
);
|
2465
|
+
}
|
2466
|
+
} : void 0,
|
2467
|
+
variant: "danger",
|
2468
|
+
position: ["panel", "table-row"]
|
2403
2469
|
};
|
2404
2470
|
};
|
2405
|
-
|
2406
|
-
const
|
2407
|
-
|
2471
|
+
UnpublishAction$1.type = "unpublish";
|
2472
|
+
const DiscardAction = ({
|
2473
|
+
activeTab,
|
2474
|
+
documentId,
|
2475
|
+
model,
|
2476
|
+
collectionType,
|
2477
|
+
document
|
2478
|
+
}) => {
|
2408
2479
|
const { formatMessage } = reactIntl.useIntl();
|
2409
|
-
const
|
2410
|
-
const
|
2411
|
-
const {
|
2412
|
-
const {
|
2413
|
-
const
|
2480
|
+
const { schema } = useDoc();
|
2481
|
+
const canUpdate = useDocumentRBAC("DiscardAction", ({ canUpdate: canUpdate2 }) => canUpdate2);
|
2482
|
+
const { discard } = useDocumentActions();
|
2483
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
2484
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2485
|
+
if (!schema?.options?.draftAndPublish) {
|
2486
|
+
return null;
|
2487
|
+
}
|
2414
2488
|
return {
|
2415
|
-
disabled: !
|
2489
|
+
disabled: !canUpdate || activeTab === "published" || document?.status !== "modified",
|
2416
2490
|
label: formatMessage({
|
2417
|
-
id: "content-manager.actions.
|
2418
|
-
defaultMessage: "
|
2491
|
+
id: "content-manager.actions.discard.label",
|
2492
|
+
defaultMessage: "Discard changes"
|
2419
2493
|
}),
|
2420
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.
|
2494
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2495
|
+
position: ["panel", "table-row"],
|
2496
|
+
variant: "danger",
|
2421
2497
|
dialog: {
|
2422
2498
|
type: "dialog",
|
2423
2499
|
title: formatMessage({
|
@@ -2427,92 +2503,90 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2427
2503
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2428
2504
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2429
2505
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2430
|
-
id: "content-manager.actions.
|
2506
|
+
id: "content-manager.actions.discard.dialog.body",
|
2431
2507
|
defaultMessage: "Are you sure?"
|
2432
2508
|
}) })
|
2433
2509
|
] }),
|
2434
2510
|
onConfirm: async () => {
|
2435
|
-
|
2436
|
-
|
2437
|
-
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
2442
|
-
|
2443
|
-
|
2444
|
-
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
2452
|
-
|
2453
|
-
|
2454
|
-
|
2455
|
-
|
2456
|
-
|
2457
|
-
|
2458
|
-
|
2459
|
-
|
2460
|
-
|
2461
|
-
|
2462
|
-
|
2463
|
-
|
2464
|
-
|
2465
|
-
|
2466
|
-
|
2467
|
-
|
2511
|
+
await discard({
|
2512
|
+
collectionType,
|
2513
|
+
model,
|
2514
|
+
documentId,
|
2515
|
+
params
|
2516
|
+
});
|
2517
|
+
}
|
2518
|
+
}
|
2519
|
+
};
|
2520
|
+
};
|
2521
|
+
DiscardAction.type = "discard";
|
2522
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2523
|
+
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2524
|
+
const RelativeTime = React__namespace.forwardRef(
|
2525
|
+
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
2526
|
+
const { formatRelativeTime, formatDate, formatTime } = reactIntl.useIntl();
|
2527
|
+
const interval = dateFns.intervalToDuration({
|
2528
|
+
start: timestamp,
|
2529
|
+
end: Date.now()
|
2530
|
+
// see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
|
2531
|
+
});
|
2532
|
+
const unit = intervals.find((intervalUnit) => {
|
2533
|
+
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2534
|
+
});
|
2535
|
+
const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
|
2536
|
+
const customInterval = customIntervals.find(
|
2537
|
+
(custom) => interval[custom.unit] < custom.threshold
|
2538
|
+
);
|
2539
|
+
const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
|
2540
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2541
|
+
"time",
|
2542
|
+
{
|
2543
|
+
ref: forwardedRef,
|
2544
|
+
dateTime: timestamp.toISOString(),
|
2545
|
+
role: "time",
|
2546
|
+
title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
|
2547
|
+
...restProps,
|
2548
|
+
children: displayText
|
2468
2549
|
}
|
2469
|
-
|
2470
|
-
|
2471
|
-
|
2472
|
-
|
2550
|
+
);
|
2551
|
+
}
|
2552
|
+
);
|
2553
|
+
const getDisplayName = ({
|
2554
|
+
firstname,
|
2555
|
+
lastname,
|
2556
|
+
username,
|
2557
|
+
email
|
2558
|
+
} = {}) => {
|
2559
|
+
if (username) {
|
2560
|
+
return username;
|
2561
|
+
}
|
2562
|
+
if (firstname) {
|
2563
|
+
return `${firstname} ${lastname ?? ""}`.trim();
|
2564
|
+
}
|
2565
|
+
return email ?? "";
|
2473
2566
|
};
|
2474
|
-
|
2475
|
-
const
|
2476
|
-
const
|
2477
|
-
|
2478
|
-
const [
|
2479
|
-
{
|
2480
|
-
query: { status }
|
2481
|
-
}
|
2482
|
-
] = strapiAdmin.useQueryParams({
|
2483
|
-
status: "draft"
|
2484
|
-
});
|
2485
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2486
|
-
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2487
|
-
const props = {
|
2488
|
-
activeTab: status,
|
2489
|
-
model,
|
2490
|
-
documentId: id,
|
2491
|
-
document: isCloning ? void 0 : document,
|
2492
|
-
meta: isCloning ? void 0 : meta,
|
2493
|
-
collectionType
|
2494
|
-
};
|
2495
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2496
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2497
|
-
{
|
2498
|
-
props,
|
2499
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2500
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2501
|
-
}
|
2502
|
-
) });
|
2567
|
+
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2568
|
+
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2569
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2570
|
+
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) }) });
|
2503
2571
|
};
|
2504
|
-
const
|
2572
|
+
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2505
2573
|
const { formatMessage } = reactIntl.useIntl();
|
2506
|
-
|
2507
|
-
|
2508
|
-
|
2509
|
-
|
2510
|
-
|
2511
|
-
|
2512
|
-
|
2574
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2575
|
+
const title = isCreating ? formatMessage({
|
2576
|
+
id: "content-manager.containers.edit.title.new",
|
2577
|
+
defaultMessage: "Create an entry"
|
2578
|
+
}) : documentTitle;
|
2579
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2580
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
|
2581
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2582
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2583
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2584
|
+
] }),
|
2585
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2586
|
+
] });
|
2513
2587
|
};
|
2514
|
-
|
2515
|
-
const
|
2588
|
+
const HeaderToolbar = () => {
|
2589
|
+
const { formatMessage } = reactIntl.useIntl();
|
2516
2590
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2517
2591
|
const [
|
2518
2592
|
{
|
@@ -2520,355 +2594,433 @@ const ActionsPanelContent = () => {
|
|
2520
2594
|
}
|
2521
2595
|
] = strapiAdmin.useQueryParams();
|
2522
2596
|
const { model, id, document, meta, collectionType } = useDoc();
|
2523
|
-
const plugins = strapiAdmin.useStrapiApp("
|
2524
|
-
|
2525
|
-
activeTab: status,
|
2526
|
-
model,
|
2527
|
-
documentId: id,
|
2528
|
-
document: isCloning ? void 0 : document,
|
2529
|
-
meta: isCloning ? void 0 : meta,
|
2530
|
-
collectionType
|
2531
|
-
};
|
2532
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2597
|
+
const plugins = strapiAdmin.useStrapiApp("HeaderToolbar", (state) => state.plugins);
|
2598
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
2533
2599
|
/* @__PURE__ */ jsxRuntime.jsx(
|
2534
2600
|
strapiAdmin.DescriptionComponentRenderer,
|
2535
2601
|
{
|
2536
|
-
props
|
2537
|
-
|
2538
|
-
|
2602
|
+
props: {
|
2603
|
+
activeTab: status,
|
2604
|
+
model,
|
2605
|
+
documentId: id,
|
2606
|
+
document: isCloning ? void 0 : document,
|
2607
|
+
meta: isCloning ? void 0 : meta,
|
2608
|
+
collectionType
|
2609
|
+
},
|
2610
|
+
descriptions: plugins["content-manager"].apis.getHeaderActions(),
|
2611
|
+
children: (actions2) => {
|
2612
|
+
if (actions2.length > 0) {
|
2613
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HeaderActions, { actions: actions2 });
|
2614
|
+
} else {
|
2615
|
+
return null;
|
2616
|
+
}
|
2617
|
+
}
|
2539
2618
|
}
|
2540
2619
|
),
|
2541
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2620
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2621
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2622
|
+
{
|
2623
|
+
props: {
|
2624
|
+
activeTab: status,
|
2625
|
+
model,
|
2626
|
+
documentId: id,
|
2627
|
+
document: isCloning ? void 0 : document,
|
2628
|
+
meta: isCloning ? void 0 : meta,
|
2629
|
+
collectionType
|
2630
|
+
},
|
2631
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2632
|
+
children: (actions2) => {
|
2633
|
+
const headerActions = actions2.filter((action) => {
|
2634
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2635
|
+
return positions.includes("header");
|
2636
|
+
});
|
2637
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2638
|
+
DocumentActionsMenu,
|
2639
|
+
{
|
2640
|
+
actions: headerActions,
|
2641
|
+
label: formatMessage({
|
2642
|
+
id: "content-manager.containers.edit.header.more-actions",
|
2643
|
+
defaultMessage: "More actions"
|
2644
|
+
}),
|
2645
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Information, { activeTab: status })
|
2646
|
+
}
|
2647
|
+
);
|
2648
|
+
}
|
2649
|
+
}
|
2650
|
+
)
|
2542
2651
|
] });
|
2543
2652
|
};
|
2544
|
-
const
|
2545
|
-
|
2546
|
-
|
2653
|
+
const Information = ({ activeTab }) => {
|
2654
|
+
const { formatMessage } = reactIntl.useIntl();
|
2655
|
+
const { document, meta } = useDoc();
|
2656
|
+
if (!document || !document.id) {
|
2657
|
+
return null;
|
2658
|
+
}
|
2659
|
+
const createAndUpdateDocument = activeTab === "draft" ? document : meta?.availableStatus.find((status) => status.publishedAt === null);
|
2660
|
+
const publishDocument = activeTab === "published" ? document : meta?.availableStatus.find((status) => status.publishedAt !== null);
|
2661
|
+
const creator = createAndUpdateDocument?.[CREATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[CREATED_BY_ATTRIBUTE_NAME]) : null;
|
2662
|
+
const updator = createAndUpdateDocument?.[UPDATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[UPDATED_BY_ATTRIBUTE_NAME]) : null;
|
2663
|
+
const information = [
|
2547
2664
|
{
|
2548
|
-
|
2549
|
-
|
2550
|
-
|
2551
|
-
|
2552
|
-
borderColor: "neutral150",
|
2553
|
-
hasRadius: true,
|
2554
|
-
paddingBottom: 4,
|
2555
|
-
paddingLeft: 4,
|
2556
|
-
paddingRight: 4,
|
2557
|
-
paddingTop: 4,
|
2558
|
-
shadow: "tableShadow",
|
2559
|
-
gap: 3,
|
2560
|
-
direction: "column",
|
2561
|
-
justifyContent: "stretch",
|
2562
|
-
alignItems: "flex-start",
|
2563
|
-
children: [
|
2564
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2565
|
-
children
|
2566
|
-
]
|
2567
|
-
}
|
2568
|
-
);
|
2569
|
-
});
|
2570
|
-
const HOOKS = {
|
2571
|
-
/**
|
2572
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2573
|
-
* @constant
|
2574
|
-
* @type {string}
|
2575
|
-
*/
|
2576
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2577
|
-
/**
|
2578
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2579
|
-
* @constant
|
2580
|
-
* @type {string}
|
2581
|
-
*/
|
2582
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2583
|
-
/**
|
2584
|
-
* Hook that allows to mutate the CM's edit view layout
|
2585
|
-
* @constant
|
2586
|
-
* @type {string}
|
2587
|
-
*/
|
2588
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2589
|
-
/**
|
2590
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2591
|
-
* @constant
|
2592
|
-
* @type {string}
|
2593
|
-
*/
|
2594
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2595
|
-
};
|
2596
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2597
|
-
endpoints: (builder) => ({
|
2598
|
-
getContentTypeConfiguration: builder.query({
|
2599
|
-
query: (uid) => ({
|
2600
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2601
|
-
method: "GET"
|
2665
|
+
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2666
|
+
label: formatMessage({
|
2667
|
+
id: "content-manager.containers.edit.information.last-published.label",
|
2668
|
+
defaultMessage: "Last published"
|
2602
2669
|
}),
|
2603
|
-
|
2604
|
-
|
2605
|
-
|
2606
|
-
|
2607
|
-
|
2608
|
-
|
2609
|
-
|
2610
|
-
|
2611
|
-
|
2612
|
-
|
2613
|
-
|
2614
|
-
|
2615
|
-
|
2616
|
-
|
2617
|
-
|
2618
|
-
|
2670
|
+
value: formatMessage(
|
2671
|
+
{
|
2672
|
+
id: "content-manager.containers.edit.information.last-published.value",
|
2673
|
+
defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
|
2674
|
+
},
|
2675
|
+
{
|
2676
|
+
time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
2677
|
+
isAnonymous: !publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME],
|
2678
|
+
author: publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME] ? getDisplayName(publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME]) : null
|
2679
|
+
}
|
2680
|
+
)
|
2681
|
+
},
|
2682
|
+
{
|
2683
|
+
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2684
|
+
label: formatMessage({
|
2685
|
+
id: "content-manager.containers.edit.information.last-draft.label",
|
2686
|
+
defaultMessage: "Last draft"
|
2687
|
+
}),
|
2688
|
+
value: formatMessage(
|
2689
|
+
{
|
2690
|
+
id: "content-manager.containers.edit.information.last-draft.value",
|
2691
|
+
defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
|
2692
|
+
},
|
2693
|
+
{
|
2694
|
+
time: /* @__PURE__ */ jsxRuntime.jsx(
|
2695
|
+
RelativeTime,
|
2696
|
+
{
|
2697
|
+
timestamp: new Date(createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME])
|
2698
|
+
}
|
2699
|
+
),
|
2700
|
+
isAnonymous: !updator,
|
2701
|
+
author: updator
|
2702
|
+
}
|
2703
|
+
)
|
2704
|
+
},
|
2705
|
+
{
|
2706
|
+
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2707
|
+
label: formatMessage({
|
2708
|
+
id: "content-manager.containers.edit.information.document.label",
|
2709
|
+
defaultMessage: "Document"
|
2619
2710
|
}),
|
2620
|
-
|
2621
|
-
|
2622
|
-
|
2623
|
-
|
2624
|
-
|
2625
|
-
{
|
2626
|
-
|
2627
|
-
|
2628
|
-
|
2629
|
-
|
2630
|
-
|
2631
|
-
|
2632
|
-
|
2633
|
-
|
2634
|
-
}
|
2635
|
-
|
2636
|
-
|
2637
|
-
|
2638
|
-
|
2639
|
-
|
2640
|
-
|
2641
|
-
|
2642
|
-
|
2643
|
-
|
2644
|
-
|
2645
|
-
|
2646
|
-
|
2647
|
-
|
2648
|
-
|
2711
|
+
value: formatMessage(
|
2712
|
+
{
|
2713
|
+
id: "content-manager.containers.edit.information.document.value",
|
2714
|
+
defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
|
2715
|
+
},
|
2716
|
+
{
|
2717
|
+
time: /* @__PURE__ */ jsxRuntime.jsx(
|
2718
|
+
RelativeTime,
|
2719
|
+
{
|
2720
|
+
timestamp: new Date(createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME])
|
2721
|
+
}
|
2722
|
+
),
|
2723
|
+
isAnonymous: !creator,
|
2724
|
+
author: creator
|
2725
|
+
}
|
2726
|
+
)
|
2727
|
+
}
|
2728
|
+
].filter((info) => info.isDisplayed);
|
2729
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2730
|
+
designSystem.Flex,
|
2731
|
+
{
|
2732
|
+
borderWidth: "1px 0 0 0",
|
2733
|
+
borderStyle: "solid",
|
2734
|
+
borderColor: "neutral150",
|
2735
|
+
direction: "column",
|
2736
|
+
marginTop: 2,
|
2737
|
+
tag: "dl",
|
2738
|
+
padding: 5,
|
2739
|
+
gap: 3,
|
2740
|
+
alignItems: "flex-start",
|
2741
|
+
marginLeft: "-0.4rem",
|
2742
|
+
marginRight: "-0.4rem",
|
2743
|
+
width: "calc(100% + 8px)",
|
2744
|
+
children: information.map((info) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
|
2745
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
|
2746
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
|
2747
|
+
] }, info.label))
|
2748
|
+
}
|
2649
2749
|
);
|
2650
|
-
return {
|
2651
|
-
name: mainFieldName,
|
2652
|
-
type: mainFieldType ?? "string"
|
2653
|
-
};
|
2654
|
-
};
|
2655
|
-
const DEFAULT_SETTINGS = {
|
2656
|
-
bulkable: false,
|
2657
|
-
filterable: false,
|
2658
|
-
searchable: false,
|
2659
|
-
pagination: false,
|
2660
|
-
defaultSortBy: "",
|
2661
|
-
defaultSortOrder: "asc",
|
2662
|
-
mainField: "id",
|
2663
|
-
pageSize: 10
|
2664
2750
|
};
|
2665
|
-
const
|
2666
|
-
const
|
2667
|
-
const
|
2668
|
-
|
2669
|
-
|
2670
|
-
|
2671
|
-
|
2672
|
-
|
2673
|
-
|
2674
|
-
|
2675
|
-
error,
|
2676
|
-
isFetching: isFetchingConfigs
|
2677
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2678
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2679
|
-
React__namespace.useEffect(() => {
|
2680
|
-
if (error) {
|
2681
|
-
toggleNotification({
|
2682
|
-
type: "danger",
|
2683
|
-
message: formatAPIError(error)
|
2684
|
-
});
|
2751
|
+
const HeaderActions = ({ actions: actions2 }) => {
|
2752
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2753
|
+
const handleClick = (action) => async (e) => {
|
2754
|
+
if (!("options" in action)) {
|
2755
|
+
const { onClick = () => false, dialog, id } = action;
|
2756
|
+
const muteDialog = await onClick(e);
|
2757
|
+
if (dialog && !muteDialog) {
|
2758
|
+
e.preventDefault();
|
2759
|
+
setDialogId(id);
|
2760
|
+
}
|
2685
2761
|
}
|
2686
|
-
}, [error, formatAPIError, toggleNotification]);
|
2687
|
-
const editLayout = React__namespace.useMemo(
|
2688
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2689
|
-
layout: [],
|
2690
|
-
components: {},
|
2691
|
-
metadatas: {},
|
2692
|
-
options: {},
|
2693
|
-
settings: DEFAULT_SETTINGS
|
2694
|
-
},
|
2695
|
-
[data, isLoading, schemas, schema, components]
|
2696
|
-
);
|
2697
|
-
const listLayout = React__namespace.useMemo(() => {
|
2698
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2699
|
-
layout: [],
|
2700
|
-
metadatas: {},
|
2701
|
-
options: {},
|
2702
|
-
settings: DEFAULT_SETTINGS
|
2703
|
-
};
|
2704
|
-
}, [data, isLoading, schemas, schema, components]);
|
2705
|
-
const { layout: edit } = React__namespace.useMemo(
|
2706
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2707
|
-
layout: editLayout,
|
2708
|
-
query
|
2709
|
-
}),
|
2710
|
-
[editLayout, query, runHookWaterfall]
|
2711
|
-
);
|
2712
|
-
return {
|
2713
|
-
error,
|
2714
|
-
isLoading,
|
2715
|
-
edit,
|
2716
|
-
list: listLayout
|
2717
2762
|
};
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
return
|
2722
|
-
|
2723
|
-
|
2724
|
-
|
2725
|
-
|
2726
|
-
|
2727
|
-
|
2728
|
-
|
2729
|
-
|
2730
|
-
|
2731
|
-
|
2732
|
-
|
2733
|
-
|
2734
|
-
|
2735
|
-
).reduce((panels, row) => {
|
2736
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2737
|
-
panels.push([row]);
|
2738
|
-
currentPanelIndex += 2;
|
2763
|
+
const handleClose = () => {
|
2764
|
+
setDialogId(null);
|
2765
|
+
};
|
2766
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2767
|
+
if (action.options) {
|
2768
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2769
|
+
designSystem.SingleSelect,
|
2770
|
+
{
|
2771
|
+
size: "S",
|
2772
|
+
disabled: action.disabled,
|
2773
|
+
"aria-label": action.label,
|
2774
|
+
onChange: action.onSelect,
|
2775
|
+
value: action.value,
|
2776
|
+
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2777
|
+
},
|
2778
|
+
action.id
|
2779
|
+
);
|
2739
2780
|
} else {
|
2740
|
-
if (
|
2741
|
-
|
2781
|
+
if (action.type === "icon") {
|
2782
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2783
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2784
|
+
designSystem.IconButton,
|
2785
|
+
{
|
2786
|
+
disabled: action.disabled,
|
2787
|
+
label: action.label,
|
2788
|
+
size: "S",
|
2789
|
+
onClick: handleClick(action),
|
2790
|
+
children: action.icon
|
2791
|
+
}
|
2792
|
+
),
|
2793
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2794
|
+
HeaderActionDialog,
|
2795
|
+
{
|
2796
|
+
...action.dialog,
|
2797
|
+
isOpen: dialogId === action.id,
|
2798
|
+
onClose: handleClose
|
2799
|
+
}
|
2800
|
+
) : null
|
2801
|
+
] }, action.id);
|
2742
2802
|
}
|
2743
|
-
panels[currentPanelIndex].push(row);
|
2744
2803
|
}
|
2745
|
-
|
2746
|
-
|
2747
|
-
|
2748
|
-
|
2749
|
-
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
|
2754
|
-
|
2755
|
-
|
2756
|
-
|
2757
|
-
|
2758
|
-
|
2759
|
-
|
2760
|
-
|
2761
|
-
|
2762
|
-
}
|
2763
|
-
|
2764
|
-
|
2765
|
-
|
2766
|
-
|
2767
|
-
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2804
|
+
}) });
|
2805
|
+
};
|
2806
|
+
const HeaderActionDialog = ({
|
2807
|
+
onClose,
|
2808
|
+
onCancel,
|
2809
|
+
title,
|
2810
|
+
content: Content,
|
2811
|
+
isOpen
|
2812
|
+
}) => {
|
2813
|
+
const handleClose = async () => {
|
2814
|
+
if (onCancel) {
|
2815
|
+
await onCancel();
|
2816
|
+
}
|
2817
|
+
onClose();
|
2818
|
+
};
|
2819
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2820
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2821
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2822
|
+
] }) });
|
2823
|
+
};
|
2824
|
+
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2825
|
+
const navigate = reactRouterDom.useNavigate();
|
2826
|
+
const { formatMessage } = reactIntl.useIntl();
|
2827
|
+
return {
|
2828
|
+
label: formatMessage({
|
2829
|
+
id: "app.links.configure-view",
|
2830
|
+
defaultMessage: "Configure the view"
|
2831
|
+
}),
|
2832
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
|
2833
|
+
onClick: () => {
|
2834
|
+
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2771
2835
|
},
|
2772
|
-
|
2773
|
-
|
2836
|
+
position: "header"
|
2837
|
+
};
|
2838
|
+
};
|
2839
|
+
ConfigureTheViewAction.type = "configure-the-view";
|
2840
|
+
const EditTheModelAction = ({ model }) => {
|
2841
|
+
const navigate = reactRouterDom.useNavigate();
|
2842
|
+
const { formatMessage } = reactIntl.useIntl();
|
2774
2843
|
return {
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2780
|
-
|
2844
|
+
label: formatMessage({
|
2845
|
+
id: "content-manager.link-to-ctb",
|
2846
|
+
defaultMessage: "Edit the model"
|
2847
|
+
}),
|
2848
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
|
2849
|
+
onClick: () => {
|
2850
|
+
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2781
2851
|
},
|
2782
|
-
|
2783
|
-
...schema?.options,
|
2784
|
-
...schema?.pluginOptions,
|
2785
|
-
...data.contentType.options
|
2786
|
-
}
|
2852
|
+
position: "header"
|
2787
2853
|
};
|
2788
2854
|
};
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2855
|
+
EditTheModelAction.type = "edit-the-model";
|
2856
|
+
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2857
|
+
const navigate = reactRouterDom.useNavigate();
|
2858
|
+
const { formatMessage } = reactIntl.useIntl();
|
2859
|
+
const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
|
2860
|
+
const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
|
2861
|
+
const { delete: deleteAction } = useDocumentActions();
|
2862
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2863
|
+
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2864
|
+
const isLocalized = document?.locale != null;
|
2865
|
+
return {
|
2866
|
+
disabled: !canDelete || !document,
|
2867
|
+
label: formatMessage(
|
2868
|
+
{
|
2869
|
+
id: "content-manager.actions.delete.label",
|
2870
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2871
|
+
},
|
2872
|
+
{ isLocalized }
|
2873
|
+
),
|
2874
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2875
|
+
dialog: {
|
2876
|
+
type: "dialog",
|
2877
|
+
title: formatMessage({
|
2878
|
+
id: "app.components.ConfirmDialog.title",
|
2879
|
+
defaultMessage: "Confirmation"
|
2880
|
+
}),
|
2881
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2882
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2883
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2884
|
+
id: "content-manager.actions.delete.dialog.body",
|
2885
|
+
defaultMessage: "Are you sure?"
|
2886
|
+
}) })
|
2887
|
+
] }),
|
2888
|
+
onConfirm: async () => {
|
2889
|
+
if (!listViewPathMatch) {
|
2890
|
+
setSubmitting(true);
|
2891
|
+
}
|
2892
|
+
try {
|
2893
|
+
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2894
|
+
console.error(
|
2895
|
+
"You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2896
|
+
);
|
2897
|
+
toggleNotification({
|
2898
|
+
message: formatMessage({
|
2899
|
+
id: "content-manager.actions.delete.error",
|
2900
|
+
defaultMessage: "An error occurred while trying to delete the document."
|
2901
|
+
}),
|
2902
|
+
type: "danger"
|
2903
|
+
});
|
2904
|
+
return;
|
2905
|
+
}
|
2906
|
+
const res = await deleteAction({
|
2907
|
+
documentId,
|
2908
|
+
model,
|
2909
|
+
collectionType,
|
2910
|
+
params: {
|
2911
|
+
locale: "*"
|
2912
|
+
}
|
2913
|
+
});
|
2914
|
+
if (!("error" in res)) {
|
2915
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2916
|
+
}
|
2917
|
+
} finally {
|
2918
|
+
if (!listViewPathMatch) {
|
2919
|
+
setSubmitting(false);
|
2920
|
+
}
|
2921
|
+
}
|
2795
2922
|
}
|
2796
|
-
const { edit: metadata } = metadatas[field.name];
|
2797
|
-
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2798
|
-
return {
|
2799
|
-
attribute,
|
2800
|
-
disabled: !metadata.editable,
|
2801
|
-
hint: metadata.description,
|
2802
|
-
label: metadata.label ?? "",
|
2803
|
-
name: field.name,
|
2804
|
-
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
2805
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2806
|
-
schemas,
|
2807
|
-
components: components?.schemas ?? {}
|
2808
|
-
}),
|
2809
|
-
placeholder: metadata.placeholder ?? "",
|
2810
|
-
required: attribute.required ?? false,
|
2811
|
-
size: field.size,
|
2812
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
2813
|
-
visible: metadata.visible ?? true,
|
2814
|
-
type: attribute.type
|
2815
|
-
};
|
2816
|
-
}).filter((field) => field !== null)
|
2817
|
-
);
|
2818
|
-
};
|
2819
|
-
const formatListLayout = (data, {
|
2820
|
-
schemas,
|
2821
|
-
schema,
|
2822
|
-
components
|
2823
|
-
}) => {
|
2824
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2825
|
-
(acc, [attribute, metadata]) => {
|
2826
|
-
return {
|
2827
|
-
...acc,
|
2828
|
-
[attribute]: metadata.list
|
2829
|
-
};
|
2830
2923
|
},
|
2831
|
-
|
2832
|
-
|
2833
|
-
|
2834
|
-
|
2835
|
-
|
2836
|
-
|
2837
|
-
|
2838
|
-
|
2839
|
-
|
2840
|
-
|
2841
|
-
|
2842
|
-
|
2843
|
-
|
2844
|
-
|
2845
|
-
|
2846
|
-
|
2847
|
-
|
2924
|
+
variant: "danger",
|
2925
|
+
position: ["header", "table-row"]
|
2926
|
+
};
|
2927
|
+
};
|
2928
|
+
DeleteAction$1.type = "delete";
|
2929
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2930
|
+
const Panels = () => {
|
2931
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2932
|
+
const [
|
2933
|
+
{
|
2934
|
+
query: { status }
|
2935
|
+
}
|
2936
|
+
] = strapiAdmin.useQueryParams({
|
2937
|
+
status: "draft"
|
2938
|
+
});
|
2939
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2940
|
+
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2941
|
+
const props = {
|
2942
|
+
activeTab: status,
|
2943
|
+
model,
|
2944
|
+
documentId: id,
|
2945
|
+
document: isCloning ? void 0 : document,
|
2946
|
+
meta: isCloning ? void 0 : meta,
|
2947
|
+
collectionType
|
2948
|
+
};
|
2949
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2950
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2951
|
+
{
|
2952
|
+
props,
|
2953
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2954
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2848
2955
|
}
|
2956
|
+
) });
|
2957
|
+
};
|
2958
|
+
const ActionsPanel = () => {
|
2959
|
+
const { formatMessage } = reactIntl.useIntl();
|
2960
|
+
return {
|
2961
|
+
title: formatMessage({
|
2962
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2963
|
+
defaultMessage: "Entry"
|
2964
|
+
}),
|
2965
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2849
2966
|
};
|
2850
2967
|
};
|
2851
|
-
|
2852
|
-
|
2853
|
-
|
2854
|
-
|
2855
|
-
|
2968
|
+
ActionsPanel.type = "actions";
|
2969
|
+
const ActionsPanelContent = () => {
|
2970
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2971
|
+
const [
|
2972
|
+
{
|
2973
|
+
query: { status = "draft" }
|
2856
2974
|
}
|
2857
|
-
|
2858
|
-
|
2859
|
-
|
2860
|
-
|
2861
|
-
|
2862
|
-
|
2863
|
-
|
2864
|
-
|
2865
|
-
|
2866
|
-
|
2867
|
-
|
2868
|
-
|
2869
|
-
|
2870
|
-
|
2975
|
+
] = strapiAdmin.useQueryParams();
|
2976
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2977
|
+
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2978
|
+
const props = {
|
2979
|
+
activeTab: status,
|
2980
|
+
model,
|
2981
|
+
documentId: id,
|
2982
|
+
document: isCloning ? void 0 : document,
|
2983
|
+
meta: isCloning ? void 0 : meta,
|
2984
|
+
collectionType
|
2985
|
+
};
|
2986
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2987
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2988
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2989
|
+
{
|
2990
|
+
props,
|
2991
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2992
|
+
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
2993
|
+
}
|
2994
|
+
),
|
2995
|
+
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2996
|
+
] });
|
2871
2997
|
};
|
2998
|
+
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
2999
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
3000
|
+
designSystem.Flex,
|
3001
|
+
{
|
3002
|
+
ref,
|
3003
|
+
tag: "aside",
|
3004
|
+
"aria-labelledby": "additional-information",
|
3005
|
+
background: "neutral0",
|
3006
|
+
borderColor: "neutral150",
|
3007
|
+
hasRadius: true,
|
3008
|
+
paddingBottom: 4,
|
3009
|
+
paddingLeft: 4,
|
3010
|
+
paddingRight: 4,
|
3011
|
+
paddingTop: 4,
|
3012
|
+
shadow: "tableShadow",
|
3013
|
+
gap: 3,
|
3014
|
+
direction: "column",
|
3015
|
+
justifyContent: "stretch",
|
3016
|
+
alignItems: "flex-start",
|
3017
|
+
children: [
|
3018
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
3019
|
+
children
|
3020
|
+
]
|
3021
|
+
}
|
3022
|
+
);
|
3023
|
+
});
|
2872
3024
|
const ConfirmBulkActionDialog = ({
|
2873
3025
|
onToggleDialog,
|
2874
3026
|
isOpen = false,
|
@@ -2907,6 +3059,7 @@ const ConfirmDialogPublishAll = ({
|
|
2907
3059
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
2908
3060
|
const { model, schema } = useDoc();
|
2909
3061
|
const [{ query }] = strapiAdmin.useQueryParams();
|
3062
|
+
const enableDraftRelationsCount = false;
|
2910
3063
|
const {
|
2911
3064
|
data: countDraftRelations = 0,
|
2912
3065
|
isLoading,
|
@@ -2918,7 +3071,7 @@ const ConfirmDialogPublishAll = ({
|
|
2918
3071
|
locale: query?.plugins?.i18n?.locale
|
2919
3072
|
},
|
2920
3073
|
{
|
2921
|
-
skip:
|
3074
|
+
skip: !enableDraftRelationsCount
|
2922
3075
|
}
|
2923
3076
|
);
|
2924
3077
|
React__namespace.useEffect(() => {
|
@@ -3103,7 +3256,7 @@ const SelectedEntriesTableContent = ({
|
|
3103
3256
|
status: row.status
|
3104
3257
|
}
|
3105
3258
|
) }),
|
3106
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3259
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3107
3260
|
designSystem.IconButton,
|
3108
3261
|
{
|
3109
3262
|
tag: reactRouterDom.Link,
|
@@ -3126,9 +3279,10 @@ const SelectedEntriesTableContent = ({
|
|
3126
3279
|
),
|
3127
3280
|
target: "_blank",
|
3128
3281
|
marginLeft: "auto",
|
3129
|
-
|
3282
|
+
variant: "ghost",
|
3283
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3130
3284
|
}
|
3131
|
-
) })
|
3285
|
+
) }) })
|
3132
3286
|
] }, row.id)) })
|
3133
3287
|
] });
|
3134
3288
|
};
|
@@ -3165,7 +3319,13 @@ const SelectedEntriesModalContent = ({
|
|
3165
3319
|
);
|
3166
3320
|
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3167
3321
|
if (data.length > 0 && schema) {
|
3168
|
-
const validate = createYupSchema(
|
3322
|
+
const validate = createYupSchema(
|
3323
|
+
schema.attributes,
|
3324
|
+
components,
|
3325
|
+
// Since this is the "Publish" action, the validation
|
3326
|
+
// schema must enforce the rules for published entities
|
3327
|
+
{ status: "published" }
|
3328
|
+
);
|
3169
3329
|
const validationErrors2 = {};
|
3170
3330
|
const rows2 = data.map((entry) => {
|
3171
3331
|
try {
|
@@ -3515,7 +3675,7 @@ const TableActions = ({ document }) => {
|
|
3515
3675
|
strapiAdmin.DescriptionComponentRenderer,
|
3516
3676
|
{
|
3517
3677
|
props,
|
3518
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3678
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3519
3679
|
children: (actions2) => {
|
3520
3680
|
const tableRowActions = actions2.filter((action) => {
|
3521
3681
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3626,7 +3786,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3626
3786
|
}),
|
3627
3787
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3628
3788
|
footer: ({ onClose }) => {
|
3629
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3789
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3630
3790
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3631
3791
|
id: "cancel",
|
3632
3792
|
defaultMessage: "Cancel"
|
@@ -3857,7 +4017,7 @@ const index = {
|
|
3857
4017
|
app.router.addRoute({
|
3858
4018
|
path: "content-manager/*",
|
3859
4019
|
lazy: async () => {
|
3860
|
-
const { Layout } = await Promise.resolve().then(() => require("./layout-
|
4020
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-CWgZzMYf.js"));
|
3861
4021
|
return {
|
3862
4022
|
Component: Layout
|
3863
4023
|
};
|
@@ -3874,7 +4034,7 @@ const index = {
|
|
3874
4034
|
async registerTrads({ locales }) {
|
3875
4035
|
const importedTrads = await Promise.all(
|
3876
4036
|
locales.map((locale) => {
|
3877
|
-
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-
|
4037
|
+
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-BlhnxQfj.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`).then(({ default: data }) => {
|
3878
4038
|
return {
|
3879
4039
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3880
4040
|
locale
|
@@ -3892,6 +4052,7 @@ const index = {
|
|
3892
4052
|
};
|
3893
4053
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
3894
4054
|
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4055
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3895
4056
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3896
4057
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3897
4058
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3919,6 +4080,7 @@ exports.getMainField = getMainField;
|
|
3919
4080
|
exports.getTranslation = getTranslation;
|
3920
4081
|
exports.index = index;
|
3921
4082
|
exports.setInitialData = setInitialData;
|
4083
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3922
4084
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3923
4085
|
exports.useDoc = useDoc;
|
3924
4086
|
exports.useDocLayout = useDocLayout;
|
@@ -3931,4 +4093,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
|
3931
4093
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3932
4094
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
3933
4095
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3934
|
-
//# sourceMappingURL=index-
|
4096
|
+
//# sourceMappingURL=index-DTKVhcla.js.map
|