@strapi/content-releases 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813 → 0.0.0-experimental.eba25ec571b091c6bde1104eb6c753debdf15462

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 (104) hide show
  1. package/LICENSE +17 -1
  2. package/dist/_chunks/{App-BsUSTHVD.mjs → App-FQyYFBJT.mjs} +642 -426
  3. package/dist/_chunks/App-FQyYFBJT.mjs.map +1 -0
  4. package/dist/_chunks/{App-CXRpb2hi.js → App-lx4Ucy9W.js} +680 -466
  5. package/dist/_chunks/App-lx4Ucy9W.js.map +1 -0
  6. package/dist/_chunks/ReleasesSettingsPage-DqBxvJ9i.mjs +178 -0
  7. package/dist/_chunks/ReleasesSettingsPage-DqBxvJ9i.mjs.map +1 -0
  8. package/dist/_chunks/ReleasesSettingsPage-T5VEAV03.js +178 -0
  9. package/dist/_chunks/ReleasesSettingsPage-T5VEAV03.js.map +1 -0
  10. package/dist/_chunks/{en-DtFJ5ViE.js → en-BWPPsSH-.js} +18 -2
  11. package/dist/_chunks/en-BWPPsSH-.js.map +1 -0
  12. package/dist/_chunks/{en-B9Ur3VsE.mjs → en-D9Q4YW03.mjs} +18 -2
  13. package/dist/_chunks/en-D9Q4YW03.mjs.map +1 -0
  14. package/dist/_chunks/{index-DJLIZdZv.mjs → index-CK9G80CL.mjs} +740 -600
  15. package/dist/_chunks/index-CK9G80CL.mjs.map +1 -0
  16. package/dist/_chunks/{index-B6-lic1Q.js → index-Cl3tM1YW.js} +731 -593
  17. package/dist/_chunks/index-Cl3tM1YW.js.map +1 -0
  18. package/dist/_chunks/schemas-BE1LxE9J.js +62 -0
  19. package/dist/_chunks/schemas-BE1LxE9J.js.map +1 -0
  20. package/dist/_chunks/schemas-DdA2ic2U.mjs +44 -0
  21. package/dist/_chunks/schemas-DdA2ic2U.mjs.map +1 -0
  22. package/dist/admin/index.js +1 -1
  23. package/dist/admin/index.mjs +2 -2
  24. package/dist/admin/src/components/EntryValidationPopover.d.ts +13 -0
  25. package/dist/admin/src/components/ReleaseActionMenu.d.ts +3 -3
  26. package/dist/admin/src/components/{CMReleasesContainer.d.ts → ReleaseActionModal.d.ts} +3 -1
  27. package/dist/admin/src/components/ReleaseListCell.d.ts +28 -0
  28. package/dist/admin/src/components/ReleaseModal.d.ts +3 -2
  29. package/dist/admin/src/components/ReleasesPanel.d.ts +3 -0
  30. package/dist/admin/src/constants.d.ts +18 -0
  31. package/dist/admin/src/modules/hooks.d.ts +7 -0
  32. package/dist/admin/src/pages/ReleasesSettingsPage.d.ts +1 -0
  33. package/dist/admin/src/services/release.d.ts +53 -370
  34. package/dist/admin/src/utils/api.d.ts +6 -0
  35. package/dist/admin/src/utils/time.d.ts +9 -0
  36. package/dist/admin/src/validation/schemas.d.ts +6 -0
  37. package/dist/server/index.js +888 -612
  38. package/dist/server/index.js.map +1 -1
  39. package/dist/server/index.mjs +889 -613
  40. package/dist/server/index.mjs.map +1 -1
  41. package/dist/server/src/bootstrap.d.ts.map +1 -1
  42. package/dist/server/src/constants.d.ts +11 -2
  43. package/dist/server/src/constants.d.ts.map +1 -1
  44. package/dist/server/src/content-types/index.d.ts +3 -5
  45. package/dist/server/src/content-types/index.d.ts.map +1 -1
  46. package/dist/server/src/content-types/release-action/index.d.ts +3 -5
  47. package/dist/server/src/content-types/release-action/index.d.ts.map +1 -1
  48. package/dist/server/src/content-types/release-action/schema.d.ts +3 -5
  49. package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -1
  50. package/dist/server/src/controllers/index.d.ts +6 -1
  51. package/dist/server/src/controllers/index.d.ts.map +1 -1
  52. package/dist/server/src/controllers/release-action.d.ts.map +1 -1
  53. package/dist/server/src/controllers/release.d.ts +7 -1
  54. package/dist/server/src/controllers/release.d.ts.map +1 -1
  55. package/dist/server/src/controllers/settings.d.ts +11 -0
  56. package/dist/server/src/controllers/settings.d.ts.map +1 -0
  57. package/dist/server/src/controllers/validation/release-action.d.ts +7 -1
  58. package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -1
  59. package/dist/server/src/controllers/validation/release.d.ts +2 -0
  60. package/dist/server/src/controllers/validation/release.d.ts.map +1 -1
  61. package/dist/server/src/controllers/validation/settings.d.ts +3 -0
  62. package/dist/server/src/controllers/validation/settings.d.ts.map +1 -0
  63. package/dist/server/src/index.d.ts +64 -49
  64. package/dist/server/src/index.d.ts.map +1 -1
  65. package/dist/server/src/middlewares/documents.d.ts +6 -0
  66. package/dist/server/src/middlewares/documents.d.ts.map +1 -0
  67. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts +9 -0
  68. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts.map +1 -0
  69. package/dist/server/src/migrations/index.d.ts.map +1 -1
  70. package/dist/server/src/register.d.ts.map +1 -1
  71. package/dist/server/src/routes/index.d.ts +16 -0
  72. package/dist/server/src/routes/index.d.ts.map +1 -1
  73. package/dist/server/src/routes/release.d.ts.map +1 -1
  74. package/dist/server/src/routes/settings.d.ts +18 -0
  75. package/dist/server/src/routes/settings.d.ts.map +1 -0
  76. package/dist/server/src/services/index.d.ts +36 -38
  77. package/dist/server/src/services/index.d.ts.map +1 -1
  78. package/dist/server/src/services/release-action.d.ts +34 -0
  79. package/dist/server/src/services/release-action.d.ts.map +1 -0
  80. package/dist/server/src/services/release.d.ts +6 -41
  81. package/dist/server/src/services/release.d.ts.map +1 -1
  82. package/dist/server/src/services/settings.d.ts +13 -0
  83. package/dist/server/src/services/settings.d.ts.map +1 -0
  84. package/dist/server/src/services/validation.d.ts +1 -1
  85. package/dist/server/src/services/validation.d.ts.map +1 -1
  86. package/dist/server/src/utils/index.d.ts +29 -8
  87. package/dist/server/src/utils/index.d.ts.map +1 -1
  88. package/dist/shared/contracts/release-actions.d.ts +17 -11
  89. package/dist/shared/contracts/release-actions.d.ts.map +1 -1
  90. package/dist/shared/contracts/releases.d.ts +9 -7
  91. package/dist/shared/contracts/releases.d.ts.map +1 -1
  92. package/dist/shared/contracts/settings.d.ts +39 -0
  93. package/dist/shared/contracts/settings.d.ts.map +1 -0
  94. package/package.json +23 -22
  95. package/dist/_chunks/App-BsUSTHVD.mjs.map +0 -1
  96. package/dist/_chunks/App-CXRpb2hi.js.map +0 -1
  97. package/dist/_chunks/en-B9Ur3VsE.mjs.map +0 -1
  98. package/dist/_chunks/en-DtFJ5ViE.js.map +0 -1
  99. package/dist/_chunks/index-B6-lic1Q.js.map +0 -1
  100. package/dist/_chunks/index-DJLIZdZv.mjs.map +0 -1
  101. package/dist/admin/src/services/axios.d.ts +0 -29
  102. package/dist/shared/validation-schemas.d.ts +0 -2
  103. package/dist/shared/validation-schemas.d.ts.map +0 -1
  104. package/strapi-server.js +0 -3
