@strapi/i18n 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813 → 0.0.0-experimental.e9122b401c96877b6707775c4f893660eab93ae3
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/LICENSE +18 -3
- package/dist/_chunks/{SettingsPage-CeqfDjsb.mjs → SettingsPage-BjxjwEOb.mjs} +115 -126
- package/dist/_chunks/SettingsPage-BjxjwEOb.mjs.map +1 -0
- package/dist/_chunks/{SettingsPage-Djqsdrzs.js → SettingsPage-CfTmCkup.js} +115 -126
- package/dist/_chunks/SettingsPage-CfTmCkup.js.map +1 -0
- package/dist/_chunks/{en-CnrTsjWS.mjs → en-2xztdZE1.mjs} +12 -1
- package/dist/_chunks/en-2xztdZE1.mjs.map +1 -0
- package/dist/_chunks/{en-BuBc6LKZ.js → en-DWpfm8h5.js} +12 -1
- package/dist/_chunks/en-DWpfm8h5.js.map +1 -0
- package/dist/_chunks/{index-DMXJeGjN.js → index-5XLZwzwx.js} +711 -207
- package/dist/_chunks/index-5XLZwzwx.js.map +1 -0
- package/dist/_chunks/{index-BDU1w_fd.mjs → index-D-qx3tz4.mjs} +710 -204
- package/dist/_chunks/index-D-qx3tz4.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +2 -2
- package/dist/admin/src/components/BulkLocaleActionModal.d.ts +16 -0
- package/dist/admin/src/components/CMHeaderActions.d.ts +33 -3
- package/dist/admin/src/components/EditLocale.d.ts +5 -4
- package/dist/admin/src/contentReleasesHooks/releaseDetailsView.d.ts +9 -5
- package/dist/admin/src/services/api.d.ts +2 -3
- package/dist/admin/src/services/locales.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +7 -0
- package/dist/admin/src/utils/baseQuery.d.ts +4 -19
- package/dist/admin/src/utils/clean.d.ts +4 -0
- package/dist/admin/src/utils/schemas.d.ts +1 -0
- package/dist/server/index.js +38 -9
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +39 -10
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +14 -2
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +14 -2
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permissions/actions.d.ts +14 -2
- package/dist/server/src/services/permissions/actions.d.ts.map +1 -1
- package/dist/server/src/services/permissions.d.ts +14 -2
- package/dist/server/src/services/permissions.d.ts.map +1 -1
- package/dist/shared/contracts/content-manager.d.ts +20 -1
- package/package.json +15 -16
- package/dist/_chunks/SettingsPage-CeqfDjsb.mjs.map +0 -1
- package/dist/_chunks/SettingsPage-Djqsdrzs.js.map +0 -1
- package/dist/_chunks/en-BuBc6LKZ.js.map +0 -1
- package/dist/_chunks/en-CnrTsjWS.mjs.map +0 -1
- package/dist/_chunks/index-BDU1w_fd.mjs.map +0 -1
- package/dist/_chunks/index-DMXJeGjN.js.map +0 -1
- package/dist/admin/src/components/Initializer.d.ts +0 -5
@@ -1,17 +1,17 @@
|
|
1
1
|
import get from "lodash/get";
|
2
2
|
import * as yup from "yup";
|
3
|
-
import { jsxs,
|
3
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
4
4
|
import * as React from "react";
|
5
|
-
import { Typography,
|
6
|
-
import { WarningCircle, Trash, Earth, EarthStriked, CaretDown } from "@strapi/icons";
|
5
|
+
import { Typography, Dialog, Field, Checkbox, Flex, Button, Modal, Box, Status, IconButton, Tooltip, SingleSelect, SingleSelectOption, VisuallyHidden, useCollator, Popover } from "@strapi/design-system";
|
6
|
+
import { WarningCircle, Pencil, CrossCircle, CheckCircle, ArrowsCounterClockwise, Trash, Download, ListPlus, Cross, Earth, EarthStriked, CaretDown } from "@strapi/icons";
|
7
7
|
import { useIntl } from "react-intl";
|
8
|
-
import styled from "styled-components";
|
9
|
-
import {
|
10
|
-
import {
|
11
|
-
import {
|
12
|
-
import {
|
13
|
-
import { isAxiosError } from "axios";
|
8
|
+
import { styled } from "styled-components";
|
9
|
+
import { skipToken } from "@reduxjs/toolkit/query";
|
10
|
+
import { useAuth, adminApi, useTable, Table, useQueryParams, useForm, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
|
11
|
+
import { unstable_useDocument, unstable_useDocumentActions, buildValidParams } from "@strapi/content-manager/strapi-admin";
|
12
|
+
import { useParams, Link, useNavigate, matchPath } from "react-router-dom";
|
14
13
|
import * as qs from "qs";
|
14
|
+
import { stringify } from "qs";
|
15
15
|
import omit from "lodash/omit";
|
16
16
|
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
17
17
|
const v = glob[path];
|
@@ -48,9 +48,7 @@ const CheckboxConfirmation = ({
|
|
48
48
|
};
|
49
49
|
const handleConfirm = () => {
|
50
50
|
onChange({ target: { name, value: false, type: "checkbox" } });
|
51
|
-
setIsOpen(false);
|
52
51
|
};
|
53
|
-
const handleToggle = () => setIsOpen((prev) => !prev);
|
54
52
|
const label = intlLabel.id ? formatMessage(
|
55
53
|
{ id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
|
56
54
|
{ ...intlLabel.values }
|
@@ -59,43 +57,36 @@ const CheckboxConfirmation = ({
|
|
59
57
|
{ id: description.id, defaultMessage: description.defaultMessage },
|
60
58
|
{ ...description.values }
|
61
59
|
) : "";
|
62
|
-
return /* @__PURE__ */ jsxs(
|
63
|
-
/* @__PURE__ */
|
64
|
-
Checkbox,
|
65
|
-
{
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
),
|
75
|
-
isOpen && /* @__PURE__ */ jsxs(Dialog, { onClose: handleToggle, title: "Confirmation", isOpen, children: [
|
76
|
-
/* @__PURE__ */ jsx(DialogBody, { icon: /* @__PURE__ */ jsx(WarningCircle, {}), children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
77
|
-
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(TextAlignTypography, { id: "confirm-description", children: formatMessage({
|
60
|
+
return /* @__PURE__ */ jsxs(Dialog.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
61
|
+
/* @__PURE__ */ jsxs(Field.Root, { hint, name, children: [
|
62
|
+
/* @__PURE__ */ jsx(Checkbox, { onCheckedChange: handleChange, checked: value, children: label }),
|
63
|
+
/* @__PURE__ */ jsx(Field.Hint, {})
|
64
|
+
] }),
|
65
|
+
/* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
66
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
|
67
|
+
id: getTranslation("CheckboxConfirmation.Modal.title"),
|
68
|
+
defaultMessage: "Disable localization"
|
69
|
+
}) }),
|
70
|
+
/* @__PURE__ */ jsx(Dialog.Body, { icon: /* @__PURE__ */ jsx(WarningCircle, {}), children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
71
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(TextAlignTypography, { children: formatMessage({
|
78
72
|
id: getTranslation("CheckboxConfirmation.Modal.content"),
|
79
73
|
defaultMessage: "Disabling localization will engender the deletion of all your content but the one associated to your default locale (if existing)."
|
80
74
|
}) }) }),
|
81
|
-
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold",
|
75
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: formatMessage({
|
82
76
|
id: getTranslation("CheckboxConfirmation.Modal.body"),
|
83
77
|
defaultMessage: "Do you want to disable it?"
|
84
78
|
}) }) })
|
85
79
|
] }) }),
|
86
|
-
/* @__PURE__ */
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
}) })
|
97
|
-
}
|
98
|
-
)
|
80
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
81
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
82
|
+
id: "components.popUpWarning.button.cancel",
|
83
|
+
defaultMessage: "No, cancel"
|
84
|
+
}) }) }),
|
85
|
+
/* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
|
86
|
+
id: getTranslation("CheckboxConfirmation.Modal.button-confirm"),
|
87
|
+
defaultMessage: "Yes, disable"
|
88
|
+
}) }) })
|
89
|
+
] })
|
99
90
|
] })
|
100
91
|
] });
|
101
92
|
};
|
@@ -146,7 +137,7 @@ const useI18n = () => {
|
|
146
137
|
model: params.slug
|
147
138
|
},
|
148
139
|
{
|
149
|
-
skip:
|
140
|
+
skip: true
|
150
141
|
}
|
151
142
|
);
|
152
143
|
if (doesPluginOptionsHaveI18nLocalized(schema?.pluginOptions)) {
|
@@ -160,64 +151,8 @@ const useI18n = () => {
|
|
160
151
|
...actions
|
161
152
|
};
|
162
153
|
};
|
163
|
-
const
|
164
|
-
|
165
|
-
const { get: get2, post, del, put } = getFetchClient();
|
166
|
-
if (typeof query === "string") {
|
167
|
-
const result = await get2(query, { signal });
|
168
|
-
return { data: result.data };
|
169
|
-
} else {
|
170
|
-
const { url, method = "GET", data, config } = query;
|
171
|
-
if (method === "POST") {
|
172
|
-
const result2 = await post(url, data, { ...config, signal });
|
173
|
-
return { data: result2.data };
|
174
|
-
}
|
175
|
-
if (method === "DELETE") {
|
176
|
-
const result2 = await del(url, { ...config, signal });
|
177
|
-
return { data: result2.data };
|
178
|
-
}
|
179
|
-
if (method === "PUT") {
|
180
|
-
const result2 = await put(url, data, { ...config, signal });
|
181
|
-
return { data: result2.data };
|
182
|
-
}
|
183
|
-
const result = await get2(url, { ...config, signal });
|
184
|
-
return { data: result.data };
|
185
|
-
}
|
186
|
-
} catch (err) {
|
187
|
-
if (isAxiosError(err)) {
|
188
|
-
if (typeof err.response?.data === "object" && err.response?.data !== null && "error" in err.response?.data) {
|
189
|
-
return { data: void 0, error: err.response?.data.error };
|
190
|
-
} else {
|
191
|
-
return {
|
192
|
-
data: void 0,
|
193
|
-
error: {
|
194
|
-
name: "UnknownError",
|
195
|
-
message: "There was an unknown error response from the API",
|
196
|
-
details: err.response?.data,
|
197
|
-
status: err.response?.status
|
198
|
-
}
|
199
|
-
};
|
200
|
-
}
|
201
|
-
}
|
202
|
-
const error = err;
|
203
|
-
return {
|
204
|
-
data: void 0,
|
205
|
-
error: {
|
206
|
-
name: error.name,
|
207
|
-
message: error.message,
|
208
|
-
stack: error.stack
|
209
|
-
}
|
210
|
-
};
|
211
|
-
}
|
212
|
-
};
|
213
|
-
const isBaseQueryError = (error) => {
|
214
|
-
return error.name !== void 0;
|
215
|
-
};
|
216
|
-
const i18nApi = createApi({
|
217
|
-
reducerPath: "i18nApi",
|
218
|
-
baseQuery: axiosBaseQuery(),
|
219
|
-
tagTypes: ["Locale"],
|
220
|
-
endpoints: () => ({})
|
154
|
+
const i18nApi = adminApi.enhanceEndpoints({
|
155
|
+
addTagTypes: ["Locale"]
|
221
156
|
});
|
222
157
|
const localesApi = i18nApi.injectEndpoints({
|
223
158
|
endpoints: (builder) => ({
|
@@ -266,6 +201,295 @@ const {
|
|
266
201
|
useGetDefaultLocalesQuery,
|
267
202
|
useUpdateLocaleMutation
|
268
203
|
} = localesApi;
|
204
|
+
const relationsApi = i18nApi.injectEndpoints({
|
205
|
+
overrideExisting: true,
|
206
|
+
endpoints: (builder) => ({
|
207
|
+
getManyDraftRelationCount: builder.query({
|
208
|
+
query: ({ model, ...params }) => ({
|
209
|
+
url: `/content-manager/collection-types/${model}/actions/countManyEntriesDraftRelations`,
|
210
|
+
method: "GET",
|
211
|
+
config: {
|
212
|
+
params
|
213
|
+
}
|
214
|
+
}),
|
215
|
+
transformResponse: (response) => response.data
|
216
|
+
})
|
217
|
+
})
|
218
|
+
});
|
219
|
+
const { useGetManyDraftRelationCountQuery } = relationsApi;
|
220
|
+
const cleanData = (data, schema, components) => {
|
221
|
+
const cleanedData = removeFields(data, [
|
222
|
+
"createdAt",
|
223
|
+
"createdBy",
|
224
|
+
"updatedAt",
|
225
|
+
"updatedBy",
|
226
|
+
"id",
|
227
|
+
"documentId",
|
228
|
+
"publishedAt",
|
229
|
+
"strapi_stage",
|
230
|
+
"strapi_assignee",
|
231
|
+
"locale"
|
232
|
+
]);
|
233
|
+
const cleanedDataWithoutPasswordAndRelation = recursiveRemoveFieldTypes(
|
234
|
+
cleanedData,
|
235
|
+
schema,
|
236
|
+
components,
|
237
|
+
["relation", "password"]
|
238
|
+
);
|
239
|
+
return cleanedDataWithoutPasswordAndRelation;
|
240
|
+
};
|
241
|
+
const removeFields = (data, fields) => {
|
242
|
+
return Object.keys(data).reduce((acc, current) => {
|
243
|
+
if (fields.includes(current)) {
|
244
|
+
return acc;
|
245
|
+
}
|
246
|
+
acc[current] = data[current];
|
247
|
+
return acc;
|
248
|
+
}, {});
|
249
|
+
};
|
250
|
+
const recursiveRemoveFieldTypes = (data, schema, components, fields) => {
|
251
|
+
return Object.keys(data).reduce((acc, current) => {
|
252
|
+
const attribute = schema.attributes[current] ?? { type: void 0 };
|
253
|
+
if (fields.includes(attribute.type)) {
|
254
|
+
return acc;
|
255
|
+
}
|
256
|
+
if (attribute.type === "dynamiczone") {
|
257
|
+
acc[current] = data[current].map((componentValue, index2) => {
|
258
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
259
|
+
componentValue,
|
260
|
+
components[componentValue.__component],
|
261
|
+
components,
|
262
|
+
fields
|
263
|
+
);
|
264
|
+
return {
|
265
|
+
...rest,
|
266
|
+
__temp_key__: index2 + 1
|
267
|
+
};
|
268
|
+
});
|
269
|
+
} else if (attribute.type === "component") {
|
270
|
+
const { repeatable, component } = attribute;
|
271
|
+
if (repeatable) {
|
272
|
+
acc[current] = (data[current] ?? []).map((compoData, index2) => {
|
273
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
274
|
+
compoData,
|
275
|
+
components[component],
|
276
|
+
components,
|
277
|
+
fields
|
278
|
+
);
|
279
|
+
return {
|
280
|
+
...rest,
|
281
|
+
__temp_key__: index2 + 1
|
282
|
+
};
|
283
|
+
});
|
284
|
+
} else {
|
285
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
286
|
+
data[current] ?? {},
|
287
|
+
components[component],
|
288
|
+
components,
|
289
|
+
fields
|
290
|
+
);
|
291
|
+
acc[current] = rest;
|
292
|
+
}
|
293
|
+
} else {
|
294
|
+
acc[current] = data[current];
|
295
|
+
}
|
296
|
+
return acc;
|
297
|
+
}, {});
|
298
|
+
};
|
299
|
+
const isErrorMessageDescriptor = (object) => {
|
300
|
+
return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
|
301
|
+
};
|
302
|
+
const EntryValidationText = ({
|
303
|
+
status = "draft",
|
304
|
+
validationErrors,
|
305
|
+
action
|
306
|
+
}) => {
|
307
|
+
const { formatMessage } = useIntl();
|
308
|
+
const getErrorStr = (key, value) => {
|
309
|
+
if (typeof value === "string") {
|
310
|
+
return `${key}: ${value}`;
|
311
|
+
} else if (isErrorMessageDescriptor(value)) {
|
312
|
+
return `${key}: ${formatMessage(value)}`;
|
313
|
+
} else if (Array.isArray(value)) {
|
314
|
+
return value.map((v) => getErrorStr(key, v)).join(" ");
|
315
|
+
} else if (typeof value === "object" && !Array.isArray(value)) {
|
316
|
+
return Object.entries(value).map(([k, v]) => getErrorStr(k, v)).join(" ");
|
317
|
+
} else {
|
318
|
+
return "";
|
319
|
+
}
|
320
|
+
};
|
321
|
+
if (validationErrors) {
|
322
|
+
const validationErrorsMessages = Object.entries(validationErrors).map(([key, value]) => {
|
323
|
+
return getErrorStr(key, value);
|
324
|
+
}).join(" ");
|
325
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
326
|
+
/* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
|
327
|
+
/* @__PURE__ */ jsx(Tooltip, { label: validationErrorsMessages, children: /* @__PURE__ */ jsx(
|
328
|
+
Typography,
|
329
|
+
{
|
330
|
+
maxWidth: "30rem",
|
331
|
+
textColor: "danger600",
|
332
|
+
variant: "omega",
|
333
|
+
fontWeight: "semiBold",
|
334
|
+
ellipsis: true,
|
335
|
+
children: validationErrorsMessages
|
336
|
+
}
|
337
|
+
) })
|
338
|
+
] });
|
339
|
+
}
|
340
|
+
const getStatusMessage = () => {
|
341
|
+
if (action === "bulk-publish") {
|
342
|
+
if (status === "published") {
|
343
|
+
return {
|
344
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
345
|
+
text: formatMessage({
|
346
|
+
id: "content-manager.bulk-publish.already-published",
|
347
|
+
defaultMessage: "Already Published"
|
348
|
+
}),
|
349
|
+
textColor: "success600",
|
350
|
+
fontWeight: "bold"
|
351
|
+
};
|
352
|
+
} else if (status === "modified") {
|
353
|
+
return {
|
354
|
+
icon: /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
|
355
|
+
text: formatMessage({
|
356
|
+
id: "app.utils.ready-to-publish-changes",
|
357
|
+
defaultMessage: "Ready to publish changes"
|
358
|
+
})
|
359
|
+
};
|
360
|
+
} else {
|
361
|
+
return {
|
362
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
363
|
+
text: formatMessage({
|
364
|
+
id: "app.utils.ready-to-publish",
|
365
|
+
defaultMessage: "Ready to publish"
|
366
|
+
})
|
367
|
+
};
|
368
|
+
}
|
369
|
+
} else {
|
370
|
+
if (status === "draft") {
|
371
|
+
return {
|
372
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
373
|
+
text: formatMessage({
|
374
|
+
id: "content-manager.bulk-unpublish.already-unpublished",
|
375
|
+
defaultMessage: "Already Unpublished"
|
376
|
+
}),
|
377
|
+
textColor: "success600",
|
378
|
+
fontWeight: "bold"
|
379
|
+
};
|
380
|
+
} else {
|
381
|
+
return {
|
382
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
383
|
+
text: formatMessage({
|
384
|
+
id: "app.utils.ready-to-unpublish-changes",
|
385
|
+
defaultMessage: "Ready to unpublish"
|
386
|
+
}),
|
387
|
+
textColor: "success600",
|
388
|
+
fontWeight: "bold"
|
389
|
+
};
|
390
|
+
}
|
391
|
+
}
|
392
|
+
};
|
393
|
+
const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
|
394
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
395
|
+
icon,
|
396
|
+
/* @__PURE__ */ jsx(Typography, { textColor, fontWeight, children: text })
|
397
|
+
] });
|
398
|
+
};
|
399
|
+
const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
400
|
+
const BulkLocaleActionModal = ({
|
401
|
+
headers,
|
402
|
+
rows,
|
403
|
+
localesMetadata,
|
404
|
+
validationErrors = {},
|
405
|
+
action
|
406
|
+
}) => {
|
407
|
+
const { formatMessage } = useIntl();
|
408
|
+
const selectedRows = useTable(
|
409
|
+
"BulkLocaleActionModal",
|
410
|
+
(state) => state.selectedRows
|
411
|
+
);
|
412
|
+
const getFormattedCountMessage = () => {
|
413
|
+
const currentStatusByLocale = rows.reduce((acc, { locale, status }) => {
|
414
|
+
acc[locale] = status;
|
415
|
+
return acc;
|
416
|
+
}, {});
|
417
|
+
const localesWithErrors = Object.keys(validationErrors);
|
418
|
+
const publishedCount = selectedRows.filter(
|
419
|
+
({ locale }) => currentStatusByLocale[locale] === "published"
|
420
|
+
).length;
|
421
|
+
const draftCount = selectedRows.filter(
|
422
|
+
({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
|
423
|
+
).length;
|
424
|
+
const withErrorsCount = localesWithErrors.length;
|
425
|
+
const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
|
426
|
+
const defaultMessage = action === "bulk-publish" ? "<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action." : "<b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} already unpublished. <b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} ready to unpublish.";
|
427
|
+
return formatMessage(
|
428
|
+
{
|
429
|
+
id: messageId,
|
430
|
+
defaultMessage
|
431
|
+
},
|
432
|
+
{
|
433
|
+
withErrorsCount,
|
434
|
+
draftCount,
|
435
|
+
publishedCount,
|
436
|
+
b: BoldChunk
|
437
|
+
}
|
438
|
+
);
|
439
|
+
};
|
440
|
+
return /* @__PURE__ */ jsxs(Modal.Body, { children: [
|
441
|
+
/* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
|
442
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsxs(Table.Content, { children: [
|
443
|
+
/* @__PURE__ */ jsxs(Table.Head, { children: [
|
444
|
+
/* @__PURE__ */ jsx(Table.HeaderCheckboxCell, {}),
|
445
|
+
headers.map((head) => /* @__PURE__ */ jsx(Table.HeaderCell, { ...head }, head.name))
|
446
|
+
] }),
|
447
|
+
/* @__PURE__ */ jsx(Table.Body, { children: rows.map(({ locale, status }, index2) => {
|
448
|
+
const error = validationErrors?.[locale] ?? null;
|
449
|
+
const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
|
450
|
+
return /* @__PURE__ */ jsxs(Table.Row, { children: [
|
451
|
+
/* @__PURE__ */ jsx(Table.CheckboxCell, { id: locale, "aria-label": `Select ${locale}` }),
|
452
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: Array.isArray(localesMetadata) ? localesMetadata.find((localeEntry) => localeEntry.code === locale)?.name : locale }) }),
|
453
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Box, { display: "flex", children: /* @__PURE__ */ jsx(
|
454
|
+
Status,
|
455
|
+
{
|
456
|
+
display: "flex",
|
457
|
+
paddingLeft: "6px",
|
458
|
+
paddingRight: "6px",
|
459
|
+
paddingTop: "2px",
|
460
|
+
paddingBottom: "2px",
|
461
|
+
showBullet: false,
|
462
|
+
size: "S",
|
463
|
+
variant: statusVariant,
|
464
|
+
children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
|
465
|
+
}
|
466
|
+
) }) }),
|
467
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status, action }) }),
|
468
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
469
|
+
IconButton,
|
470
|
+
{
|
471
|
+
tag: Link,
|
472
|
+
to: {
|
473
|
+
search: stringify({ plugins: { i18n: { locale } } })
|
474
|
+
},
|
475
|
+
label: formatMessage(
|
476
|
+
{
|
477
|
+
id: getTranslation("Settings.list.actions.edit"),
|
478
|
+
defaultMessage: "Edit {name} locale"
|
479
|
+
},
|
480
|
+
{
|
481
|
+
name: locale
|
482
|
+
}
|
483
|
+
),
|
484
|
+
variant: "ghost",
|
485
|
+
children: /* @__PURE__ */ jsx(Pencil, {})
|
486
|
+
}
|
487
|
+
) })
|
488
|
+
] }, index2);
|
489
|
+
}) })
|
490
|
+
] }) })
|
491
|
+
] });
|
492
|
+
};
|
269
493
|
const LocalePickerAction = ({
|
270
494
|
document,
|
271
495
|
meta,
|
@@ -277,7 +501,13 @@ const LocalePickerAction = ({
|
|
277
501
|
const [{ query }, setQuery] = useQueryParams();
|
278
502
|
const { hasI18n, canCreate, canRead } = useI18n();
|
279
503
|
const { data: locales = [] } = useGetLocalesQuery();
|
280
|
-
const
|
504
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
505
|
+
const { schema } = unstable_useDocument({
|
506
|
+
model,
|
507
|
+
collectionType,
|
508
|
+
documentId,
|
509
|
+
params: { locale: currentDesiredLocale }
|
510
|
+
});
|
281
511
|
const handleSelect = React.useCallback(
|
282
512
|
(value) => {
|
283
513
|
setQuery({
|
@@ -295,21 +525,20 @@ const LocalePickerAction = ({
|
|
295
525
|
if (!Array.isArray(locales) || !hasI18n) {
|
296
526
|
return;
|
297
527
|
}
|
298
|
-
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
299
528
|
const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
|
300
529
|
const defaultLocale = locales.find((locale) => locale.isDefault);
|
301
530
|
if (!doesLocaleExist && defaultLocale?.code) {
|
302
531
|
handleSelect(defaultLocale.code);
|
303
532
|
}
|
304
|
-
}, [handleSelect, hasI18n, locales,
|
305
|
-
|
306
|
-
return null;
|
307
|
-
}
|
308
|
-
const currentLocale = query.plugins?.i18n?.locale || locales.find((loc) => loc.isDefault)?.code;
|
533
|
+
}, [handleSelect, hasI18n, locales, currentDesiredLocale]);
|
534
|
+
const currentLocale = Array.isArray(locales) ? locales.find((locale) => locale.code === currentDesiredLocale)?.code : void 0;
|
309
535
|
const allCurrentLocales = [
|
310
536
|
{ status: getDocumentStatus(document, meta), locale: currentLocale },
|
311
537
|
...meta?.availableLocales ?? []
|
312
538
|
];
|
539
|
+
if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
|
540
|
+
return null;
|
541
|
+
}
|
313
542
|
return {
|
314
543
|
label: formatMessage({
|
315
544
|
id: getTranslation("Settings.locales.modal.locales.label"),
|
@@ -321,7 +550,7 @@ const LocalePickerAction = ({
|
|
321
550
|
);
|
322
551
|
const status = currentLocaleDoc?.status ?? "draft";
|
323
552
|
const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
|
324
|
-
const statusVariant = status === "draft" ? "
|
553
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
325
554
|
return {
|
326
555
|
disabled: !permissionsToCheck.includes(locale.code),
|
327
556
|
value: locale.code,
|
@@ -337,7 +566,7 @@ const LocalePickerAction = ({
|
|
337
566
|
showBullet: false,
|
338
567
|
size: "S",
|
339
568
|
variant: statusVariant,
|
340
|
-
children: /* @__PURE__ */ jsx(Typography, {
|
569
|
+
children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
|
341
570
|
}
|
342
571
|
) : null
|
343
572
|
};
|
@@ -357,6 +586,95 @@ const getDocumentStatus = (document, meta) => {
|
|
357
586
|
}
|
358
587
|
return docStatus;
|
359
588
|
};
|
589
|
+
const FillFromAnotherLocaleAction = ({
|
590
|
+
documentId,
|
591
|
+
meta,
|
592
|
+
model,
|
593
|
+
collectionType
|
594
|
+
}) => {
|
595
|
+
const { formatMessage } = useIntl();
|
596
|
+
const [{ query }] = useQueryParams();
|
597
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
598
|
+
const [localeSelected, setLocaleSelected] = React.useState(null);
|
599
|
+
const setValues = useForm("FillFromAnotherLocale", (state) => state.setValues);
|
600
|
+
const { getDocument } = unstable_useDocumentActions();
|
601
|
+
const { schema, components } = unstable_useDocument({
|
602
|
+
model,
|
603
|
+
documentId,
|
604
|
+
collectionType,
|
605
|
+
params: { locale: currentDesiredLocale }
|
606
|
+
});
|
607
|
+
const { data: locales = [] } = useGetLocalesQuery();
|
608
|
+
const availableLocales = Array.isArray(locales) ? locales.filter((locale) => meta?.availableLocales.some((l) => l.locale === locale.code)) : [];
|
609
|
+
const fillFromLocale = (onClose) => async () => {
|
610
|
+
const response = await getDocument({
|
611
|
+
collectionType,
|
612
|
+
model,
|
613
|
+
documentId,
|
614
|
+
params: { locale: localeSelected }
|
615
|
+
});
|
616
|
+
if (!response || !schema) {
|
617
|
+
return;
|
618
|
+
}
|
619
|
+
const { data } = response;
|
620
|
+
const cleanedData = cleanData(data, schema, components);
|
621
|
+
setValues(cleanedData);
|
622
|
+
onClose();
|
623
|
+
};
|
624
|
+
return {
|
625
|
+
type: "icon",
|
626
|
+
icon: /* @__PURE__ */ jsx(Download, {}),
|
627
|
+
disabled: availableLocales.length === 0,
|
628
|
+
label: formatMessage({
|
629
|
+
id: getTranslation("CMEditViewCopyLocale.copy-text"),
|
630
|
+
defaultMessage: "Fill in from another locale"
|
631
|
+
}),
|
632
|
+
dialog: {
|
633
|
+
type: "dialog",
|
634
|
+
title: formatMessage({
|
635
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.title"),
|
636
|
+
defaultMessage: "Confirmation"
|
637
|
+
}),
|
638
|
+
content: ({ onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
639
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
|
640
|
+
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
641
|
+
/* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
|
642
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.body"),
|
643
|
+
defaultMessage: "Your current content will be erased and filled by the content of the selected locale:"
|
644
|
+
}) }),
|
645
|
+
/* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
|
646
|
+
/* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
|
647
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.field.label"),
|
648
|
+
defaultMessage: "Locale"
|
649
|
+
}) }),
|
650
|
+
/* @__PURE__ */ jsx(
|
651
|
+
SingleSelect,
|
652
|
+
{
|
653
|
+
value: localeSelected,
|
654
|
+
placeholder: formatMessage({
|
655
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.field.placeholder"),
|
656
|
+
defaultMessage: "Select one locale..."
|
657
|
+
}),
|
658
|
+
onChange: (value) => setLocaleSelected(value),
|
659
|
+
children: availableLocales.map((locale) => /* @__PURE__ */ jsx(SingleSelectOption, { value: locale.code, children: locale.name }, locale.code))
|
660
|
+
}
|
661
|
+
)
|
662
|
+
] })
|
663
|
+
] }) }),
|
664
|
+
/* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, width: "100%", children: [
|
665
|
+
/* @__PURE__ */ jsx(Button, { flex: "auto", variant: "tertiary", onClick: onClose, children: formatMessage({
|
666
|
+
id: getTranslation("CMEditViewCopyLocale.cancel-text"),
|
667
|
+
defaultMessage: "No, cancel"
|
668
|
+
}) }),
|
669
|
+
/* @__PURE__ */ jsx(Button, { flex: "auto", variant: "success", onClick: fillFromLocale(onClose), children: formatMessage({
|
670
|
+
id: getTranslation("CMEditViewCopyLocale.submit-text"),
|
671
|
+
defaultMessage: "Yes, fill in"
|
672
|
+
}) })
|
673
|
+
] }) })
|
674
|
+
] })
|
675
|
+
}
|
676
|
+
};
|
677
|
+
};
|
360
678
|
const DeleteLocaleAction = ({
|
361
679
|
document,
|
362
680
|
documentId,
|
@@ -388,7 +706,7 @@ const DeleteLocaleAction = ({
|
|
388
706
|
}),
|
389
707
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
390
708
|
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
391
|
-
/* @__PURE__ */ jsx(Typography, {
|
709
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
392
710
|
id: getTranslation("actions.delete.dialog.body"),
|
393
711
|
defaultMessage: "Are you sure?"
|
394
712
|
}) })
|
@@ -420,6 +738,262 @@ const DeleteLocaleAction = ({
|
|
420
738
|
}
|
421
739
|
};
|
422
740
|
};
|
741
|
+
const BulkLocaleAction = ({
|
742
|
+
document: baseDocument,
|
743
|
+
documentId,
|
744
|
+
model,
|
745
|
+
collectionType,
|
746
|
+
action
|
747
|
+
}) => {
|
748
|
+
const baseLocale = baseDocument?.locale ?? null;
|
749
|
+
const [{ query }] = useQueryParams();
|
750
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
751
|
+
const isOnPublishedTab = query.status === "published";
|
752
|
+
const { formatMessage } = useIntl();
|
753
|
+
const { hasI18n, canPublish } = useI18n();
|
754
|
+
const { toggleNotification } = useNotification();
|
755
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
756
|
+
const [selectedRows, setSelectedRows] = React.useState([]);
|
757
|
+
const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
|
758
|
+
const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
|
759
|
+
const {
|
760
|
+
document,
|
761
|
+
meta: documentMeta,
|
762
|
+
schema,
|
763
|
+
validate
|
764
|
+
} = unstable_useDocument(
|
765
|
+
{
|
766
|
+
model,
|
767
|
+
collectionType,
|
768
|
+
documentId,
|
769
|
+
params: {
|
770
|
+
locale: baseLocale
|
771
|
+
}
|
772
|
+
},
|
773
|
+
{
|
774
|
+
skip: !hasI18n || !baseLocale
|
775
|
+
}
|
776
|
+
);
|
777
|
+
const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : skipToken);
|
778
|
+
const headers = [
|
779
|
+
{
|
780
|
+
label: formatMessage({
|
781
|
+
id: "global.name",
|
782
|
+
defaultMessage: "Name"
|
783
|
+
}),
|
784
|
+
name: "name"
|
785
|
+
},
|
786
|
+
{
|
787
|
+
label: formatMessage({
|
788
|
+
id: getTranslation("CMEditViewBulkLocale.status"),
|
789
|
+
defaultMessage: "Status"
|
790
|
+
}),
|
791
|
+
name: "status"
|
792
|
+
},
|
793
|
+
{
|
794
|
+
label: formatMessage({
|
795
|
+
id: getTranslation("CMEditViewBulkLocale.publication-status"),
|
796
|
+
defaultMessage: "Publication Status"
|
797
|
+
}),
|
798
|
+
name: "publication-status"
|
799
|
+
}
|
800
|
+
];
|
801
|
+
const [rows, validationErrors] = React.useMemo(() => {
|
802
|
+
if (!document || !documentMeta?.availableLocales) {
|
803
|
+
return [[], {}];
|
804
|
+
}
|
805
|
+
const rowsFromMeta = documentMeta?.availableLocales.map((doc) => {
|
806
|
+
const { locale, status } = doc;
|
807
|
+
return { locale, status };
|
808
|
+
});
|
809
|
+
rowsFromMeta.unshift({
|
810
|
+
locale: document.locale,
|
811
|
+
status: document.status
|
812
|
+
});
|
813
|
+
const allDocuments = [document, ...documentMeta?.availableLocales ?? []];
|
814
|
+
const errors = allDocuments.reduce((errs, document2) => {
|
815
|
+
if (!document2) {
|
816
|
+
return errs;
|
817
|
+
}
|
818
|
+
const validation = validate(document2);
|
819
|
+
if (validation !== null) {
|
820
|
+
errs[document2.locale] = validation;
|
821
|
+
}
|
822
|
+
return errs;
|
823
|
+
}, {});
|
824
|
+
return [rowsFromMeta, errors];
|
825
|
+
}, [document, documentMeta?.availableLocales, validate]);
|
826
|
+
const isBulkPublish = action === "bulk-publish";
|
827
|
+
const localesForAction = selectedRows.reduce((acc, selectedRow) => {
|
828
|
+
const isValidLocale = (
|
829
|
+
// Validation errors are irrelevant if we are trying to unpublish
|
830
|
+
!isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
|
831
|
+
);
|
832
|
+
const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
|
833
|
+
if (shouldAddLocale) {
|
834
|
+
acc.push(selectedRow.locale);
|
835
|
+
}
|
836
|
+
return acc;
|
837
|
+
}, []);
|
838
|
+
const enableDraftRelationsCount = false;
|
839
|
+
const {
|
840
|
+
data: draftRelationsCount = 0,
|
841
|
+
isLoading: isDraftRelationsLoading,
|
842
|
+
error: isDraftRelationsError
|
843
|
+
} = useGetManyDraftRelationCountQuery(
|
844
|
+
{
|
845
|
+
model,
|
846
|
+
documentIds: [documentId],
|
847
|
+
locale: localesForAction
|
848
|
+
},
|
849
|
+
{
|
850
|
+
skip: !enableDraftRelationsCount
|
851
|
+
}
|
852
|
+
);
|
853
|
+
React.useEffect(() => {
|
854
|
+
if (isDraftRelationsError) {
|
855
|
+
toggleNotification({
|
856
|
+
type: "danger",
|
857
|
+
message: formatAPIError(isDraftRelationsError)
|
858
|
+
});
|
859
|
+
}
|
860
|
+
}, [isDraftRelationsError, toggleNotification, formatAPIError]);
|
861
|
+
if (!schema?.options?.draftAndPublish) {
|
862
|
+
return null;
|
863
|
+
}
|
864
|
+
if (!hasI18n) {
|
865
|
+
return null;
|
866
|
+
}
|
867
|
+
if (!documentId) {
|
868
|
+
return null;
|
869
|
+
}
|
870
|
+
const publish = async () => {
|
871
|
+
await publishManyAction({
|
872
|
+
model,
|
873
|
+
documentIds: [documentId],
|
874
|
+
params: {
|
875
|
+
...params,
|
876
|
+
locale: localesForAction
|
877
|
+
}
|
878
|
+
});
|
879
|
+
setSelectedRows([]);
|
880
|
+
};
|
881
|
+
const unpublish = async () => {
|
882
|
+
await unpublishManyAction({
|
883
|
+
model,
|
884
|
+
documentIds: [documentId],
|
885
|
+
params: {
|
886
|
+
...params,
|
887
|
+
locale: localesForAction
|
888
|
+
}
|
889
|
+
});
|
890
|
+
setSelectedRows([]);
|
891
|
+
};
|
892
|
+
const handleAction = async () => {
|
893
|
+
if (draftRelationsCount > 0) {
|
894
|
+
setIsDraftRelationConfirmationOpen(true);
|
895
|
+
} else if (isBulkPublish) {
|
896
|
+
await publish();
|
897
|
+
} else {
|
898
|
+
await unpublish();
|
899
|
+
}
|
900
|
+
};
|
901
|
+
if (isDraftRelationConfirmationOpen) {
|
902
|
+
return {
|
903
|
+
label: formatMessage({
|
904
|
+
id: "app.components.ConfirmDialog.title",
|
905
|
+
defaultMessage: "Confirmation"
|
906
|
+
}),
|
907
|
+
variant: "danger",
|
908
|
+
dialog: {
|
909
|
+
onCancel: () => {
|
910
|
+
setIsDraftRelationConfirmationOpen(false);
|
911
|
+
},
|
912
|
+
onConfirm: async () => {
|
913
|
+
await publish();
|
914
|
+
setIsDraftRelationConfirmationOpen(false);
|
915
|
+
},
|
916
|
+
type: "dialog",
|
917
|
+
title: formatMessage({
|
918
|
+
id: getTranslation("actions.publish.dialog.title"),
|
919
|
+
defaultMessage: "Confirmation"
|
920
|
+
}),
|
921
|
+
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 2, children: [
|
922
|
+
/* @__PURE__ */ jsx(WarningCircle, { width: "2.4rem", height: "2.4rem", fill: "danger600" }),
|
923
|
+
/* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
|
924
|
+
id: getTranslation("CMEditViewBulkLocale.draft-relation-warning"),
|
925
|
+
defaultMessage: "Some locales are related to draft entries. Publishing them could leave broken links in your app."
|
926
|
+
}) }),
|
927
|
+
/* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
|
928
|
+
id: getTranslation("CMEditViewBulkLocale.continue-confirmation"),
|
929
|
+
defaultMessage: "Are you sure you want to continue?"
|
930
|
+
}) })
|
931
|
+
] })
|
932
|
+
}
|
933
|
+
};
|
934
|
+
}
|
935
|
+
const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
|
936
|
+
return {
|
937
|
+
label: formatMessage({
|
938
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
939
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
940
|
+
}),
|
941
|
+
variant: isBulkPublish ? "secondary" : "danger",
|
942
|
+
icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
|
943
|
+
disabled: isOnPublishedTab || canPublish.length === 0,
|
944
|
+
position: ["panel"],
|
945
|
+
dialog: {
|
946
|
+
type: "modal",
|
947
|
+
title: formatMessage({
|
948
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
949
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
950
|
+
}),
|
951
|
+
content: () => {
|
952
|
+
return /* @__PURE__ */ jsx(
|
953
|
+
Table.Root,
|
954
|
+
{
|
955
|
+
headers,
|
956
|
+
rows: rows.map((row) => ({
|
957
|
+
...row,
|
958
|
+
id: row.locale
|
959
|
+
})),
|
960
|
+
selectedRows,
|
961
|
+
onSelectedRowsChange: (tableSelectedRows) => setSelectedRows(tableSelectedRows),
|
962
|
+
children: /* @__PURE__ */ jsx(
|
963
|
+
BulkLocaleActionModal,
|
964
|
+
{
|
965
|
+
validationErrors,
|
966
|
+
headers,
|
967
|
+
rows,
|
968
|
+
localesMetadata,
|
969
|
+
action: action ?? "bulk-publish"
|
970
|
+
}
|
971
|
+
)
|
972
|
+
}
|
973
|
+
);
|
974
|
+
},
|
975
|
+
footer: () => /* @__PURE__ */ jsx(Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
|
976
|
+
Button,
|
977
|
+
{
|
978
|
+
loading: isDraftRelationsLoading,
|
979
|
+
disabled: !hasPermission || localesForAction.length === 0,
|
980
|
+
variant: "default",
|
981
|
+
onClick: handleAction,
|
982
|
+
children: formatMessage({
|
983
|
+
id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
|
984
|
+
defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
|
985
|
+
})
|
986
|
+
}
|
987
|
+
) })
|
988
|
+
}
|
989
|
+
};
|
990
|
+
};
|
991
|
+
const BulkLocalePublishAction = (props) => {
|
992
|
+
return BulkLocaleAction({ action: "bulk-publish", ...props });
|
993
|
+
};
|
994
|
+
const BulkLocaleUnpublishAction = (props) => {
|
995
|
+
return BulkLocaleAction({ action: "bulk-unpublish", ...props });
|
996
|
+
};
|
423
997
|
const StyledTrash = styled(Trash)`
|
424
998
|
path {
|
425
999
|
fill: currentColor;
|
@@ -476,13 +1050,6 @@ const UnpublishModalAdditionalInfo = () => {
|
|
476
1050
|
}
|
477
1051
|
) });
|
478
1052
|
};
|
479
|
-
const Initializer = ({ setPlugin }) => {
|
480
|
-
const setPluginRef = React.useRef(setPlugin);
|
481
|
-
React.useEffect(() => {
|
482
|
-
setPluginRef.current(pluginId);
|
483
|
-
}, []);
|
484
|
-
return null;
|
485
|
-
};
|
486
1053
|
const LocalePicker = () => {
|
487
1054
|
const { formatMessage } = useIntl();
|
488
1055
|
const [{ query }, setQuery] = useQueryParams();
|
@@ -542,7 +1109,7 @@ const PERMISSIONS = {
|
|
542
1109
|
read: [{ action: "plugin::i18n.locale.read", subject: null }]
|
543
1110
|
};
|
544
1111
|
const mutateEditViewHook = ({ layout }) => {
|
545
|
-
if ("i18n" in layout.options
|
1112
|
+
if (!("i18n" in layout.options) || typeof layout.options.i18n === "object" && layout.options.i18n !== null && "localized" in layout.options.i18n && !layout.options.i18n.localized) {
|
546
1113
|
return { layout };
|
547
1114
|
}
|
548
1115
|
const components = Object.entries(layout.components).reduce(
|
@@ -587,8 +1154,8 @@ const doesFieldHaveI18nPluginOpt = (pluginOpts) => {
|
|
587
1154
|
};
|
588
1155
|
const LabelAction = ({ title, icon }) => {
|
589
1156
|
const { formatMessage } = useIntl();
|
590
|
-
return /* @__PURE__ */ jsxs(Span, {
|
591
|
-
/* @__PURE__ */ jsx(VisuallyHidden, {
|
1157
|
+
return /* @__PURE__ */ jsxs(Span, { tag: "span", children: [
|
1158
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: formatMessage(title) }),
|
592
1159
|
React.cloneElement(icon, {
|
593
1160
|
"aria-hidden": true,
|
594
1161
|
focusable: false
|
@@ -623,13 +1190,7 @@ const LocaleListCell = ({
|
|
623
1190
|
}
|
624
1191
|
});
|
625
1192
|
const { locale: language } = useIntl();
|
626
|
-
const [visible, setVisible] = React.useState(false);
|
627
|
-
const buttonRef = React.useRef(null);
|
628
1193
|
const { data: locales = [] } = useGetLocalesQuery();
|
629
|
-
const handleTogglePopover = (e) => {
|
630
|
-
e.stopPropagation();
|
631
|
-
setVisible((prev) => !prev);
|
632
|
-
};
|
633
1194
|
const formatter = useCollator(language, {
|
634
1195
|
sensitivity: "base"
|
635
1196
|
});
|
@@ -651,64 +1212,14 @@ const LocaleListCell = ({
|
|
651
1212
|
}
|
652
1213
|
return locale.name;
|
653
1214
|
}).toSorted((a, b) => formatter.compare(a, b));
|
654
|
-
return /* @__PURE__ */ jsxs(
|
655
|
-
/* @__PURE__ */ jsxs(
|
656
|
-
|
657
|
-
{
|
658
|
-
|
659
|
-
|
660
|
-
justifyContent: "center",
|
661
|
-
height: "3.2rem",
|
662
|
-
width: "3.2rem",
|
663
|
-
children: [
|
664
|
-
/* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, children: localesForDocument.join(", ") }),
|
665
|
-
/* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, {}) })
|
666
|
-
]
|
667
|
-
}
|
668
|
-
),
|
669
|
-
visible && /* @__PURE__ */ jsx(
|
670
|
-
Popover,
|
671
|
-
{
|
672
|
-
onDismiss: () => setVisible(false),
|
673
|
-
source: buttonRef,
|
674
|
-
spacing: 16,
|
675
|
-
centered: true,
|
676
|
-
children: /* @__PURE__ */ jsx("ul", { children: localesForDocument.map((name) => /* @__PURE__ */ jsx(Box, { padding: 3, as: "li", children: /* @__PURE__ */ jsx(Typography, { children: name }) }, name)) })
|
677
|
-
}
|
678
|
-
)
|
1215
|
+
return /* @__PURE__ */ jsxs(Popover.Root, { children: [
|
1216
|
+
/* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(Button, { variant: "ghost", type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs(Flex, { minWidth: "100%", alignItems: "center", justifyContent: "center", fontWeight: "regular", children: [
|
1217
|
+
/* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, marginRight: 2, children: localesForDocument.join(", ") }),
|
1218
|
+
/* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, { width: "1.2rem", height: "1.2rem" }) })
|
1219
|
+
] }) }) }),
|
1220
|
+
/* @__PURE__ */ jsx(Popover.Content, { sideOffset: 16, children: /* @__PURE__ */ jsx("ul", { children: localesForDocument.map((name) => /* @__PURE__ */ jsx(Box, { padding: 3, tag: "li", children: /* @__PURE__ */ jsx(Typography, { children: name }) }, name)) }) })
|
679
1221
|
] });
|
680
1222
|
};
|
681
|
-
const Button = styled.button`
|
682
|
-
width: 100%;
|
683
|
-
|
684
|
-
svg {
|
685
|
-
> g,
|
686
|
-
path {
|
687
|
-
fill: ${({ theme }) => theme.colors.neutral500};
|
688
|
-
}
|
689
|
-
}
|
690
|
-
&:hover {
|
691
|
-
svg {
|
692
|
-
> g,
|
693
|
-
path {
|
694
|
-
fill: ${({ theme }) => theme.colors.neutral600};
|
695
|
-
}
|
696
|
-
}
|
697
|
-
}
|
698
|
-
&:active {
|
699
|
-
svg {
|
700
|
-
> g,
|
701
|
-
path {
|
702
|
-
fill: ${({ theme }) => theme.colors.neutral400};
|
703
|
-
}
|
704
|
-
}
|
705
|
-
}
|
706
|
-
`;
|
707
|
-
const ActionWrapper = styled(Flex)`
|
708
|
-
svg {
|
709
|
-
height: 0.4rem;
|
710
|
-
}
|
711
|
-
`;
|
712
1223
|
const addColumnToTableHook = ({ displayedHeaders, layout }) => {
|
713
1224
|
const { options } = layout;
|
714
1225
|
const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
|
@@ -737,18 +1248,11 @@ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
|
|
737
1248
|
const addLocaleToReleasesHook = ({ displayedHeaders = [] }) => {
|
738
1249
|
return {
|
739
1250
|
displayedHeaders: [
|
740
|
-
|
741
|
-
// ...displayedHeaders,
|
1251
|
+
...displayedHeaders,
|
742
1252
|
{
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
label: {
|
747
|
-
id: "content-releases.page.ReleaseDetails.table.header.label.locale",
|
748
|
-
defaultMessage: "locale"
|
749
|
-
},
|
750
|
-
searchable: false,
|
751
|
-
sortable: false
|
1253
|
+
label: {
|
1254
|
+
id: "content-releases.page.ReleaseDetails.table.header.label.locale",
|
1255
|
+
defaultMessage: "locale"
|
752
1256
|
},
|
753
1257
|
name: "locale"
|
754
1258
|
}
|
@@ -896,8 +1400,6 @@ const index = {
|
|
896
1400
|
app.addRBACMiddleware([localeMiddleware]);
|
897
1401
|
app.registerPlugin({
|
898
1402
|
id: pluginId,
|
899
|
-
initializer: Initializer,
|
900
|
-
isReady: false,
|
901
1403
|
name: pluginId
|
902
1404
|
});
|
903
1405
|
},
|
@@ -915,16 +1417,21 @@ const index = {
|
|
915
1417
|
},
|
916
1418
|
id: "internationalization",
|
917
1419
|
to: "internationalization",
|
918
|
-
Component: () => import("./SettingsPage-
|
1420
|
+
Component: () => import("./SettingsPage-BjxjwEOb.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
|
919
1421
|
permissions: PERMISSIONS.accessMain
|
920
1422
|
});
|
921
1423
|
const contentManager = app.getPlugin("content-manager");
|
922
|
-
contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
|
1424
|
+
contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
|
923
1425
|
contentManager.apis.addDocumentAction((actions) => {
|
924
1426
|
const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
|
925
1427
|
actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
|
926
1428
|
return actions;
|
927
1429
|
});
|
1430
|
+
contentManager.apis.addDocumentAction((actions) => {
|
1431
|
+
actions.splice(2, 0, BulkLocalePublishAction);
|
1432
|
+
actions.splice(5, 0, BulkLocaleUnpublishAction);
|
1433
|
+
return actions;
|
1434
|
+
});
|
928
1435
|
contentManager.injectComponent("listView", "actions", {
|
929
1436
|
name: "i18n-locale-filter",
|
930
1437
|
Component: LocalePicker
|
@@ -1028,7 +1535,7 @@ const index = {
|
|
1028
1535
|
async registerTrads({ locales }) {
|
1029
1536
|
const importedTrads = await Promise.all(
|
1030
1537
|
locales.map((locale) => {
|
1031
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-9eCAqqrB.mjs"), "./translations/dk.json": () => import("./dk-2qBjxt-P.mjs"), "./translations/en.json": () => import("./en-
|
1538
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-9eCAqqrB.mjs"), "./translations/dk.json": () => import("./dk-2qBjxt-P.mjs"), "./translations/en.json": () => import("./en-2xztdZE1.mjs"), "./translations/es.json": () => import("./es-DlmMVaBG.mjs"), "./translations/fr.json": () => import("./fr-3S6ke71d.mjs"), "./translations/ko.json": () => import("./ko-qTjQ8IMw.mjs"), "./translations/pl.json": () => import("./pl-B67TSHqT.mjs"), "./translations/ru.json": () => import("./ru-hagMa57T.mjs"), "./translations/tr.json": () => import("./tr-Dw_jmkG-.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-Dyc-aR-h.mjs"), "./translations/zh.json": () => import("./zh-57YM4amO.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
|
1032
1539
|
return {
|
1033
1540
|
data: prefixPluginTranslations(data, pluginId),
|
1034
1541
|
locale
|
@@ -1047,12 +1554,11 @@ const index = {
|
|
1047
1554
|
export {
|
1048
1555
|
PERMISSIONS as P,
|
1049
1556
|
useGetDefaultLocalesQuery as a,
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
index as e,
|
1557
|
+
useDeleteLocaleMutation as b,
|
1558
|
+
useUpdateLocaleMutation as c,
|
1559
|
+
useGetLocalesQuery as d,
|
1054
1560
|
getTranslation as g,
|
1055
|
-
|
1561
|
+
index as i,
|
1056
1562
|
useCreateLocaleMutation as u
|
1057
1563
|
};
|
1058
|
-
//# sourceMappingURL=index-
|
1564
|
+
//# sourceMappingURL=index-D-qx3tz4.mjs.map
|