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