@@ -1,18 +1,15 @@
1
- import { Cross, Pencil, More, Plus, PaperPlane } from "@strapi/icons";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import * as React from "react";
4
- import { skipToken } from "@reduxjs/toolkit/query";
5
- import { getFetchClient, useNotification, useAPIErrorHandler, useRBAC, useAuth, useQueryParams } from "@strapi/admin/strapi-admin";
6
- import { unstable_useDocument } from "@strapi/content-manager/strapi-admin";
7
- import { Menu, IconButton, Flex, Typography, Field, FieldLabel, VisuallyHidden, FieldInput, Box, Button, EmptyStateLayout, LinkButton, ModalLayout, ModalHeader, ModalBody, SingleSelect, SingleSelectOption, ModalFooter } from "@strapi/design-system";
8
- import { EmptyDocuments } from "@strapi/icons/symbols";
9
- import { isAxiosError as isAxiosError$1 } from "axios";
10
- import { Formik, Form } from "formik";
1
+ import { PaperPlane, CaretDown, Cross, Pencil, More } from "@strapi/icons";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import { adminApi, useRBAC, useNotification, useAPIErrorHandler, useQueryParams, isFetchError, useTable, useAuth } from "@strapi/admin/strapi-admin";
4
+ import { Field, Flex, VisuallyHidden, Modal, Button, EmptyStateLayout, LinkButton, Box, SingleSelect, SingleSelectOption, Popover, Typography, Link as Link$1, Menu, AccessibleIcon } from "@strapi/design-system";
5
+ import { useFormik, Formik, Form } from "formik";
11
6
  import { useIntl } from "react-intl";
12
- import { Link, useParams } from "react-router-dom";
7
+ import { unstable_useDocumentLayout } from "@strapi/content-manager/strapi-admin";
8
+ import { EmptyDocuments } from "@strapi/icons/symbols";
9
+ import { Link, NavLink } from "react-router-dom";
13
10
  import * as yup from "yup";
14
- import { createApi } from "@reduxjs/toolkit/query/react";
15
- import styled from "styled-components";
11
+ import { styled } from "styled-components";
12
+ import * as React from "react";
16
13
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
17
14
  const v = glob[path];
18
15
  if (v) {
@@ -94,55 +91,70 @@ const PERMISSIONS = {
94
91
  }
95
92
  ]
96
93
  };
