@strapi/content-releases 0.0.0-experimental.check-license → 0.0.0-experimental.d10cfc2d4947d3dcbf166b29dc168cb4a7123772

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.
Files changed (35) hide show
  1. package/LICENSE +17 -1
  2. package/dist/_chunks/App-dLXY5ei3.js +1353 -0
  3. package/dist/_chunks/App-dLXY5ei3.js.map +1 -0
  4. package/dist/_chunks/App-jrh58sXY.mjs +1330 -0
  5. package/dist/_chunks/App-jrh58sXY.mjs.map +1 -0
  6. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs +51 -0
  7. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
  8. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js +51 -0
  9. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
  10. package/dist/_chunks/en-HrREghh3.js +86 -0
  11. package/dist/_chunks/en-HrREghh3.js.map +1 -0
  12. package/dist/_chunks/en-ltT1TlKQ.mjs +86 -0
  13. package/dist/_chunks/en-ltT1TlKQ.mjs.map +1 -0
  14. package/dist/_chunks/index-CVO0Rqdm.js +1336 -0
  15. package/dist/_chunks/index-CVO0Rqdm.js.map +1 -0
  16. package/dist/_chunks/index-PiOGBETy.mjs +1315 -0
  17. package/dist/_chunks/index-PiOGBETy.mjs.map +1 -0
  18. package/dist/admin/index.js +17 -35
  19. package/dist/admin/index.js.map +1 -1
  20. package/dist/admin/index.mjs +17 -35
  21. package/dist/admin/index.mjs.map +1 -1
  22. package/dist/server/index.js +1785 -5
  23. package/dist/server/index.js.map +1 -1
  24. package/dist/server/index.mjs +1762 -5
  25. package/dist/server/index.mjs.map +1 -1
  26. package/package.json +37 -20
  27. package/dist/_chunks/en-21947221.js +0 -5
  28. package/dist/_chunks/en-21947221.js.map +0 -1
  29. package/dist/_chunks/en-92157b33.mjs +0 -5
  30. package/dist/_chunks/en-92157b33.mjs.map +0 -1
  31. package/dist/admin/src/index.d.ts +0 -15
  32. package/dist/admin/src/tests/index.test.d.ts +0 -0
  33. package/dist/server/src/__tests__/index.test.d.ts +0 -2
  34. package/dist/server/src/index.d.ts +0 -4
  35. package/dist/server/src/register.d.ts +0 -1
