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