97
- const pluginId = "content-releases";
98
- const axiosBaseQuery = async ({
99
- url,
100
- method,
101
- data,
102
- config
103
- }) => {
104
- try {
105
- const { get, post, del, put } = getFetchClient();
106
- if (method === "POST") {
107
- const result2 = await post(url, data, config);
108
- return { data: result2.data };
109
- }
110
- if (method === "DELETE") {
111
- const result2 = await del(url, config);
112
- return { data: result2.data };
113
- }
114
- if (method === "PUT") {
115
- const result2 = await put(url, data, config);
116
- return { data: result2.data };
117
- }
118
- const result = await get(url, config);
119
- return { data: result.data };
120
- } catch (error) {
121
- const err = error;
122
- return {
123
- error: {
124
- status: err.response?.status,
125
- code: err.code,
126
- response: {
127
- data: err.response?.data
128
- }
129
- }
130
- };
94
+ const extendInvalidatesTags = (endpoint, extraTags) => {
95
+ if (!endpoint) {
96
+ return;
131
97
  }
98
+ const originalInvalidatesTags = endpoint.invalidatesTags;
99
+ const newInvalidatesTags = (result, err, args, meta) => {
100
+ const originalTags = typeof originalInvalidatesTags === "function" ? originalInvalidatesTags(result, err, args, meta) : originalInvalidatesTags;
101
+ return [...originalTags ?? [], ...extraTags];
102
+ };
103
+ Object.assign(endpoint, { invalidatesTags: newInvalidatesTags });
132
104
  };
133
- const isAxiosError = (err) => {
134
- return typeof err === "object" && err !== null && "response" in err && typeof err.response === "object" && err.response !== null && "data" in err.response;
135
- };
136
- const releaseApi = createApi({
137
- reducerPath: pluginId,
138
- baseQuery: axiosBaseQuery,
139
- tagTypes: ["Release", "ReleaseAction", "EntriesInRelease"],
105
+ const releaseApi = adminApi.enhanceEndpoints({
106
+ addTagTypes: ["Release", "ReleaseAction", "EntriesInRelease", "ReleaseSettings", "Document"],
107
+ endpoints: {
108
+ updateDocument(endpoint) {
109
+ extendInvalidatesTags(endpoint, [
110
+ { type: "Release", id: "LIST" },
111
+ { type: "ReleaseAction", id: "LIST" }
112
+ ]);
113
+ },
114
+ deleteDocument(endpoint) {
115
+ extendInvalidatesTags(endpoint, [
116
+ { type: "Release", id: "LIST" },
117
+ { type: "ReleaseAction", id: "LIST" }
118
+ ]);
119
+ },
120
+ deleteManyDocuments(endpoint) {
121
+ extendInvalidatesTags(endpoint, [
122
+ { type: "Release", id: "LIST" },
123
+ { type: "ReleaseAction", id: "LIST" }
124
+ ]);
125
+ },
126
+ discardDocument(endpoint) {
127
+ extendInvalidatesTags(endpoint, [
128
+ { type: "Release", id: "LIST" },
129
+ { type: "ReleaseAction", id: "LIST" }
130
+ ]);
131
+ },
132
+ createWorkflow(endpoint) {
133
+ extendInvalidatesTags(endpoint, [
134
+ { type: "Release", id: "LIST" },
135
+ { type: "ReleaseAction", id: "LIST" }
136
+ ]);
137
+ },
138
+ updateWorkflow(endpoint) {
139
+ extendInvalidatesTags(endpoint, [
140
+ { type: "Release", id: "LIST" },
141
+ { type: "ReleaseAction", id: "LIST" }
142
+ ]);
143
+ },
144
+ deleteWorkflow(endpoint) {
145
+ extendInvalidatesTags(endpoint, [
146
+ { type: "Release", id: "LIST" },
147
+ { type: "ReleaseAction", id: "LIST" }
148
+ ]);
149
+ }
150
+ }
151
+ }).injectEndpoints({
140
152
  endpoints: (build) => {
141
153
  return {
142
154
  getReleasesForEntry: build.query({
143
155
  query(params) {
144
156
  return {
145
- url: "/content-releases",
157
+ url: "/content-releases/getByDocumentAttached",
146
158
  method: "GET",
147
159
  config: {
148
160
  params
@@ -204,7 +216,10 @@ const releaseApi = createApi({
204
216
  method: "GET"
205
217
  };
206
218
  },
207
- providesTags: (result, error, arg) => [{ type: "Release", id: arg.id }]
219
+ providesTags: (result, error, arg) => [
220
+ { type: "Release", id: "LIST" },
221
+ { type: "Release", id: arg.id }
222
+ ]
208
223
  }),
209
224
  getReleaseActions: build.query({
210
225
  query({ releaseId, ...params }) {
@@ -273,20 +288,28 @@ const releaseApi = createApi({
273
288
  data: body
274
289
  };
275
290
  },
276
- invalidatesTags: () => [{ type: "ReleaseAction", id: "LIST" }],
291
+ invalidatesTags: (res, error, arg) => [
292
+ { type: "ReleaseAction", id: "LIST" },
293
+ { type: "Release", id: "LIST" },
294
+ { type: "Release", id: arg.params.releaseId }
295
+ ],
277
296
  async onQueryStarted({ body, params, query, actionPath }, { dispatch, queryFulfilled }) {
278
297
  const paramsWithoutActionId = {
279
298
  releaseId: params.releaseId,
280
299
  ...query
281
300
  };
282
301
  const patchResult = dispatch(
283
- releaseApi.util.updateQueryData("getReleaseActions", paramsWithoutActionId, (draft) => {
284
- const [key, index] = actionPath;
285
- const action = draft.data[key][index];
286
- if (action) {
287
- action.type = body.type;
302
+ releaseApi.util.updateQueryData(
303
+ "getReleaseActions",
304
+ paramsWithoutActionId,
305
+ (draft) => {
306
+ const [key, index] = actionPath;
307
+ const action = draft.data[key][index];
308
+ if (action) {
309
+ action.type = body.type;
310
+ }
288
311
  }
289
- })
312
+ )
290
313
  );
291
314
  try {
292
315
  await queryFulfilled;
@@ -316,7 +339,10 @@ const releaseApi = createApi({
316
339
  method: "POST"
317
340
  };
318
341
  },
319
- invalidatesTags: (result, error, arg) => [{ type: "Release", id: arg.id }]
342
+ invalidatesTags: (result, error, arg) => [
343
+ { type: "Release", id: arg.id },
344
+ { type: "Document", id: `ALL_LIST` }
345
+ ]
320
346
  }),
321
347
  deleteRelease: build.mutation({
322
348
  query({ id }) {
@@ -341,6 +367,20 @@ const releaseApi = createApi({
341
367
  return response.data;
342
368
  },
343
369
  providesTags: [{ type: "EntriesInRelease" }]
370
+ }),
371
+ getReleaseSettings: build.query({
372
+ query: () => "/content-releases/settings",
373
+ providesTags: [{ type: "ReleaseSettings" }]
374
+ }),
375
+ updateReleaseSettings: build.mutation({
376
+ query(data) {
377
+ return {
378
+ url: "/content-releases/settings",
379
+ method: "PUT",
380
+ data
381
+ };
382
+ },
383
+ invalidatesTags: [{ type: "ReleaseSettings" }]
344
384
  })
345
385
  };
346
386
  }
@@ -358,199 +398,21 @@ const {
358
398
  usePublishReleaseMutation,
359
399
  useDeleteReleaseActionMutation,
360
400
  useDeleteReleaseMutation,
361
- useGetMappedEntriesInReleasesQuery
401
+ useGetMappedEntriesInReleasesQuery,
402
+ useGetReleaseSettingsQuery,
403
+ useUpdateReleaseSettingsMutation
362
404
  } = releaseApi;
363
- const getTimezoneOffset = (timezone, date) => {
364
- try {
365
- const offsetPart = new Intl.DateTimeFormat("en", {
366
- timeZone: timezone,
367
- timeZoneName: "longOffset"
368
- }).formatToParts(date).find((part) => part.type === "timeZoneName");
369
- const offset = offsetPart ? offsetPart.value : "";
370
- let utcOffset = offset.replace("GMT", "UTC");
371
- if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
372
- utcOffset = `${utcOffset}+00:00`;
373
- }
374
- return utcOffset;
375
- } catch (error) {
376
- return "";
377
- }
378
- };
379
- const StyledMenuItem = styled(Menu.Item)`
380
- &:hover {
381
- background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
382
-
383
- svg {
384
- fill: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}600`]};
385
- }
386
-
387
- a {
388
- color: ${({ theme }) => theme.colors.neutral800};
389
- }
390
- }
391
-
392
- svg {
393
- fill: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}600`]};
394
- }
395
-
396
- a {
397
- color: ${({ theme }) => theme.colors.neutral800};
398
- }
399
-
400
- span,
401
- a {
402
- width: 100%;
403
- }
404
- `;
405
- const StyledIconButton = styled(IconButton)`
406
- /* Setting this style inline with borderColor will not apply the style */
407
- border: ${({ theme }) => `1px solid ${theme.colors.neutral200}`};
408
- `;
409
- const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
410
- const { formatMessage } = useIntl();
411
- const { toggleNotification } = useNotification();
412
- const { formatAPIError } = useAPIErrorHandler();
413
- const [deleteReleaseAction] = useDeleteReleaseActionMutation();
414
- const {
415
- allowedActions: { canDeleteAction }
416
- } = useRBAC(PERMISSIONS);
417
- const handleDeleteAction = async () => {
418
- const response = await deleteReleaseAction({
419
- params: { releaseId, actionId }
420
- });
421
- if ("data" in response) {
422
- toggleNotification({
423
- type: "success",
424
- message: formatMessage({
425
- id: "content-releases.content-manager-edit-view.remove-from-release.notification.success",
426
- defaultMessage: "Entry removed from release"
427
- })
428
- });
429
- return;
430
- }
431
- if ("error" in response) {
432
- if (isAxiosError$1(response.error)) {
433
- toggleNotification({
434
- type: "danger",
435
- message: formatAPIError(response.error)
436
- });
437
- } else {
438
- toggleNotification({
439
- type: "danger",
440
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
441
- });
442
- }
443
- }
444
- };
445
- if (!canDeleteAction) {
446
- return null;
447
- }
448
- return /* @__PURE__ */ jsx(StyledMenuItem, { variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
449
- /* @__PURE__ */ jsx(Cross, { width: "1.6rem", height: "1.6rem" }),
450
- /* @__PURE__ */ jsx(Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
451
- id: "content-releases.content-manager-edit-view.remove-from-release",
452
- defaultMessage: "Remove from release"
453
- }) })
454
- ] }) });
455
- };
456
- const ReleaseActionEntryLinkItem = ({
457
- contentTypeUid,
458
- entryId,
459
- locale
460
- }) => {
461
- const { formatMessage } = useIntl();
462
- const userPermissions = useAuth("ReleaseActionEntryLinkItem", (state) => state.permissions);
463
- const canUpdateEntryForLocale = React.useMemo(() => {
464
- const updatePermissions = userPermissions.find(
465
- (permission) => permission.subject === contentTypeUid && permission.action === "plugin::content-manager.explorer.update"
466
- );
467
- if (!updatePermissions) {
468
- return false;
469
- }
470
- return Boolean(!locale || updatePermissions.properties?.locales?.includes(locale));
471
- }, [contentTypeUid, locale, userPermissions]);
472
- const {
473
- allowedActions: { canUpdate: canUpdateContentType }
474
- } = useRBAC({
475
- updateContentType: [
476
- {
477
- action: "plugin::content-manager.explorer.update",
478
- subject: contentTypeUid
479
- }
480
- ]
481
- });
482
- if (!canUpdateContentType || !canUpdateEntryForLocale) {
483
- return null;
484
- }
485
- return /* @__PURE__ */ jsx(
486
- StyledMenuItem,
487
- {
488
- forwardedAs: Link,
489
- isLink: true,
490
- to: {
491
- pathname: `/content-manager/collection-types/${contentTypeUid}/${entryId}`,
492
- search: locale && `?plugins[i18n][locale]=${locale}`
493
- },
494
- children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
495
- /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
496
- /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
497
- id: "content-releases.content-manager-edit-view.edit-entry",
498
- defaultMessage: "Edit entry"
499
- }) })
500
- ] })
501
- }
502
- );
503
- };
504
- const EditReleaseItem = ({ releaseId }) => {
505
- const { formatMessage } = useIntl();
506
- return /* @__PURE__ */ jsx(StyledMenuItem, { forwardedAs: Link, isLink: true, to: `/plugins/content-releases/${releaseId}`, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
507
- /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
508
- /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
509
- id: "content-releases.content-manager-edit-view.edit-release",
510
- defaultMessage: "Edit release"
511
- }) })
512
- ] }) });
513
- };
514
- const Root = ({ children, hasTriggerBorder = false }) => {
515
- const { formatMessage } = useIntl();
516
- const { allowedActions } = useRBAC(PERMISSIONS);
517
- return (
518
- // A user can access the dropdown if they have permissions to delete a release-action OR update a release
519
- allowedActions.canDeleteAction || allowedActions.canUpdate ? /* @__PURE__ */ jsxs(Menu.Root, { children: [
520
- /* @__PURE__ */ jsx(
521
- Menu.Trigger,
522
- {
523
- as: hasTriggerBorder ? StyledIconButton : IconButton,
524
- paddingLeft: 2,
525
- paddingRight: 2,
526
- "aria-label": formatMessage({
527
- id: "content-releases.content-manager-edit-view.release-action-menu",
528
- defaultMessage: "Release action options"
529
- }),
530
- icon: /* @__PURE__ */ jsx(More, {})
531
- }
532
- ),
533
- /* @__PURE__ */ jsx(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
534
- ] }) : null
535
- );
536
- };
537
- const ReleaseActionMenu = {
538
- Root,
539
- EditReleaseItem,
540
- DeleteReleaseActionItem,
541
- ReleaseActionEntryLinkItem
542
- };
543
405
  const getBorderLeftRadiusValue = (actionType) => {
544
406
  return actionType === "publish" ? 1 : 0;
545
407
  };
546
408
  const getBorderRightRadiusValue = (actionType) => {
547
409
  return actionType === "publish" ? 0 : 1;
548
410
  };
549
- const FieldWrapper = styled(Field)`
550
- border-top-left-radius: ${({ actionType, theme }) => theme.spaces[getBorderLeftRadiusValue(actionType)]};
551
- border-bottom-left-radius: ${({ actionType, theme }) => theme.spaces[getBorderLeftRadiusValue(actionType)]};
552
- border-top-right-radius: ${({ actionType, theme }) => theme.spaces[getBorderRightRadiusValue(actionType)]};
553
- border-bottom-right-radius: ${({ actionType, theme }) => theme.spaces[getBorderRightRadiusValue(actionType)]};
411
+ const FieldWrapper = styled(Field.Root)`
412
+ border-top-left-radius: ${({ $actionType, theme }) => theme.spaces[getBorderLeftRadiusValue($actionType)]};
413
+ border-bottom-left-radius: ${({ $actionType, theme }) => theme.spaces[getBorderLeftRadiusValue($actionType)]};
414
+ border-top-right-radius: ${({ $actionType, theme }) => theme.spaces[getBorderRightRadiusValue($actionType)]};
415
+ border-bottom-right-radius: ${({ $actionType, theme }) => theme.spaces[getBorderRightRadiusValue($actionType)]};
554
416
 
555
417
  > label {
556
418
  color: inherit;
@@ -561,14 +423,14 @@ const FieldWrapper = styled(Field)`
561
423
  }
562
424
 
563
425
  &[data-checked='true'] {
564
- color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
565
- background-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary100 : theme.colors.danger100};
566
- border-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
426
+ color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
427
+ background-color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary100 : theme.colors.danger100};
428
+ border-color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
567
429
  }
568
430
 
569
431
  &[data-checked='false'] {
570
- border-left: ${({ actionType }) => actionType === "unpublish" && "none"};
571
- border-right: ${({ actionType }) => actionType === "publish" && "none"};
432
+ border-left: ${({ $actionType }) => $actionType === "unpublish" && "none"};
433
+ border-right: ${({ $actionType }) => $actionType === "publish" && "none"};
572
434
  }
573
435
 
574
436
  &[data-checked='false'][data-disabled='false']:hover {
@@ -597,7 +459,7 @@ const ActionOption = ({
597
459
  return /* @__PURE__ */ jsx(
598
460
  FieldWrapper,
599
461
  {
600
- actionType,
462
+ $actionType: actionType,
601
463
  background: "primary0",
602
464
  borderColor: "neutral200",
603
465
  color: selected === actionType ? "primary600" : "neutral600",
@@ -605,12 +467,11 @@ const ActionOption = ({
605
467
  cursor: "pointer",
606
468
  "data-checked": selected === actionType,
607
469
  "data-disabled": disabled && selected !== actionType,
608
- children: /* @__PURE__ */ jsxs(FieldLabel, { htmlFor: `${name}-${actionType}`, children: [
470
+ children: /* @__PURE__ */ jsxs(Field.Label, { children: [
609
471
  /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx(
610
- FieldInput,
472
+ Field.Input,
611
473
  {
612
474
  type: "radio",
613
- id: `${name}-${actionType}`,
614
475
  name,
615
476
  checked: selected === actionType,
616
477
  onChange: handleChange,
@@ -676,302 +537,192 @@ const NoReleases = () => {
676
537
  to: {
677
538
  pathname: "/plugins/content-releases"
678
539
  },
679
- as: Link,
540
+ tag: Link,
680
541
  variant: "secondary",
681
542
  children: formatMessage({
682
543
  id: "content-releases.content-manager-edit-view.add-to-release.redirect-button",
683
544
  defaultMessage: "Open the list of releases"
684
545
  })
685
546
  }
686
- )
547
+ ),
548
+ shadow: "none"
687
549
  }
688
550
  );
689
551
  };
690
552
  const AddActionToReleaseModal = ({
691
- handleClose,
692
- contentTypeUid,
693
- entryId
553
+ contentType,
554
+ documentId,
555
+ onInputChange,
556
+ values
694
557
  }) => {
695
- const releaseHeaderId = React.useId();
696
558
  const { formatMessage } = useIntl();
697
- const { toggleNotification } = useNotification();
698
- const { formatAPIError } = useAPIErrorHandler();
699
559
  const [{ query }] = useQueryParams();
700
560
  const locale = query.plugins?.i18n?.locale;
701
561
  const response = useGetReleasesForEntryQuery({
702
- contentTypeUid,
703
- entryId,
704
- hasEntryAttached: false
562
+ contentType,
563
+ entryDocumentId: documentId,
564
+ hasEntryAttached: false,
565
+ locale
705
566
  });
706
567
  const releases = response.data?.data;
568
+ if (releases?.length === 0) {
569
+ return /* @__PURE__ */ jsx(NoReleases, {});
570
+ }
571
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
572
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxs(Field.Root, { required: true, children: [
573
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
574
+ id: "content-releases.content-manager-edit-view.add-to-release.select-label",
575
+ defaultMessage: "Select a release"
576
+ }) }),
577
+ /* @__PURE__ */ jsx(
578
+ SingleSelect,
579
+ {
580
+ required: true,
581
+ placeholder: formatMessage({
582
+ id: "content-releases.content-manager-edit-view.add-to-release.select-placeholder",
583
+ defaultMessage: "Select"
584
+ }),
585
+ name: "releaseId",
586
+ onChange: (value) => onInputChange("releaseId", value),
587
+ value: values.releaseId,
588
+ children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
589
+ }
590
+ )
591
+ ] }) }),
592
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
593
+ id: "content-releases.content-manager-edit-view.add-to-release.action-type-label",
594
+ defaultMessage: "What do you want to do with this entry?"
595
+ }) }),
596
+ /* @__PURE__ */ jsx(
597
+ ReleaseActionOptions,
598
+ {
599
+ selected: values.type,
600
+ handleChange: (e) => onInputChange("type", e.target.value),
601
+ name: "type"
602
+ }
603
+ )
604
+ ] });
605
+ };
606
+ const ReleaseActionModalForm = ({
607
+ documentId,
608
+ document,
609
+ model,
610
+ collectionType
611
+ }) => {
612
+ const { formatMessage } = useIntl();
613
+ const { allowedActions } = useRBAC(PERMISSIONS);
614
+ const { canCreateAction } = allowedActions;
707
615
  const [createReleaseAction, { isLoading }] = useCreateReleaseActionMutation();
708
- const handleSubmit = async (values) => {
709
- const releaseActionEntry = {
710
- contentType: contentTypeUid,
711
- id: entryId,
712
- locale
713
- };
714
- const response2 = await createReleaseAction({
715
- body: { type: values.type, entry: releaseActionEntry },
716
- params: { releaseId: values.releaseId }
717
- });
718
- if ("data" in response2) {
719
- toggleNotification({
720
- type: "success",
721
- message: formatMessage({
722
- id: "content-releases.content-manager-edit-view.add-to-release.notification.success",
723
- defaultMessage: "Entry added to release"
724
- })
725
- });
726
- handleClose();
727
- return;
728
- }
729
- if ("error" in response2) {
730
- if (isAxiosError$1(response2.error)) {
616
+ const { toggleNotification } = useNotification();
617
+ const { formatAPIError } = useAPIErrorHandler();
618
+ const [{ query }] = useQueryParams();
619
+ const locale = query.plugins?.i18n?.locale;
620
+ const handleSubmit = async (e, onClose) => {
621
+ try {
622
+ await formik.handleSubmit(e);
623
+ onClose();
624
+ } catch (error) {
625
+ if (isFetchError(error)) {
731
626
  toggleNotification({
732
627
  type: "danger",
733
- message: formatAPIError(response2.error)
628
+ message: formatAPIError(error)
734
629
  });
735
630
  } else {
736
631
  toggleNotification({
737
632
  type: "danger",
738
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
633
+ message: formatMessage({
634
+ id: "notification.error",
635
+ defaultMessage: "An error occurred"
636
+ })
739
637
  });
740
638
  }
741
639
  }
742
640
  };
743
- return /* @__PURE__ */ jsxs(ModalLayout, { onClose: handleClose, labelledBy: releaseHeaderId, children: [
744
- /* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { id: releaseHeaderId, fontWeight: "bold", textColor: "neutral800", children: formatMessage({
641
+ const formik = useFormik({
642
+ initialValues: INITIAL_VALUES,
643
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
644
+ onSubmit: async (values) => {
645
+ if (collectionType === "collection-types" && !documentId) {
646
+ throw new Error("Document id is required");
647
+ }
648
+ const response = await createReleaseAction({
649
+ body: {
650
+ type: values.type,
651
+ contentType: model,
652
+ entryDocumentId: documentId,
653
+ locale
654
+ },
655
+ params: { releaseId: values.releaseId }
656
+ });
657
+ if ("data" in response) {
658
+ toggleNotification({
659
+ type: "success",
660
+ message: formatMessage({
661
+ id: "content-releases.content-manager-edit-view.add-to-release.notification.success",
662
+ defaultMessage: "Entry added to release"
663
+ })
664
+ });
665
+ return;
666
+ }
667
+ if ("error" in response) {
668
+ throw response.error;
669
+ }
670
+ }
671
+ });
672
+ const {
673
+ edit: { options }
674
+ } = unstable_useDocumentLayout(model);
675
+ if (!window.strapi.isEE || !options?.draftAndPublish || !canCreateAction) {
676
+ return null;
677
+ }
678
+ if (collectionType === "collection-types" && (!documentId || documentId === "create")) {
679
+ return null;
680
+ }
681
+ return {
682
+ label: formatMessage({
745
683
  id: "content-releases.content-manager-edit-view.add-to-release",
746
684
  defaultMessage: "Add to release"
747
- }) }) }),
748
- /* @__PURE__ */ jsx(
749
- Formik,
750
- {
751
- onSubmit: handleSubmit,
752
- validationSchema: RELEASE_ACTION_FORM_SCHEMA,
753
- initialValues: INITIAL_VALUES,
754
- children: ({ values, setFieldValue }) => {
755
- return /* @__PURE__ */ jsxs(Form, { children: [
756
- releases?.length === 0 ? /* @__PURE__ */ jsx(NoReleases, {}) : /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
757
- /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsx(
758
- SingleSelect,
759
- {
760
- required: true,
761
- label: formatMessage({
762
- id: "content-releases.content-manager-edit-view.add-to-release.select-label",
763
- defaultMessage: "Select a release"
764
- }),
765
- placeholder: formatMessage({
766
- id: "content-releases.content-manager-edit-view.add-to-release.select-placeholder",
767
- defaultMessage: "Select"
768
- }),
769
- onChange: (value) => setFieldValue("releaseId", value),
770
- value: values.releaseId,
771
- children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
772
- }
773
- ) }),
774
- /* @__PURE__ */ jsx(FieldLabel, { children: formatMessage({
775
- id: "content-releases.content-manager-edit-view.add-to-release.action-type-label",
776
- defaultMessage: "What do you want to do with this entry?"
777
- }) }),
778
- /* @__PURE__ */ jsx(
779
- ReleaseActionOptions,
780
- {
781
- selected: values.type,
782
- handleChange: (e) => setFieldValue("type", e.target.value),
783
- name: "type"
784
- }
785
- )
786
- ] }) }),
787
- /* @__PURE__ */ jsx(
788
- ModalFooter,
789
- {
790
- startActions: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({
791
- id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
792
- defaultMessage: "Cancel"
793
- }) }),
794
- endActions: (
795
- /**
796
- * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
797
- * for yup.string().required(), even when the value is falsy (including empty string)
798
- */
799
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
800
- id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
801
- defaultMessage: "Continue"
802
- }) })
803
- )
804
- }
805
- )
806
- ] });
807
- }
808
- }
809
- )
810
- ] });
811
- };
812
- const CMReleasesContainer = () => {
813
- const [isModalOpen, setIsModalOpen] = React.useState(false);
814
- const { formatMessage, formatDate, formatTime } = useIntl();
815
- const { id, slug, collectionType } = useParams();
816
- const isCreatingEntry = id === "create";
817
- const entryId = parseInt(id, 10);
818
- const { allowedActions } = useRBAC(PERMISSIONS);
819
- const { canCreateAction, canRead: canMain, canDeleteAction } = allowedActions;
820
- const { schema } = unstable_useDocument({
821
- collectionType,
822
- model: slug
823
- });
824
- const hasDraftAndPublish = schema?.options?.draftAndPublish;
825
- const contentTypeUid = slug;
826
- const canFetch = id != null && contentTypeUid != null;
827
- const fetchParams = canFetch ? {
828
- contentTypeUid,
829
- entryId,
830
- hasEntryAttached: true
831
- } : skipToken;
832
- const response = useGetReleasesForEntryQuery(fetchParams);
833
- const releases = response.data?.data;
834
- if (!canFetch) {
835
- return null;
836
- }
837
- if (isCreatingEntry || !hasDraftAndPublish) {
838
- return null;
839
- }
840
- const toggleModal = () => setIsModalOpen((prev) => !prev);
841
- const getReleaseColorVariant = (actionType, shade) => {
842
- if (actionType === "unpublish") {
843
- return `secondary${shade}`;
844
- }
845
- return `success${shade}`;
846
- };
847
- if (!canMain) {
848
- return null;
849
- }
850
- return /* @__PURE__ */ jsxs(
851
- Box,
852
- {
853
- as: "aside",
854
- "aria-label": formatMessage({
855
- id: "content-releases.plugin.name",
856
- defaultMessage: "Releases"
685
+ }),
686
+ icon: /* @__PURE__ */ jsx(PaperPlane, {}),
687
+ // Entry is creating so we don't want to allow adding it to a release
688
+ disabled: !document,
689
+ position: ["panel", "table-row"],
690
+ dialog: {
691
+ type: "modal",
692
+ title: formatMessage({
693
+ id: "content-releases.content-manager-edit-view.add-to-release",
694
+ defaultMessage: "Add to release"
857
695
  }),
858
- background: "neutral0",
859
- borderColor: "neutral150",
860
- hasRadius: true,
861
- padding: 4,
862
- shadow: "tableShadow",
863
- children: [
864
- /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
865
- /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", children: formatMessage({
866
- id: "content-releases.plugin.name",
867
- defaultMessage: "Releases"
868
- }) }),
869
- releases?.map((release) => {
870
- return /* @__PURE__ */ jsxs(
871
- Flex,
872
- {
873
- direction: "column",
874
- alignItems: "start",
875
- borderWidth: "1px",
876
- borderStyle: "solid",
877
- borderColor: getReleaseColorVariant(release.actions[0].type, "200"),
878
- overflow: "hidden",
879
- hasRadius: true,
880
- children: [
881
- /* @__PURE__ */ jsx(
882
- Box,
883
- {
884
- paddingTop: 3,
885
- paddingBottom: 3,
886
- paddingLeft: 4,
887
- paddingRight: 4,
888
- background: getReleaseColorVariant(release.actions[0].type, "100"),
889
- width: "100%",
890
- children: /* @__PURE__ */ jsx(
891
- Typography,
892
- {
893
- fontSize: 1,
894
- variant: "pi",
895
- textColor: getReleaseColorVariant(release.actions[0].type, "600"),
896
- children: formatMessage(
897
- {
898
- id: "content-releases.content-manager-edit-view.list-releases.title",
899
- defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
900
- },
901
- { isPublish: release.actions[0].type === "publish" }
902
- )
903
- }
904
- )
905
- }
906
- ),
907
- /* @__PURE__ */ jsx(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
908
- /* @__PURE__ */ jsx(Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
909
- release.scheduledAt && release.timezone && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
910
- {
911
- id: "content-releases.content-manager-edit-view.scheduled.date",
912
- defaultMessage: "{date} at {time} ({offset})"
913
- },
914
- {
915
- date: formatDate(new Date(release.scheduledAt), {
916
- day: "2-digit",
917
- month: "2-digit",
918
- year: "numeric",
919
- timeZone: release.timezone
920
- }),
921
- time: formatTime(new Date(release.scheduledAt), {
922
- hourCycle: "h23",
923
- timeZone: release.timezone
924
- }),
925
- offset: getTimezoneOffset(
926
- release.timezone,
927
- new Date(release.scheduledAt)
928
- )
929
- }
930
- ) }),
931
- canDeleteAction ? /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
932
- /* @__PURE__ */ jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
933
- /* @__PURE__ */ jsx(
934
- ReleaseActionMenu.DeleteReleaseActionItem,
935
- {
936
- releaseId: release.id,
937
- actionId: release.actions[0].id
938
- }
939
- )
940
- ] }) : null
941
- ] }) })
942
- ]
943
- },
944
- release.id
945
- );
946
- }),
947
- canCreateAction ? /* @__PURE__ */ jsx(
948
- Button,
949
- {
950
- justifyContent: "center",
951
- paddingLeft: 4,
952
- paddingRight: 4,
953
- color: "neutral700",
954
- variant: "tertiary",
955
- startIcon: /* @__PURE__ */ jsx(Plus, {}),
956
- onClick: toggleModal,
957
- children: formatMessage({
958
- id: "content-releases.content-manager-edit-view.add-to-release",
959
- defaultMessage: "Add to release"
960
- })
961
- }
962
- ) : null
963
- ] }),
964
- isModalOpen && /* @__PURE__ */ jsx(
965
- AddActionToReleaseModal,
696
+ content: /* @__PURE__ */ jsx(
697
+ AddActionToReleaseModal,
698
+ {
699
+ contentType: model,
700
+ documentId,
701
+ onInputChange: formik.setFieldValue,
702
+ values: formik.values
703
+ }
704
+ ),
705
+ footer: ({ onClose }) => /* @__PURE__ */ jsxs(Modal.Footer, { children: [
706
+ /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
707
+ id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
708
+ defaultMessage: "Cancel"
709
+ }) }),
710
+ /* @__PURE__ */ jsx(
711
+ Button,
966
712
  {
967
- handleClose: toggleModal,
968
- contentTypeUid,
969
- entryId
713
+ type: "submit",
714
+ onClick: (e) => handleSubmit(e, onClose),
715
+ disabled: !formik.values.releaseId,
716
+ loading: isLoading,
717
+ children: formatMessage({
718
+ id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
719
+ defaultMessage: "Continue"
720
+ })
970
721
  }
971
722
  )
972
- ]
723
+ ] })
973
724
  }
974
- );
725
+ };
975
726
  };
976
727
  const getContentPermissions = (subject) => {
977
728
  const permissions = {
@@ -988,7 +739,7 @@ const getContentPermissions = (subject) => {
988
739
  };
989
740
  return permissions;
990
741
  };
991
- const ReleaseAction = ({ documentIds, model }) => {
742
+ const ReleaseAction = ({ documents, model }) => {
992
743
  const { formatMessage } = useIntl();
993
744
  const { toggleNotification } = useNotification();
994
745
  const { formatAPIError } = useAPIErrorHandler();
@@ -1003,16 +754,15 @@ const ReleaseAction = ({ documentIds, model }) => {
1003
754
  const response = useGetReleasesQuery();
1004
755
  const releases = response.data?.data;
1005
756
  const [createManyReleaseActions, { isLoading }] = useCreateManyReleaseActionsMutation();
757
+ const documentIds = documents.map((doc) => doc.documentId);
1006
758
  const handleSubmit = async (values) => {
1007
759
  const locale = query.plugins?.i18n?.locale;
1008
760
  const releaseActionEntries = documentIds.map(
1009
- (id) => ({
761
+ (entryDocumentId) => ({
1010
762
  type: values.type,
1011
- entry: {
1012
- contentType: model,
1013
- id,
1014
- locale
1015
- }
763
+ contentType: model,
764
+ entryDocumentId,
765
+ locale
1016
766
  })
1017
767
  );
1018
768
  const response2 = await createManyReleaseActions({
@@ -1048,7 +798,7 @@ const ReleaseAction = ({ documentIds, model }) => {
1048
798
  return true;
1049
799
  }
1050
800
  if ("error" in response2) {
1051
- if (isAxiosError$1(response2.error)) {
801
+ if (isFetchError(response2.error)) {
1052
802
  toggleNotification({
1053
803
  type: "warning",
1054
804
  message: formatAPIError(response2.error)
@@ -1089,25 +839,26 @@ const ReleaseAction = ({ documentIds, model }) => {
1089
839
  validationSchema: RELEASE_ACTION_FORM_SCHEMA,
1090
840
  initialValues: INITIAL_VALUES,
1091
841
  children: ({ values, setFieldValue }) => /* @__PURE__ */ jsxs(Form, { children: [
1092
- releases?.length === 0 ? /* @__PURE__ */ jsx(NoReleases, {}) : /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
1093
- /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsx(
1094
- SingleSelect,
1095
- {
1096
- required: true,
1097
- label: formatMessage({
1098
- id: "content-releases.content-manager-list-view.add-to-release.select-label",
1099
- defaultMessage: "Select a release"
1100
- }),
1101
- placeholder: formatMessage({
1102
- id: "content-releases.content-manager-list-view.add-to-release.select-placeholder",
1103
- defaultMessage: "Select"
1104
- }),
1105
- onChange: (value) => setFieldValue("releaseId", value),
1106
- value: values.releaseId,
1107
- children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
1108
- }
1109
- ) }),
1110
- /* @__PURE__ */ jsx(FieldLabel, { children: formatMessage({
842
+ releases?.length === 0 ? /* @__PURE__ */ jsx(NoReleases, {}) : /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
843
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxs(Field.Root, { required: true, children: [
844
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
845
+ id: "content-releases.content-manager-list-view.add-to-release.select-label",
846
+ defaultMessage: "Select a release"
847
+ }) }),
848
+ /* @__PURE__ */ jsx(
849
+ SingleSelect,
850
+ {
851
+ placeholder: formatMessage({
852
+ id: "content-releases.content-manager-list-view.add-to-release.select-placeholder",
853
+ defaultMessage: "Select"
854
+ }),
855
+ onChange: (value) => setFieldValue("releaseId", value),
856
+ value: values.releaseId,
857
+ children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
858
+ }
859
+ )
860
+ ] }) }),
861
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
1111
862
  id: "content-releases.content-manager-list-view.add-to-release.action-type-label",
1112
863
  defaultMessage: "What do you want to do with these entries?"
1113
864
  }) }),
@@ -1120,25 +871,16 @@ const ReleaseAction = ({ documentIds, model }) => {
1120
871
  }
1121
872
  )
1122
873
  ] }) }),
1123
- /* @__PURE__ */ jsx(
1124
- ModalFooter,
1125
- {
1126
- startActions: /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
1127
- id: "content-releases.content-manager-list-view.add-to-release.cancel-button",
1128
- defaultMessage: "Cancel"
1129
- }) }),
1130
- endActions: (
1131
- /**
1132
- * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
1133
- * for yup.string().required(), even when the value is falsy (including empty string)
1134
- */
1135
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
1136
- id: "content-releases.content-manager-list-view.add-to-release.continue-button",
1137
- defaultMessage: "Continue"
1138
- }) })
1139
- )
1140
- }
1141
- )
874
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
875
+ /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
876
+ id: "content-releases.content-manager-list-view.add-to-release.cancel-button",
877
+ defaultMessage: "Cancel"
878
+ }) }),
879
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
880
+ id: "content-releases.content-manager-list-view.add-to-release.continue-button",
881
+ defaultMessage: "Continue"
882
+ }) })
883
+ ] })
1142
884
  ] })
1143
885
  }
1144
886
  );
@@ -1146,10 +888,386 @@ const ReleaseAction = ({ documentIds, model }) => {
1146
888
  }
1147
889
  };
1148
890
  };
1149
- const prefixPluginTranslations = (trad, pluginId2) => {
1150
- if (!pluginId2) {
1151
- throw new TypeError("pluginId can't be empty");
891
+ const useReleasesList = (contentTypeUid, documentId) => {
892
+ const listViewData = useTable("ListView", (state) => state.rows);
893
+ const documentIds = listViewData.map((entry) => entry.documentId);
894
+ const [{ query }] = useQueryParams();
895
+ const locale = query?.plugins?.i18n?.locale || void 0;
896
+ const response = useGetMappedEntriesInReleasesQuery(
897
+ { contentTypeUid, documentIds, locale },
898
+ { skip: !documentIds || !contentTypeUid || documentIds.length === 0 }
899
+ );
900
+ const mappedEntriesInReleases = response.data || {};
901
+ return mappedEntriesInReleases?.[documentId] || [];
902
+ };
903
+ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
904
+ const { options } = layout;
905
+ if (!options?.draftAndPublish) {
906
+ return { displayedHeaders, layout };
907
+ }
908
+ return {
909
+ displayedHeaders: [
910
+ ...displayedHeaders,
911
+ {
912
+ searchable: false,
913
+ sortable: false,
914
+ name: "releases",
915
+ label: {
916
+ id: "content-releases.content-manager.list-view.releases.header",
917
+ defaultMessage: "To be released in"
918
+ },
919
+ cellFormatter: (props, _, { model }) => /* @__PURE__ */ jsx(ReleaseListCell, { ...props, model })
920
+ }
921
+ ],
922
+ layout
923
+ };
924
+ };
925
+ const ReleaseListCell = ({ documentId, model }) => {
926
+ const releases = useReleasesList(model, documentId);
927
+ const { formatMessage } = useIntl();
928
+ return /* @__PURE__ */ jsxs(Popover.Root, { children: [
929
+ /* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(
930
+ Button,
931
+ {
932
+ variant: "ghost",
933
+ onClick: (e) => e.stopPropagation(),
934
+ endIcon: releases.length > 0 ? /* @__PURE__ */ jsx(CaretDown, { width: "1.2rem", height: "1.2rem" }) : null,
935
+ children: /* @__PURE__ */ jsx(
936
+ Typography,
937
+ {
938
+ style: { maxWidth: "252px", cursor: "pointer" },
939
+ textColor: "neutral800",
940
+ fontWeight: "regular",
941
+ children: releases.length > 0 ? formatMessage(
942
+ {
943
+ id: "content-releases.content-manager.list-view.releases-number",
944
+ defaultMessage: "{number} {number, plural, one {release} other {releases}}"
945
+ },
946
+ {
947
+ number: releases.length
948
+ }
949
+ ) : "-"
950
+ }
951
+ )
952
+ }
953
+ ) }),
954
+ /* @__PURE__ */ jsx(Popover.Content, { children: /* @__PURE__ */ jsx("ul", { children: releases.map(({ id, name }) => /* @__PURE__ */ jsx(Box, { padding: 3, tag: "li", children: /* @__PURE__ */ jsx(Link$1, { href: `/admin/plugins/content-releases/${id}`, isExternal: false, children: name }) }, id)) }) })
955
+ ] });
956
+ };
957
+ const getTimezoneOffset = (timezone, date) => {
958
+ try {
959
+ const offsetPart = new Intl.DateTimeFormat("en", {
960
+ timeZone: timezone,
961
+ timeZoneName: "longOffset"
962
+ }).formatToParts(date).find((part) => part.type === "timeZoneName");
963
+ const offset = offsetPart ? offsetPart.value : "";
964
+ let utcOffset = offset.replace("GMT", "UTC");
965
+ if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
966
+ utcOffset = `${utcOffset}+00:00`;
967
+ }
968
+ return utcOffset;
969
+ } catch (error) {
970
+ return "";
971
+ }
972
+ };
973
+ const getTimezones = (selectedDate) => {
974
+ const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
975
+ const utcOffset = getTimezoneOffset(timezone, selectedDate);
976
+ return { offset: utcOffset, value: `${utcOffset}&${timezone}` };
977
+ });
978
+ const systemTimezone = timezoneList.find(
979
+ (timezone) => timezone.value.split("&")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
980
+ );
981
+ return { timezoneList, systemTimezone };
982
+ };
983
+ const StyledMenuItem = styled(Menu.Item)`
984
+ &:hover {
985
+ background: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}100`]};
986
+
987
+ svg {
988
+ fill: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}600`]};
989
+ }
990
+
991
+ a {
992
+ color: ${({ theme }) => theme.colors.neutral800};
993
+ }
994
+ }
995
+
996
+ svg {
997
+ color: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}500`]};
998
+ }
999
+
1000
+ span {
1001
+ color: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}800`]};
1002
+ }
1003
+
1004
+ span,
1005
+ a {
1006
+ width: 100%;
1152
1007
  }
