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