@@ -0,0 +1,1336 @@
1
+ "use strict";
2
+ const helperPlugin = require("@strapi/helper-plugin");
3
+ const icons = require("@strapi/icons");
4
+ const jsxRuntime = require("react/jsx-runtime");
5
+ const React = require("react");
6
+ const query = require("@reduxjs/toolkit/query");
7
+ const designSystem = require("@strapi/design-system");
8
+ const v2 = require("@strapi/design-system/v2");
9
+ const axios = require("axios");
10
+ const formik = require("formik");
11
+ const reactIntl = require("react-intl");
12
+ const reactRouterDom = require("react-router-dom");
13
+ const yup = require("yup");
14
+ const react = require("@reduxjs/toolkit/query/react");
15
+ const styled = require("styled-components");
16
+ const reactRedux = require("react-redux");
17
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
18
+ function _interopNamespace(e) {
19
+ if (e && e.__esModule)
20
+ return e;
21
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
22
+ if (e) {
23
+ for (const k in e) {
24
+ if (k !== "default") {
25
+ const d = Object.getOwnPropertyDescriptor(e, k);
26
+ Object.defineProperty(n, k, d.get ? d : {
27
+ enumerable: true,
28
+ get: () => e[k]
29
+ });
30
+ }
31
+ }
32
+ }
33
+ n.default = e;
34
+ return Object.freeze(n);
35
+ }
36
+ const React__namespace = /* @__PURE__ */ _interopNamespace(React);
37
+ const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
38
+ const styled__default = /* @__PURE__ */ _interopDefault(styled);
39
+ const __variableDynamicImportRuntimeHelper = (glob, path) => {
40
+ const v = glob[path];
41
+ if (v) {
42
+ return typeof v === "function" ? v() : Promise.resolve(v);
43
+ }
44
+ return new Promise((_, reject) => {
45
+ (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(reject.bind(null, new Error("Unknown variable dynamic import: " + path)));
46
+ });
47
+ };
48
+ const PERMISSIONS = {
49
+ main: [
50
+ {
51
+ action: "plugin::content-releases.read",
52
+ subject: null,
53
+ id: "",
54
+ actionParameters: {},
55
+ properties: {},
56
+ conditions: []
57
+ }
58
+ ],
59
+ create: [
60
+ {
61
+ action: "plugin::content-releases.create",
62
+ subject: null,
63
+ id: "",
64
+ actionParameters: {},
65
+ properties: {},
66
+ conditions: []
67
+ }
68
+ ],
69
+ update: [
70
+ {
71
+ action: "plugin::content-releases.update",
72
+ subject: null,
73
+ id: "",
74
+ actionParameters: {},
75
+ properties: {},
76
+ conditions: []
77
+ }
78
+ ],
79
+ delete: [
80
+ {
81
+ action: "plugin::content-releases.delete",
82
+ subject: null,
83
+ id: "",
84
+ actionParameters: {},
85
+ properties: {},
86
+ conditions: []
87
+ }
88
+ ],
89
+ createAction: [
90
+ {
91
+ action: "plugin::content-releases.create-action",
92
+ subject: null,
93
+ id: "",
94
+ actionParameters: {},
95
+ properties: {},
96
+ conditions: []
97
+ }
98
+ ],
99
+ deleteAction: [
100
+ {
101
+ action: "plugin::content-releases.delete-action",
102
+ subject: null,
103
+ id: "",
104
+ actionParameters: {},
105
+ properties: {},
106
+ conditions: []
107
+ }
108
+ ],
109
+ publish: [
110
+ {
111
+ action: "plugin::content-releases.publish",
112
+ subject: null,
113
+ id: "",
114
+ actionParameters: {},
115
+ properties: {},
116
+ conditions: []
117
+ }
118
+ ]
119
+ };
120
+ const pluginId = "content-releases";
121
+ const axiosBaseQuery = async ({
122
+ url,
123
+ method,
124
+ data,
125
+ config
126
+ }) => {
127
+ try {
128
+ const { get, post, del, put } = helperPlugin.getFetchClient();
129
+ if (method === "POST") {
130
+ const result2 = await post(url, data, config);
131
+ return { data: result2.data };
132
+ }
133
+ if (method === "DELETE") {
134
+ const result2 = await del(url, config);
135
+ return { data: result2.data };
136
+ }
137
+ if (method === "PUT") {
138
+ const result2 = await put(url, data, config);
139
+ return { data: result2.data };
140
+ }
141
+ const result = await get(url, config);
142
+ return { data: result.data };
143
+ } catch (error) {
144
+ const err = error;
145
+ return {
146
+ error: {
147
+ status: err.response?.status,
148
+ code: err.code,
149
+ response: {
150
+ data: err.response?.data
151
+ }
152
+ }
153
+ };
154
+ }
155
+ };
156
+ const isAxiosError = (err) => {
157
+ return typeof err === "object" && err !== null && "response" in err && typeof err.response === "object" && err.response !== null && "data" in err.response;
158
+ };
159
+ const releaseApi = react.createApi({
160
+ reducerPath: pluginId,
161
+ baseQuery: axiosBaseQuery,
162
+ tagTypes: ["Release", "ReleaseAction", "EntriesInRelease"],
163
+ endpoints: (build) => {
164
+ return {
165
+ getReleasesForEntry: build.query({
166
+ query(params) {
167
+ return {
168
+ url: "/content-releases",
169
+ method: "GET",
170
+ config: {
171
+ params
172
+ }
173
+ };
174
+ },
175
+ providesTags: (result) => result ? [
176
+ ...result.data.map(({ id }) => ({ type: "Release", id })),
177
+ { type: "Release", id: "LIST" }
178
+ ] : []
179
+ }),
180
+ getReleases: build.query({
181
+ query({ page, pageSize, filters } = {
182
+ page: 1,
183
+ pageSize: 16,
184
+ filters: {
185
+ releasedAt: {
186
+ $notNull: false
187
+ }
188
+ }
189
+ }) {
190
+ return {
191
+ url: "/content-releases",
192
+ method: "GET",
193
+ config: {
194
+ params: {
195
+ page: page || 1,
196
+ pageSize: pageSize || 16,
197
+ filters: filters || {
198
+ releasedAt: {
199
+ $notNull: false
200
+ }
201
+ }
202
+ }
203
+ }
204
+ };
205
+ },
206
+ transformResponse(response, meta, arg) {
207
+ const releasedAtValue = arg?.filters?.releasedAt?.$notNull;
208
+ const isActiveDoneTab = releasedAtValue === "true";
209
+ const newResponse = {
210
+ ...response,
211
+ meta: {
212
+ ...response.meta,
213
+ activeTab: isActiveDoneTab ? "done" : "pending"
214
+ }
215
+ };
216
+ return newResponse;
217
+ },
218
+ providesTags: (result) => result ? [
219
+ ...result.data.map(({ id }) => ({ type: "Release", id })),
220
+ { type: "Release", id: "LIST" }
221
+ ] : [{ type: "Release", id: "LIST" }]
222
+ }),
223
+ getRelease: build.query({
224
+ query({ id }) {
225
+ return {
226
+ url: `/content-releases/${id}`,
227
+ method: "GET"
228
+ };
229
+ },
230
+ providesTags: (result, error, arg) => [{ type: "Release", id: arg.id }]
231
+ }),
232
+ getReleaseActions: build.query({
233
+ query({ releaseId, ...params }) {
234
+ return {
235
+ url: `/content-releases/${releaseId}/actions`,
236
+ method: "GET",
237
+ config: {
238
+ params
239
+ }
240
+ };
241
+ },
242
+ providesTags: [{ type: "ReleaseAction", id: "LIST" }]
243
+ }),
244
+ createRelease: build.mutation({
245
+ query(data) {
246
+ return {
247
+ url: "/content-releases",
248
+ method: "POST",
249
+ data
250
+ };
251
+ },
252
+ invalidatesTags: [{ type: "Release", id: "LIST" }]
253
+ }),
254
+ updateRelease: build.mutation({
255
+ query({ id, ...data }) {
256
+ return {
257
+ url: `/content-releases/${id}`,
258
+ method: "PUT",
259
+ data
260
+ };
261
+ },
262
+ invalidatesTags: (result, error, arg) => [{ type: "Release", id: arg.id }]
263
+ }),
264
+ createReleaseAction: build.mutation({
265
+ query({ body, params }) {
266
+ return {
267
+ url: `/content-releases/${params.releaseId}/actions`,
268
+ method: "POST",
269
+ data: body
270
+ };
271
+ },
272
+ invalidatesTags: [
273
+ { type: "Release", id: "LIST" },
274
+ { type: "ReleaseAction", id: "LIST" }
275
+ ]
276
+ }),
277
+ createManyReleaseActions: build.mutation({
278
+ query({ body, params }) {
279
+ return {
280
+ url: `/content-releases/${params.releaseId}/actions/bulk`,
281
+ method: "POST",
282
+ data: body
283
+ };
284
+ },
285
+ invalidatesTags: [
286
+ { type: "Release", id: "LIST" },
287
+ { type: "ReleaseAction", id: "LIST" },
288
+ { type: "EntriesInRelease" }
289
+ ]
290
+ }),
291
+ updateReleaseAction: build.mutation({
292
+ query({ body, params }) {
293
+ return {
294
+ url: `/content-releases/${params.releaseId}/actions/${params.actionId}`,
295
+ method: "PUT",
296
+ data: body
297
+ };
298
+ },
299
+ invalidatesTags: () => [{ type: "ReleaseAction", id: "LIST" }],
300
+ async onQueryStarted({ body, params, query: query2, actionPath }, { dispatch, queryFulfilled }) {
301
+ const paramsWithoutActionId = {
302
+ releaseId: params.releaseId,
303
+ ...query2
304
+ };
305
+ const patchResult = dispatch(
306
+ releaseApi.util.updateQueryData("getReleaseActions", paramsWithoutActionId, (draft) => {
307
+ const [key, index] = actionPath;
308
+ const action = draft.data[key][index];
309
+ if (action) {
310
+ action.type = body.type;
311
+ }
312
+ })
313
+ );
314
+ try {
315
+ await queryFulfilled;
316
+ } catch {
317
+ patchResult.undo();
318
+ }
319
+ }
320
+ }),
321
+ deleteReleaseAction: build.mutation({
322
+ query({ params }) {
323
+ return {
324
+ url: `/content-releases/${params.releaseId}/actions/${params.actionId}`,
325
+ method: "DELETE"
326
+ };
327
+ },
328
+ invalidatesTags: (result, error, arg) => [
329
+ { type: "Release", id: "LIST" },
330
+ { type: "Release", id: arg.params.releaseId },
331
+ { type: "ReleaseAction", id: "LIST" },
332
+ { type: "EntriesInRelease" }
333
+ ]
334
+ }),
335
+ publishRelease: build.mutation({
336
+ query({ id }) {
337
+ return {
338
+ url: `/content-releases/${id}/publish`,
339
+ method: "POST"
340
+ };
341
+ },
342
+ invalidatesTags: (result, error, arg) => [{ type: "Release", id: arg.id }]
343
+ }),
344
+ deleteRelease: build.mutation({
345
+ query({ id }) {
346
+ return {
347
+ url: `/content-releases/${id}`,
348
+ method: "DELETE"
349
+ };
350
+ },
351
+ invalidatesTags: () => [{ type: "Release", id: "LIST" }, { type: "EntriesInRelease" }]
352
+ }),
353
+ getMappedEntriesInReleases: build.query({
354
+ query(params) {
355
+ return {
356
+ url: "/content-releases/mapEntriesToReleases",
357
+ method: "GET",
358
+ config: {
359
+ params
360
+ }
361
+ };
362
+ },
363
+ transformResponse(response) {
364
+ return response.data;
365
+ },
366
+ providesTags: [{ type: "EntriesInRelease" }]
367
+ })
368
+ };
369
+ }
370
+ });
371
+ const {
372
+ useGetReleasesQuery,
373
+ useGetReleasesForEntryQuery,
374
+ useGetReleaseQuery,
375
+ useGetReleaseActionsQuery,
376
+ useCreateReleaseMutation,
377
+ useCreateReleaseActionMutation,
378
+ useCreateManyReleaseActionsMutation,
379
+ useUpdateReleaseMutation,
380
+ useUpdateReleaseActionMutation,
381
+ usePublishReleaseMutation,
382
+ useDeleteReleaseActionMutation,
383
+ useDeleteReleaseMutation,
384
+ useGetMappedEntriesInReleasesQuery
385
+ } = releaseApi;
386
+ const getTimezoneOffset = (timezone, date) => {
387
+ try {
388
+ const offsetPart = new Intl.DateTimeFormat("en", {
389
+ timeZone: timezone,
390
+ timeZoneName: "longOffset"
391
+ }).formatToParts(date).find((part) => part.type === "timeZoneName");
392
+ const offset = offsetPart ? offsetPart.value : "";
393
+ let utcOffset = offset.replace("GMT", "UTC");
394
+ if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
395
+ utcOffset = `${utcOffset}+00:00`;
396
+ }
397
+ return utcOffset;
398
+ } catch (error) {
399
+ return "";
400
+ }
401
+ };
402
+ const useTypedDispatch = reactRedux.useDispatch;
403
+ const useTypedSelector = reactRedux.useSelector;
404
+ const StyledMenuItem = styled__default.default(v2.Menu.Item)`
405
+ &:hover {
406
+ background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
407
+
408
+ svg {
409
+ path {
410
+ fill: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}600`]};
411
+ }
412
+ }
413
+
414
+ a {
415
+ color: ${({ theme }) => theme.colors.neutral800};
416
+ }
417
+ }
418
+
419
+ svg {
420
+ path {
421
+ fill: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}600`]};
422
+ }
423
+ }
424
+
425
+ a {
426
+ color: ${({ theme }) => theme.colors.neutral800};
427
+ }
428
+
429
+ span,
430
+ a {
431
+ width: 100%;
432
+ }
433
+ `;
434
+ const StyledIconButton = styled__default.default(designSystem.IconButton)`
435
+ /* Setting this style inline with borderColor will not apply the style */
436
+ border: ${({ theme }) => `1px solid ${theme.colors.neutral200}`};
437
+ `;
438
+ const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
439
+ const { formatMessage } = reactIntl.useIntl();
440
+ const toggleNotification = helperPlugin.useNotification();
441
+ const { formatAPIError } = helperPlugin.useAPIErrorHandler();
442
+ const [deleteReleaseAction] = useDeleteReleaseActionMutation();
443
+ const handleDeleteAction = async () => {
444
+ const response = await deleteReleaseAction({
445
+ params: { releaseId, actionId }
446
+ });
447
+ if ("data" in response) {
448
+ toggleNotification({
449
+ type: "success",
450
+ message: formatMessage({
451
+ id: "content-releases.content-manager-edit-view.remove-from-release.notification.success",
452
+ defaultMessage: "Entry removed from release"
453
+ })
454
+ });
455
+ return;
456
+ }
457
+ if ("error" in response) {
458
+ if (axios.isAxiosError(response.error)) {
459
+ toggleNotification({
460
+ type: "warning",
461
+ message: formatAPIError(response.error)
462
+ });
463
+ } else {
464
+ toggleNotification({
465
+ type: "warning",
466
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
467
+ });
468
+ }
469
+ }
470
+ };
471
+ return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
472
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { as: icons.Cross, width: 3, height: 3 }),
473
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
474
+ id: "content-releases.content-manager-edit-view.remove-from-release",
475
+ defaultMessage: "Remove from release"
476
+ }) })
477
+ ] }) }) });
478
+ };
479
+ const ReleaseActionEntryLinkItem = ({
480
+ contentTypeUid,
481
+ entryId,
482
+ locale
483
+ }) => {
484
+ const { formatMessage } = reactIntl.useIntl();
485
+ const collectionTypePermissions = useTypedSelector(
486
+ (state) => state.rbacProvider.collectionTypesRelatedPermissions
487
+ );
488
+ const updatePermissions = contentTypeUid ? collectionTypePermissions[contentTypeUid]?.["plugin::content-manager.explorer.update"] : [];
489
+ const canUpdateEntryForLocale = Boolean(
490
+ !locale || updatePermissions?.find(
491
+ (permission) => permission.properties?.locales?.includes(locale)
492
+ )
493
+ );
494
+ return /* @__PURE__ */ jsxRuntime.jsx(
495
+ helperPlugin.CheckPermissions,
496
+ {
497
+ permissions: [
498
+ {
499
+ action: "plugin::content-manager.explorer.update",
500
+ subject: contentTypeUid
501
+ }
502
+ ],
503
+ children: canUpdateEntryForLocale && /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsx(
504
+ v2.Link,
505
+ {
506
+ as: reactRouterDom.NavLink,
507
+ to: {
508
+ pathname: `/content-manager/collection-types/${contentTypeUid}/${entryId}`,
509
+ search: locale && `?plugins[i18n][locale]=${locale}`
510
+ },
511
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { as: icons.Pencil, width: 3, height: 3 }),
512
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: formatMessage({
513
+ id: "content-releases.content-manager-edit-view.edit-entry",
514
+ defaultMessage: "Edit entry"
515
+ }) })
516
+ }
517
+ ) })
518
+ }
519
+ );
520
+ };
521
+ const EditReleaseItem = ({ releaseId }) => {
522
+ const { formatMessage } = reactIntl.useIntl();
523
+ return /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsx(
524
+ v2.Link,
525
+ {
526
+ href: `/admin/plugins/content-releases/${releaseId}`,
527
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { as: icons.Pencil, width: 3, height: 3 }),
528
+ isExternal: false,
529
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: formatMessage({
530
+ id: "content-releases.content-manager-edit-view.edit-release",
531
+ defaultMessage: "Edit release"
532
+ }) })
533
+ }
534
+ ) });
535
+ };
536
+ const Root = ({ children, hasTriggerBorder = false }) => {
537
+ const { formatMessage } = reactIntl.useIntl();
538
+ return (
539
+ // A user can access the dropdown if they have permissions to delete a release-action OR update a release
540
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: [...PERMISSIONS.deleteAction, ...PERMISSIONS.update], children: /* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Root, { children: [
541
+ /* @__PURE__ */ jsxRuntime.jsx(
542
+ v2.Menu.Trigger,
543
+ {
544
+ as: hasTriggerBorder ? StyledIconButton : designSystem.IconButton,
545
+ paddingLeft: 2,
546
+ paddingRight: 2,
547
+ "aria-label": formatMessage({
548
+ id: "content-releases.content-manager-edit-view.release-action-menu",
549
+ defaultMessage: "Release action options"
550
+ }),
551
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {})
552
+ }
553
+ ),
554
+ /* @__PURE__ */ jsxRuntime.jsx(v2.Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
555
+ ] }) })
556
+ );
557
+ };
558
+ const ReleaseActionMenu = {
559
+ Root,
560
+ EditReleaseItem,
561
+ DeleteReleaseActionItem,
562
+ ReleaseActionEntryLinkItem
563
+ };
564
+ const getBorderLeftRadiusValue = (actionType) => {
565
+ return actionType === "publish" ? 1 : 0;
566
+ };
567
+ const getBorderRightRadiusValue = (actionType) => {
568
+ return actionType === "publish" ? 0 : 1;
569
+ };
570
+ const FieldWrapper = styled__default.default(designSystem.Field)`
571
+ border-top-left-radius: ${({ actionType, theme }) => theme.spaces[getBorderLeftRadiusValue(actionType)]};
572
+ border-bottom-left-radius: ${({ actionType, theme }) => theme.spaces[getBorderLeftRadiusValue(actionType)]};
573
+ border-top-right-radius: ${({ actionType, theme }) => theme.spaces[getBorderRightRadiusValue(actionType)]};
574
+ border-bottom-right-radius: ${({ actionType, theme }) => theme.spaces[getBorderRightRadiusValue(actionType)]};
575
+
576
+ > label {
577
+ color: inherit;
578
+ padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[3]}`};
579
+ text-align: center;
580
+ vertical-align: middle;
581
+ text-transform: capitalize;
582
+ }
583
+
584
+ &[data-checked='true'] {
585
+ color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
586
+ background-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary100 : theme.colors.danger100};
587
+ border-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
588
+ }
589
+
590
+ &[data-checked='false'] {
591
+ border-left: ${({ actionType }) => actionType === "unpublish" && "none"};
592
+ border-right: ${({ actionType }) => actionType === "publish" && "none"};
593
+ }
594
+
595
+ &[data-checked='false'][data-disabled='false']:hover {
596
+ color: ${({ theme }) => theme.colors.neutral700};
597
+ background-color: ${({ theme }) => theme.colors.neutral100};
598
+ border-color: ${({ theme }) => theme.colors.neutral200};
599
+
600
+ & > label {
601
+ cursor: pointer;
602
+ }
603
+ }
604
+
605
+ &[data-disabled='true'] {
606
+ color: ${({ theme }) => theme.colors.neutral600};
607
+ background-color: ${({ theme }) => theme.colors.neutral150};
608
+ border-color: ${({ theme }) => theme.colors.neutral300};
609
+ }
610
+ `;
611
+ const ActionOption = ({
612
+ selected,
613
+ actionType,
614
+ handleChange,
615
+ name,
616
+ disabled = false
617
+ }) => {
618
+ return /* @__PURE__ */ jsxRuntime.jsx(
619
+ FieldWrapper,
620
+ {
621
+ actionType,
622
+ background: "primary0",
623
+ borderColor: "neutral200",
624
+ color: selected === actionType ? "primary600" : "neutral600",
625
+ position: "relative",
626
+ cursor: "pointer",
627
+ "data-checked": selected === actionType,
628
+ "data-disabled": disabled && selected !== actionType,
629
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.FieldLabel, { htmlFor: `${name}-${actionType}`, children: [
630
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { children: /* @__PURE__ */ jsxRuntime.jsx(
631
+ designSystem.FieldInput,
632
+ {
633
+ type: "radio",
634
+ id: `${name}-${actionType}`,
635
+ name,
636
+ checked: selected === actionType,
637
+ onChange: handleChange,
638
+ value: actionType,
639
+ disabled
640
+ }
641
+ ) }),
642
+ actionType
643
+ ] })
644
+ }
645
+ );
646
+ };
647
+ const ReleaseActionOptions = ({
648
+ selected,
649
+ handleChange,
650
+ name,
651
+ disabled = false
652
+ }) => {
653
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { children: [
654
+ /* @__PURE__ */ jsxRuntime.jsx(
655
+ ActionOption,
656
+ {
657
+ actionType: "publish",
658
+ selected,
659
+ handleChange,
660
+ name,
661
+ disabled
662
+ }
663
+ ),
664
+ /* @__PURE__ */ jsxRuntime.jsx(
665
+ ActionOption,
666
+ {
667
+ actionType: "unpublish",
668
+ selected,
669
+ handleChange,
670
+ name,
671
+ disabled
672
+ }
673
+ )
674
+ ] });
675
+ };
676
+ const RELEASE_ACTION_FORM_SCHEMA = yup__namespace.object().shape({
677
+ type: yup__namespace.string().oneOf(["publish", "unpublish"]).required(),
678
+ releaseId: yup__namespace.string().required()
679
+ });
680
+ const INITIAL_VALUES = {
681
+ type: "publish",
682
+ releaseId: ""
683
+ };
684
+ const NoReleases = () => {
685
+ const { formatMessage } = reactIntl.useIntl();
686
+ return /* @__PURE__ */ jsxRuntime.jsx(
687
+ helperPlugin.NoContent,
688
+ {
689
+ content: {
690
+ id: "content-releases.content-manager-edit-view.add-to-release.no-releases-message",
691
+ defaultMessage: "No available releases. Open the list of releases and create a new one from there."
692
+ },
693
+ action: /* @__PURE__ */ jsxRuntime.jsx(
694
+ v2.LinkButton,
695
+ {
696
+ to: {
697
+ pathname: "/plugins/content-releases"
698
+ },
699
+ as: reactRouterDom.Link,
700
+ variant: "secondary",
701
+ children: formatMessage({
702
+ id: "content-releases.content-manager-edit-view.add-to-release.redirect-button",
703
+ defaultMessage: "Open the list of releases"
704
+ })
705
+ }
706
+ )
707
+ }
708
+ );
709
+ };
710
+ const AddActionToReleaseModal = ({
711
+ handleClose,
712
+ contentTypeUid,
713
+ entryId
714
+ }) => {
715
+ const releaseHeaderId = React__namespace.useId();
716
+ const { formatMessage } = reactIntl.useIntl();
717
+ const toggleNotification = helperPlugin.useNotification();
718
+ const { formatAPIError } = helperPlugin.useAPIErrorHandler();
719
+ const { modifiedData } = helperPlugin.useCMEditViewDataManager();
720
+ const response = useGetReleasesForEntryQuery({
721
+ contentTypeUid,
722
+ entryId,
723
+ hasEntryAttached: false
724
+ });
725
+ const releases = response.data?.data;
726
+ const [createReleaseAction, { isLoading }] = useCreateReleaseActionMutation();
727
+ const handleSubmit = async (values) => {
728
+ const locale = modifiedData.locale;
729
+ const releaseActionEntry = {
730
+ contentType: contentTypeUid,
731
+ id: entryId,
732
+ locale
733
+ };
734
+ const response2 = await createReleaseAction({
735
+ body: { type: values.type, entry: releaseActionEntry },
736
+ params: { releaseId: values.releaseId }
737
+ });
738
+ if ("data" in response2) {
739
+ toggleNotification({
740
+ type: "success",
741
+ message: formatMessage({
742
+ id: "content-releases.content-manager-edit-view.add-to-release.notification.success",
743
+ defaultMessage: "Entry added to release"
744
+ })
745
+ });
746
+ handleClose();
747
+ return;
748
+ }
749
+ if ("error" in response2) {
750
+ if (axios.isAxiosError(response2.error)) {
751
+ toggleNotification({
752
+ type: "warning",
753
+ message: formatAPIError(response2.error)
754
+ });
755
+ } else {
756
+ toggleNotification({
757
+ type: "warning",
758
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
759
+ });
760
+ }
761
+ }
762
+ };
763
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { onClose: handleClose, labelledBy: releaseHeaderId, children: [
764
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: releaseHeaderId, fontWeight: "bold", textColor: "neutral800", children: formatMessage({
765
+ id: "content-releases.content-manager-edit-view.add-to-release",
766
+ defaultMessage: "Add to release"
767
+ }) }) }),
768
+ /* @__PURE__ */ jsxRuntime.jsx(
769
+ formik.Formik,
770
+ {
771
+ onSubmit: handleSubmit,
772
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
773
+ initialValues: INITIAL_VALUES,
774
+ children: ({ values, setFieldValue }) => {
775
+ return /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
776
+ releases?.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(NoReleases, {}) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
777
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxRuntime.jsx(
778
+ designSystem.SingleSelect,
779
+ {
780
+ required: true,
781
+ label: formatMessage({
782
+ id: "content-releases.content-manager-edit-view.add-to-release.select-label",
783
+ defaultMessage: "Select a release"
784
+ }),
785
+ placeholder: formatMessage({
786
+ id: "content-releases.content-manager-edit-view.add-to-release.select-placeholder",
787
+ defaultMessage: "Select"
788
+ }),
789
+ onChange: (value) => setFieldValue("releaseId", value),
790
+ value: values.releaseId,
791
+ children: releases?.map((release) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: release.id, children: release.name }, release.id))
792
+ }
793
+ ) }),
794
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.FieldLabel, { children: formatMessage({
795
+ id: "content-releases.content-manager-edit-view.add-to-release.action-type-label",
796
+ defaultMessage: "What do you want to do with this entry?"
797
+ }) }),
798
+ /* @__PURE__ */ jsxRuntime.jsx(
799
+ ReleaseActionOptions,
800
+ {
801
+ selected: values.type,
802
+ handleChange: (e) => setFieldValue("type", e.target.value),
803
+ name: "type"
804
+ }
805
+ )
806
+ ] }) }),
807
+ /* @__PURE__ */ jsxRuntime.jsx(
808
+ designSystem.ModalFooter,
809
+ {
810
+ startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({
811
+ id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
812
+ defaultMessage: "Cancel"
813
+ }) }),
814
+ endActions: (
815
+ /**
816
+ * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
817
+ * for yup.string().required(), even when the value is falsy (including empty string)
818
+ */
819
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
820
+ id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
821
+ defaultMessage: "Continue"
822
+ }) })
823
+ )
824
+ }
825
+ )
826
+ ] });
827
+ }
828
+ }
829
+ )
830
+ ] });
831
+ };
832
+ const CMReleasesContainer = () => {
833
+ const [isModalOpen, setIsModalOpen] = React__namespace.useState(false);
834
+ const { formatMessage, formatDate, formatTime } = reactIntl.useIntl();
835
+ const {
836
+ isCreatingEntry,
837
+ hasDraftAndPublish,
838
+ initialData: { id: entryId },
839
+ slug
840
+ } = helperPlugin.useCMEditViewDataManager();
841
+ const contentTypeUid = slug;
842
+ const canFetch = entryId != null && contentTypeUid != null;
843
+ const fetchParams = canFetch ? {
844
+ contentTypeUid,
845
+ entryId,
846
+ hasEntryAttached: true
847
+ } : query.skipToken;
848
+ const response = useGetReleasesForEntryQuery(fetchParams);
849
+ const releases = response.data?.data;
850
+ if (!canFetch) {
851
+ return null;
852
+ }
853
+ if (isCreatingEntry || !hasDraftAndPublish) {
854
+ return null;
855
+ }
856
+ const toggleModal = () => setIsModalOpen((prev) => !prev);
857
+ const getReleaseColorVariant = (actionType, shade) => {
858
+ if (actionType === "unpublish") {
859
+ return `secondary${shade}`;
860
+ }
861
+ return `success${shade}`;
862
+ };
863
+ return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxRuntime.jsxs(
864
+ designSystem.Box,
865
+ {
866
+ as: "aside",
867
+ "aria-label": formatMessage({
868
+ id: "content-releases.plugin.name",
869
+ defaultMessage: "Releases"
870
+ }),
871
+ background: "neutral0",
872
+ borderColor: "neutral150",
873
+ hasRadius: true,
874
+ padding: 4,
875
+ shadow: "tableShadow",
876
+ children: [
877
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
878
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", children: formatMessage({
879
+ id: "content-releases.plugin.name",
880
+ defaultMessage: "Releases"
881
+ }) }),
882
+ releases?.map((release) => {
883
+ return /* @__PURE__ */ jsxRuntime.jsxs(
884
+ designSystem.Flex,
885
+ {
886
+ direction: "column",
887
+ alignItems: "start",
888
+ borderWidth: "1px",
889
+ borderStyle: "solid",
890
+ borderColor: getReleaseColorVariant(release.actions[0].type, "200"),
891
+ overflow: "hidden",
892
+ hasRadius: true,
893
+ children: [
894
+ /* @__PURE__ */ jsxRuntime.jsx(
895
+ designSystem.Box,
896
+ {
897
+ paddingTop: 3,
898
+ paddingBottom: 3,
899
+ paddingLeft: 4,
900
+ paddingRight: 4,
901
+ background: getReleaseColorVariant(release.actions[0].type, "100"),
902
+ width: "100%",
903
+ children: /* @__PURE__ */ jsxRuntime.jsx(
904
+ designSystem.Typography,
905
+ {
906
+ fontSize: 1,
907
+ variant: "pi",
908
+ textColor: getReleaseColorVariant(release.actions[0].type, "600"),
909
+ children: formatMessage(
910
+ {
911
+ id: "content-releases.content-manager-edit-view.list-releases.title",
912
+ defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
913
+ },
914
+ { isPublish: release.actions[0].type === "publish" }
915
+ )
916
+ }
917
+ )
918
+ }
919
+ ),
920
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
921
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
922
+ release.scheduledAt && release.timezone && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
923
+ {
924
+ id: "content-releases.content-manager-edit-view.scheduled.date",
925
+ defaultMessage: "{date} at {time} ({offset})"
926
+ },
927
+ {
928
+ date: formatDate(new Date(release.scheduledAt), {
929
+ day: "2-digit",
930
+ month: "2-digit",
931
+ year: "numeric",
932
+ timeZone: release.timezone
933
+ }),
934
+ time: formatTime(new Date(release.scheduledAt), {
935
+ hourCycle: "h23",
936
+ timeZone: release.timezone
937
+ }),
938
+ offset: getTimezoneOffset(
939
+ release.timezone,
940
+ new Date(release.scheduledAt)
941
+ )
942
+ }
943
+ ) }),
944
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsxRuntime.jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
945
+ /* @__PURE__ */ jsxRuntime.jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
946
+ /* @__PURE__ */ jsxRuntime.jsx(
947
+ ReleaseActionMenu.DeleteReleaseActionItem,
948
+ {
949
+ releaseId: release.id,
950
+ actionId: release.actions[0].id
951
+ }
952
+ )
953
+ ] }) })
954
+ ] })
955
+ ]
956
+ },
957
+ release.id
958
+ );
959
+ }),
960
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.createAction, children: /* @__PURE__ */ jsxRuntime.jsx(
961
+ designSystem.Button,
962
+ {
963
+ justifyContent: "center",
964
+ paddingLeft: 4,
965
+ paddingRight: 4,
966
+ color: "neutral700",
967
+ variant: "tertiary",
968
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
969
+ onClick: toggleModal,
970
+ children: formatMessage({
971
+ id: "content-releases.content-manager-edit-view.add-to-release",
972
+ defaultMessage: "Add to release"
973
+ })
974
+ }
975
+ ) })
976
+ ] }),
977
+ isModalOpen && /* @__PURE__ */ jsxRuntime.jsx(
978
+ AddActionToReleaseModal,
979
+ {
980
+ handleClose: toggleModal,
981
+ contentTypeUid,
982
+ entryId
983
+ }
984
+ )
985
+ ]
986
+ }
987
+ ) });
988
+ };
989
+ const getContentPermissions = (subject) => {
990
+ const permissions = {
991
+ publish: [
992
+ {
993
+ action: "plugin::content-manager.explorer.publish",
994
+ subject,
995
+ id: "",
996
+ actionParameters: {},
997
+ properties: {},
998
+ conditions: []
999
+ }
1000
+ ]
1001
+ };
1002
+ return permissions;
1003
+ };
1004
+ const ReleaseAction = ({ ids, model }) => {
1005
+ const { formatMessage } = reactIntl.useIntl();
1006
+ const toggleNotification = helperPlugin.useNotification();
1007
+ const { formatAPIError } = helperPlugin.useAPIErrorHandler();
1008
+ const { modifiedData } = helperPlugin.useCMEditViewDataManager();
1009
+ const contentPermissions = getContentPermissions(model);
1010
+ const {
1011
+ allowedActions: { canPublish }
1012
+ } = helperPlugin.useRBAC(contentPermissions);
1013
+ const {
1014
+ allowedActions: { canCreate }
1015
+ } = helperPlugin.useRBAC(PERMISSIONS);
1016
+ const response = useGetReleasesQuery();
1017
+ const releases = response.data?.data;
1018
+ const [createManyReleaseActions, { isLoading }] = useCreateManyReleaseActionsMutation();
1019
+ const handleSubmit = async (values) => {
1020
+ const locale = modifiedData.locale;
1021
+ const releaseActionEntries = ids.map((id) => ({
1022
+ type: values.type,
1023
+ entry: {
1024
+ contentType: model,
1025
+ id,
1026
+ locale
1027
+ }
1028
+ }));
1029
+ const response2 = await createManyReleaseActions({
1030
+ body: releaseActionEntries,
1031
+ params: { releaseId: values.releaseId }
1032
+ });
1033
+ if ("data" in response2) {
1034
+ const notificationMessage = formatMessage(
1035
+ {
1036
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.message",
1037
+ defaultMessage: "{entriesAlreadyInRelease} out of {totalEntries} entries were already in the release."
1038
+ },
1039
+ {
1040
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
1041
+ totalEntries: response2.data.meta.totalEntries
1042
+ }
1043
+ );
1044
+ const notification = {
1045
+ type: "success",
1046
+ title: formatMessage(
1047
+ {
1048
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.title",
1049
+ defaultMessage: "Successfully added to release."
1050
+ },
1051
+ {
1052
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
1053
+ totalEntries: response2.data.meta.totalEntries
1054
+ }
1055
+ ),
1056
+ message: response2.data.meta.entriesAlreadyInRelease ? notificationMessage : ""
1057
+ };
1058
+ toggleNotification(notification);
1059
+ return true;
1060
+ }
1061
+ if ("error" in response2) {
1062
+ if (axios.isAxiosError(response2.error)) {
1063
+ toggleNotification({
1064
+ type: "warning",
1065
+ message: formatAPIError(response2.error)
1066
+ });
1067
+ } else {
1068
+ toggleNotification({
1069
+ type: "warning",
1070
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1071
+ });
1072
+ }
1073
+ }
1074
+ };
1075
+ if (!canCreate || !canPublish)
1076
+ return null;
1077
+ return {
1078
+ actionType: "release",
1079
+ variant: "tertiary",
1080
+ label: formatMessage({
1081
+ id: "content-manager-list-view.add-to-release",
1082
+ defaultMessage: "Add to Release"
1083
+ }),
1084
+ dialog: {
1085
+ type: "modal",
1086
+ title: formatMessage({
1087
+ id: "content-manager-list-view.add-to-release",
1088
+ defaultMessage: "Add to Release"
1089
+ }),
1090
+ content: ({ onClose }) => {
1091
+ return /* @__PURE__ */ jsxRuntime.jsx(
1092
+ formik.Formik,
1093
+ {
1094
+ onSubmit: async (values) => {
1095
+ const data = await handleSubmit(values);
1096
+ if (data) {
1097
+ return onClose();
1098
+ }
1099
+ },
1100
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
1101
+ initialValues: INITIAL_VALUES,
1102
+ children: ({ values, setFieldValue }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
1103
+ releases?.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(NoReleases, {}) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
1104
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxRuntime.jsx(
1105
+ designSystem.SingleSelect,
1106
+ {
1107
+ required: true,
1108
+ label: formatMessage({
1109
+ id: "content-releases.content-manager-list-view.add-to-release.select-label",
1110
+ defaultMessage: "Select a release"
1111
+ }),
1112
+ placeholder: formatMessage({
1113
+ id: "content-releases.content-manager-list-view.add-to-release.select-placeholder",
1114
+ defaultMessage: "Select"
1115
+ }),
1116
+ onChange: (value) => setFieldValue("releaseId", value),
1117
+ value: values.releaseId,
1118
+ children: releases?.map((release) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: release.id, children: release.name }, release.id))
1119
+ }
1120
+ ) }),
1121
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.FieldLabel, { children: formatMessage({
1122
+ id: "content-releases.content-manager-list-view.add-to-release.action-type-label",
1123
+ defaultMessage: "What do you want to do with these entries?"
1124
+ }) }),
1125
+ /* @__PURE__ */ jsxRuntime.jsx(
1126
+ ReleaseActionOptions,
1127
+ {
1128
+ selected: values.type,
1129
+ handleChange: (e) => setFieldValue("type", e.target.value),
1130
+ name: "type"
1131
+ }
1132
+ )
1133
+ ] }) }),
1134
+ /* @__PURE__ */ jsxRuntime.jsx(
1135
+ designSystem.ModalFooter,
1136
+ {
1137
+ startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
1138
+ id: "content-releases.content-manager-list-view.add-to-release.cancel-button",
1139
+ defaultMessage: "Cancel"
1140
+ }) }),
1141
+ endActions: (
1142
+ /**
1143
+ * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
1144
+ * for yup.string().required(), even when the value is falsy (including empty string)
1145
+ */
1146
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
1147
+ id: "content-releases.content-manager-list-view.add-to-release.continue-button",
1148
+ defaultMessage: "Continue"
1149
+ }) })
1150
+ )
1151
+ }
1152
+ )
1153
+ ] })
1154
+ }
1155
+ );
1156
+ }
1157
+ }
1158
+ };
1159
+ };
1160
+ const Button = styled__default.default.button`
1161
+ svg {
1162
+ > g,
1163
+ path {
1164
+ fill: ${({ theme }) => theme.colors.neutral500};
1165
+ }
1166
+ }
1167
+ &:hover {
1168
+ svg {
1169
+ > g,
1170
+ path {
1171
+ fill: ${({ theme }) => theme.colors.neutral600};
1172
+ }
1173
+ }
1174
+ }
1175
+ &:active {
1176
+ svg {
1177
+ > g,
1178
+ path {
1179
+ fill: ${({ theme }) => theme.colors.neutral400};
1180
+ }
1181
+ }
1182
+ }
1183
+ `;
1184
+ const ActionWrapper = styled__default.default(designSystem.Flex)`
1185
+ svg {
1186
+ height: ${4 / 16}rem;
1187
+ }
1188
+ `;
1189
+ const useReleasesList = (entryId) => {
1190
+ const { uid: contentTypeUid } = useTypedSelector(
1191
+ (state) => state["content-manager_listView"].contentType
1192
+ );
1193
+ const listViewData = useTypedSelector((state) => state["content-manager_listView"].data);
1194
+ const entriesIds = listViewData.map((entry) => entry.id);
1195
+ const response = useGetMappedEntriesInReleasesQuery(
1196
+ { contentTypeUid, entriesIds },
1197
+ { skip: !entriesIds || !contentTypeUid || entriesIds.length === 0 }
1198
+ );
1199
+ const mappedEntriesInReleases = response.data || {};
1200
+ return mappedEntriesInReleases?.[entryId] || [];
1201
+ };
1202
+ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1203
+ const { contentType } = layout;
1204
+ if (!contentType.options?.draftAndPublish) {
1205
+ return { displayedHeaders, layout };
1206
+ }
1207
+ return {
1208
+ displayedHeaders: [
1209
+ ...displayedHeaders,
1210
+ {
1211
+ key: "__release_key__",
1212
+ fieldSchema: { type: "string" },
1213
+ metadatas: { label: "To be released in", searchable: true, sortable: false },
1214
+ name: "releasedAt",
1215
+ cellFormatter: (props) => /* @__PURE__ */ jsxRuntime.jsx(ReleaseListCell, { ...props })
1216
+ }
1217
+ ],
1218
+ layout
1219
+ };
1220
+ };
1221
+ const ReleaseListCell = ({ id }) => {
1222
+ const releases = useReleasesList(id);
1223
+ const [visible, setVisible] = React__namespace.useState(false);
1224
+ const buttonRef = React__namespace.useRef(null);
1225
+ const { formatMessage } = reactIntl.useIntl();
1226
+ const handleTogglePopover = () => setVisible((prev) => !prev);
1227
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", onClick: handleTogglePopover, ref: buttonRef, children: /* @__PURE__ */ jsxRuntime.jsxs(ActionWrapper, { height: "2rem", width: "2rem", children: [
1228
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { style: { maxWidth: "252px", cursor: "pointer" }, textColor: "neutral800", children: releases.length > 0 ? formatMessage(
1229
+ {
1230
+ id: "content-releases.content-manager.list-view.releases-number",
1231
+ defaultMessage: "{number} {number, plural, one {release} other {releases}}"
1232
+ },
1233
+ {
1234
+ number: releases.length
1235
+ }
1236
+ ) : "-" }),
1237
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { children: [
1238
+ releases.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.SortIcon, {}),
1239
+ visible && /* @__PURE__ */ jsxRuntime.jsx(
1240
+ designSystem.Popover,
1241
+ {
1242
+ onDismiss: handleTogglePopover,
1243
+ source: buttonRef,
1244
+ spacing: 16,
1245
+ children: /* @__PURE__ */ jsxRuntime.jsx("ul", { children: releases.map(({ id: id2, name }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 3, as: "li", children: /* @__PURE__ */ jsxRuntime.jsx(v2.Link, { href: `/admin/plugins/content-releases/${id2}`, isExternal: false, children: name }) }, id2)) })
1246
+ }
1247
+ )
1248
+ ] })
1249
+ ] }) }) });
1250
+ };
1251
+ const admin = {
1252
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1253
+ register(app) {
1254
+ app.createHook("ContentReleases/pages/ReleaseDetails/add-locale-in-releases");
1255
+ if (window.strapi.features.isEnabled("cms-content-releases")) {
1256
+ app.addMenuLink({
1257
+ to: `/plugins/${pluginId}`,
1258
+ icon: icons.PaperPlane,
1259
+ intlLabel: {
1260
+ id: `${pluginId}.plugin.name`,
1261
+ defaultMessage: "Releases"
1262
+ },
1263
+ async Component() {
1264
+ const { App } = await Promise.resolve().then(() => require("./App-dLXY5ei3.js"));
1265
+ return App;
1266
+ },
1267
+ permissions: PERMISSIONS.main
1268
+ });
1269
+ app.addMiddlewares([() => releaseApi.middleware]);
1270
+ app.addReducers({
1271
+ [releaseApi.reducerPath]: releaseApi.reducer
1272
+ });
1273
+ app.injectContentManagerComponent("editView", "right-links", {
1274
+ name: `${pluginId}-link`,
1275
+ Component: CMReleasesContainer
1276
+ });
1277
+ app.plugins["content-manager"].apis.addBulkAction((actions) => {
1278
+ const deleteActionIndex = actions.findIndex((action) => action.name === "DeleteAction");
1279
+ actions.splice(deleteActionIndex, 0, ReleaseAction);
1280
+ return actions;
1281
+ });
1282
+ app.registerHook("Admin/CM/pages/ListView/inject-column-in-table", addColumnToTableHook);
1283
+ } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
1284
+ app.addMenuLink({
1285
+ to: `/plugins/purchase-content-releases`,
1286
+ icon: icons.PaperPlane,
1287
+ intlLabel: {
1288
+ id: `${pluginId}.plugin.name`,
1289
+ defaultMessage: "Releases"
1290
+ },
1291
+ async Component() {
1292
+ const { PurchaseContentReleases } = await Promise.resolve().then(() => require("./PurchaseContentReleases-bpIYXOfu.js"));
1293
+ return PurchaseContentReleases;
1294
+ },
1295
+ lockIcon: true
1296
+ // TODO: to replace with another name in v5
1297
+ });
1298
+ }
1299
+ },
1300
+ async registerTrads({ locales }) {
1301
+ const importedTrads = await Promise.all(
1302
+ locales.map((locale) => {
1303
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-HrREghh3.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
1304
+ return {
1305
+ data: helperPlugin.prefixPluginTranslations(data, "content-releases"),
1306
+ locale
1307
+ };
1308
+ }).catch(() => {
1309
+ return {
1310
+ data: {},
1311
+ locale
1312
+ };
1313
+ });
1314
+ })
1315
+ );
1316
+ return Promise.resolve(importedTrads);
1317
+ }
1318
+ };
1319
+ exports.PERMISSIONS = PERMISSIONS;
1320
+ exports.ReleaseActionMenu = ReleaseActionMenu;
1321
+ exports.ReleaseActionOptions = ReleaseActionOptions;
1322
+ exports.admin = admin;
1323
+ exports.getTimezoneOffset = getTimezoneOffset;
1324
+ exports.isAxiosError = isAxiosError;
1325
+ exports.pluginId = pluginId;
1326
+ exports.releaseApi = releaseApi;
1327
+ exports.useCreateReleaseMutation = useCreateReleaseMutation;
1328
+ exports.useDeleteReleaseMutation = useDeleteReleaseMutation;
1329
+ exports.useGetReleaseActionsQuery = useGetReleaseActionsQuery;
1330
+ exports.useGetReleaseQuery = useGetReleaseQuery;
1331
+ exports.useGetReleasesQuery = useGetReleasesQuery;
1332
+ exports.usePublishReleaseMutation = usePublishReleaseMutation;
1333
+ exports.useTypedDispatch = useTypedDispatch;
1334
+ exports.useUpdateReleaseActionMutation = useUpdateReleaseActionMutation;
1335
+ exports.useUpdateReleaseMutation = useUpdateReleaseMutation;
1336
+ //# sourceMappingURL=index-CVO0Rqdm.js.map