1008
+ `;
1009
+ const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
1010
+ const { formatMessage } = useIntl();
1011
+ const { toggleNotification } = useNotification();
1012
+ const { formatAPIError } = useAPIErrorHandler();
1013
+ const [deleteReleaseAction] = useDeleteReleaseActionMutation();
1014
+ const {
1015
+ allowedActions: { canDeleteAction }
1016
+ } = useRBAC(PERMISSIONS);
1017
+ const handleDeleteAction = async () => {
1018
+ const response = await deleteReleaseAction({
1019
+ params: { releaseId, actionId }
1020
+ });
1021
+ if ("data" in response) {
1022
+ toggleNotification({
1023
+ type: "success",
1024
+ message: formatMessage({
1025
+ id: "content-releases.content-manager-edit-view.remove-from-release.notification.success",
1026
+ defaultMessage: "Entry removed from release"
1027
+ })
1028
+ });
1029
+ return;
1030
+ }
1031
+ if ("error" in response) {
1032
+ if (isFetchError(response.error)) {
1033
+ toggleNotification({
1034
+ type: "danger",
1035
+ message: formatAPIError(response.error)
1036
+ });
1037
+ } else {
1038
+ toggleNotification({
1039
+ type: "danger",
1040
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1041
+ });
1042
+ }
1043
+ }
1044
+ };
1045
+ if (!canDeleteAction) {
1046
+ return null;
1047
+ }
1048
+ return /* @__PURE__ */ jsx(StyledMenuItem, { $variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1049
+ /* @__PURE__ */ jsx(Cross, { width: "1.6rem", height: "1.6rem" }),
1050
+ /* @__PURE__ */ jsx(Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
1051
+ id: "content-releases.content-manager-edit-view.remove-from-release",
1052
+ defaultMessage: "Remove from release"
1053
+ }) })
1054
+ ] }) });
1055
+ };
1056
+ const ReleaseActionEntryLinkItem = ({
1057
+ contentTypeUid,
1058
+ documentId,
1059
+ locale
1060
+ }) => {
1061
+ const { formatMessage } = useIntl();
1062
+ const userPermissions = useAuth("ReleaseActionEntryLinkItem", (state) => state.permissions);
1063
+ const canUpdateEntryForLocale = React.useMemo(() => {
1064
+ const updatePermissions = userPermissions.find(
1065
+ (permission) => permission.subject === contentTypeUid && permission.action === "plugin::content-manager.explorer.update"
1066
+ );
1067
+ if (!updatePermissions) {
1068
+ return false;
1069
+ }
1070
+ return Boolean(!locale || updatePermissions.properties?.locales?.includes(locale));
1071
+ }, [contentTypeUid, locale, userPermissions]);
1072
+ const {
1073
+ allowedActions: { canUpdate: canUpdateContentType }
1074
+ } = useRBAC({
1075
+ updateContentType: [
1076
+ {
1077
+ action: "plugin::content-manager.explorer.update",
1078
+ subject: contentTypeUid
1079
+ }
1080
+ ]
1081
+ });
1082
+ if (!canUpdateContentType || !canUpdateEntryForLocale) {
1083
+ return null;
1084
+ }
1085
+ return /* @__PURE__ */ jsx(
1086
+ StyledMenuItem,
1087
+ {
1088
+ tag: NavLink,
1089
+ isLink: true,
1090
+ to: {
1091
+ pathname: `/content-manager/collection-types/${contentTypeUid}/${documentId}`,
1092
+ search: locale && `?plugins[i18n][locale]=${locale}`
1093
+ },
1094
+ children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1095
+ /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
1096
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
1097
+ id: "content-releases.content-manager-edit-view.edit-entry",
1098
+ defaultMessage: "Edit entry"
1099
+ }) })
1100
+ ] })
1101
+ }
1102
+ );
1103
+ };
1104
+ const EditReleaseItem = ({ releaseId }) => {
1105
+ const { formatMessage } = useIntl();
1106
+ return (
1107
+ /* @ts-expect-error inference isn't working in DS */
1108
+ /* @__PURE__ */ jsx(StyledMenuItem, { tag: NavLink, isLink: true, to: `/plugins/content-releases/${releaseId}`, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
1109
+ /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
1110
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", variant: "omega", children: formatMessage({
1111
+ id: "content-releases.content-manager-edit-view.edit-release",
1112
+ defaultMessage: "Edit release"
1113
+ }) })
1114
+ ] }) })
1115
+ );
1116
+ };
1117
+ const Root = ({ children }) => {
1118
+ const { formatMessage } = useIntl();
1119
+ const { allowedActions } = useRBAC(PERMISSIONS);
1120
+ return (
1121
+ // A user can access the dropdown if they have permissions to delete a release-action OR update a release
1122
+ allowedActions.canDeleteAction || allowedActions.canUpdate ? /* @__PURE__ */ jsxs(Menu.Root, { children: [
1123
+ /* @__PURE__ */ jsx(StyledMoreButton, { variant: "tertiary", endIcon: null, paddingLeft: "7px", paddingRight: "7px", children: /* @__PURE__ */ jsx(
1124
+ AccessibleIcon,
1125
+ {
1126
+ label: formatMessage({
1127
+ id: "content-releases.content-manager-edit-view.release-action-menu",
1128
+ defaultMessage: "Release action options"
1129
+ }),
1130
+ children: /* @__PURE__ */ jsx(More, {})
1131
+ }
1132
+ ) }),
1133
+ /* @__PURE__ */ jsx(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
1134
+ ] }) : null
1135
+ );
1136
+ };
1137
+ const StyledMoreButton = styled(Menu.Trigger)`
1138
+ & > span {
1139
+ display: flex;
1140
+ }
1141
+ `;
1142
+ const ReleaseActionMenu = {
1143
+ Root,
1144
+ EditReleaseItem,
1145
+ DeleteReleaseActionItem,
1146
+ ReleaseActionEntryLinkItem
1147
+ };
1148
+ const Panel = ({
1149
+ model,
1150
+ document,
1151
+ documentId,
1152
+ collectionType
1153
+ }) => {
1154
+ const [{ query }] = useQueryParams();
1155
+ const locale = query.plugins?.i18n?.locale;
1156
+ const {
1157
+ edit: { options }
1158
+ } = unstable_useDocumentLayout(model);
1159
+ const { formatMessage, formatDate, formatTime } = useIntl();
1160
+ const { allowedActions } = useRBAC(PERMISSIONS);
1161
+ const { canRead, canDeleteAction } = allowedActions;
1162
+ const response = useGetReleasesForEntryQuery(
1163
+ {
1164
+ contentType: model,
1165
+ entryDocumentId: documentId,
1166
+ locale,
1167
+ hasEntryAttached: true
1168
+ },
1169
+ {
1170
+ skip: !document
1171
+ }
1172
+ );
1173
+ const releases = response.data?.data;
1174
+ const getReleaseColorVariant = (actionType, shade) => {
1175
+ if (actionType === "unpublish") {
1176
+ return `secondary${shade}`;
1177
+ }
1178
+ return `success${shade}`;
1179
+ };
1180
+ if (!window.strapi.isEE || !options?.draftAndPublish || !canRead) {
1181
+ return null;
1182
+ }
1183
+ if (collectionType === "collection-types" && (!documentId || documentId === "create")) {
1184
+ return null;
1185
+ }
1186
+ if (!releases || releases.length === 0) {
1187
+ return null;
1188
+ }
1189
+ return {
1190
+ title: formatMessage({
1191
+ id: "content-releases.plugin.name",
1192
+ defaultMessage: "Releases"
1193
+ }),
1194
+ content: /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 3, width: "100%", children: releases?.map((release) => /* @__PURE__ */ jsxs(
1195
+ Flex,
1196
+ {
1197
+ direction: "column",
1198
+ alignItems: "start",
1199
+ borderWidth: "1px",
1200
+ borderStyle: "solid",
1201
+ borderColor: getReleaseColorVariant(release.actions[0].type, "200"),
1202
+ overflow: "hidden",
1203
+ hasRadius: true,
1204
+ children: [
1205
+ /* @__PURE__ */ jsx(
1206
+ Box,
1207
+ {
1208
+ paddingTop: 3,
1209
+ paddingBottom: 3,
1210
+ paddingLeft: 4,
1211
+ paddingRight: 4,
1212
+ background: getReleaseColorVariant(release.actions[0].type, "100"),
1213
+ width: "100%",
1214
+ children: /* @__PURE__ */ jsx(
1215
+ Typography,
1216
+ {
1217
+ fontSize: 1,
1218
+ variant: "pi",
1219
+ textColor: getReleaseColorVariant(release.actions[0].type, "600"),
1220
+ children: formatMessage(
1221
+ {
1222
+ id: "content-releases.content-manager-edit-view.list-releases.title",
1223
+ defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
1224
+ },
1225
+ { isPublish: release.actions[0].type === "publish" }
1226
+ )
1227
+ }
1228
+ )
1229
+ }
1230
+ ),
1231
+ /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
1232
+ /* @__PURE__ */ jsx(Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
1233
+ release.scheduledAt && release.timezone && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
1234
+ {
1235
+ id: "content-releases.content-manager-edit-view.scheduled.date",
1236
+ defaultMessage: "{date} at {time} ({offset})"
1237
+ },
1238
+ {
1239
+ date: formatDate(new Date(release.scheduledAt), {
1240
+ day: "2-digit",
1241
+ month: "2-digit",
1242
+ year: "numeric",
1243
+ timeZone: release.timezone
1244
+ }),
1245
+ time: formatTime(new Date(release.scheduledAt), {
1246
+ hourCycle: "h23",
1247
+ timeZone: release.timezone
1248
+ }),
1249
+ offset: getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
1250
+ }
1251
+ ) }),
1252
+ canDeleteAction ? /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
1253
+ /* @__PURE__ */ jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
1254
+ /* @__PURE__ */ jsx(
1255
+ ReleaseActionMenu.DeleteReleaseActionItem,
1256
+ {
1257
+ releaseId: release.id,
1258
+ actionId: release.actions[0].id
1259
+ }
1260
+ )
1261
+ ] }) : null
1262
+ ] })
1263
+ ]
1264
+ },
1265
+ release.id
1266
+ )) })
1267
+ };
1268
+ };
1269
+ const pluginId = "content-releases";
1270
+ const prefixPluginTranslations = (trad, pluginId2) => {
1153
1271
  return Object.keys(trad).reduce((acc, current) => {
1154
1272
  acc[`${pluginId2}.${current}`] = trad[current];
1155
1273
  return acc;
@@ -1167,26 +1285,46 @@ const admin = {
1167
1285
  id: `${pluginId}.plugin.name`,
1168
1286
  defaultMessage: "Releases"
1169
1287
  },
1170
- Component: () => import("./App-BsUSTHVD.mjs").then((mod) => ({ default: mod.App })),
1171
- permissions: PERMISSIONS.main
1172
- });
1173
- app.addMiddlewares([() => releaseApi.middleware]);
1174
- app.addReducers({
1175
- [releaseApi.reducerPath]: releaseApi.reducer
1176
- });
1177
- app.getPlugin("content-manager").injectComponent("editView", "right-links", {
1178
- name: `${pluginId}-link`,
1179
- Component: CMReleasesContainer
1288
+ Component: () => import("./App-FQyYFBJT.mjs").then((mod) => ({ default: mod.App })),
1289
+ permissions: PERMISSIONS.main,
1290
+ position: 2
1180
1291
  });
1181
- app.plugins["content-manager"].apis.addBulkAction((actions) => {
1182
- const deleteActionIndex = actions.findIndex((action) => action.name === "DeleteAction");
1183
- actions.splice(deleteActionIndex, 0, ReleaseAction);
1184
- return actions;
1292
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
1293
+ if ("addEditViewSidePanel" in contentManagerPluginApis && typeof contentManagerPluginApis.addEditViewSidePanel === "function") {
1294
+ contentManagerPluginApis.addEditViewSidePanel([Panel]);
1295
+ }
1296
+ if ("addDocumentAction" in contentManagerPluginApis && typeof contentManagerPluginApis.addDocumentAction === "function") {
1297
+ contentManagerPluginApis.addDocumentAction((actions) => {
1298
+ const indexOfDeleteAction = actions.findIndex((action) => action.type === "unpublish");
1299
+ actions.splice(indexOfDeleteAction, 0, ReleaseActionModalForm);
1300
+ return actions;
1301
+ });
1302
+ }
1303
+ app.addSettingsLink("global", {
1304
+ id: pluginId,
1305
+ to: "releases",
1306
+ intlLabel: {
1307
+ id: `${pluginId}.plugin.name`,
1308
+ defaultMessage: "Releases"
1309
+ },
1310
+ permissions: [],
1311
+ async Component() {
1312
+ const { ProtectedReleasesSettingsPage } = await import("./ReleasesSettingsPage-DqBxvJ9i.mjs");
1313
+ return { default: ProtectedReleasesSettingsPage };
1314
+ }
1185
1315
  });
1316
+ if ("addBulkAction" in contentManagerPluginApis && typeof contentManagerPluginApis.addBulkAction === "function") {
1317
+ contentManagerPluginApis.addBulkAction((actions) => {
1318
+ const deleteActionIndex = actions.findIndex((action) => action.type === "delete");
1319
+ actions.splice(deleteActionIndex, 0, ReleaseAction);
1320
+ return actions;
1321
+ });
1322
+ }
1323
+ app.registerHook("Admin/CM/pages/ListView/inject-column-in-table", addColumnToTableHook);
1186
1324
  } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
1187
- app.addMenuLink({
1188
- to: `/plugins/purchase-content-releases`,
1189
- icon: PaperPlane,
1325
+ app.addSettingsLink("global", {
1326
+ id: pluginId,
1327
+ to: "/plugins/purchase-content-releases",
1190
1328
  intlLabel: {
1191
1329
  id: `${pluginId}.plugin.name`,
1192
1330
  defaultMessage: "Releases"
@@ -1196,14 +1334,14 @@ const admin = {
1196
1334
  const { PurchaseContentReleases } = await import("./PurchaseContentReleases-_MxP6-Dt.mjs");
1197
1335
  return { default: PurchaseContentReleases };
1198
1336
  },
1199
- lockIcon: true
1337
+ licenseOnly: true
1200
1338
  });
1201
1339
  }
1202
1340
  },
1203
1341
  async registerTrads({ locales }) {
1204
1342
  const importedTrads = await Promise.all(
1205
1343
  locales.map((locale) => {
1206
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-B9Ur3VsE.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1344
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-D9Q4YW03.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1207
1345
  return {
1208
1346
  data: prefixPluginTranslations(data, "content-releases"),
1209
1347
  locale
@@ -1222,19 +1360,21 @@ const admin = {
1222
1360
  export {
1223
1361
  PERMISSIONS as P,
1224
1362
  ReleaseActionOptions as R,
1225
- useCreateReleaseMutation as a,
1226
- useGetReleaseQuery as b,
1227
- useUpdateReleaseMutation as c,
1228
- useDeleteReleaseMutation as d,
1229
- usePublishReleaseMutation as e,
1230
- useGetReleaseActionsQuery as f,
1231
- getTimezoneOffset as g,
1232
- useUpdateReleaseActionMutation as h,
1233
- isAxiosError as i,
1234
- ReleaseActionMenu as j,
1235
- admin as k,
1363
+ useGetReleaseSettingsQuery as a,
1364
+ useCreateReleaseMutation as b,
1365
+ useGetReleaseQuery as c,
1366
+ useUpdateReleaseMutation as d,
1367
+ useDeleteReleaseMutation as e,
1368
+ usePublishReleaseMutation as f,
1369
+ getTimezones as g,
1370
+ getTimezoneOffset as h,
1371
+ useGetReleaseActionsQuery as i,
1372
+ useUpdateReleaseActionMutation as j,
1373
+ ReleaseActionMenu as k,
1374
+ useUpdateReleaseSettingsMutation as l,
1375
+ admin as m,
1236
1376
  pluginId as p,
1237
1377
  releaseApi as r,
1238
1378
  useGetReleasesQuery as u
1239
1379
  };
1240
- //# sourceMappingURL=index-DJLIZdZv.mjs.map
1380
+ //# sourceMappingURL=index-CK9G80CL.mjs.map