@strapi/content-releases 5.0.0-beta.1 → 5.0.0-beta.11

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 (109) hide show
  1. package/dist/_chunks/{App-1LckaIGY.js → App-B5UOQWbt.js} +375 -368
  2. package/dist/_chunks/App-B5UOQWbt.js.map +1 -0
  3. package/dist/_chunks/{App-X01LBg5V.mjs → App-DcXlnXrr.mjs} +371 -363
  4. package/dist/_chunks/App-DcXlnXrr.mjs.map +1 -0
  5. package/dist/_chunks/{PurchaseContentReleases-YhAPgpG9.js → PurchaseContentReleases-Be3acS2L.js} +8 -7
  6. package/dist/_chunks/PurchaseContentReleases-Be3acS2L.js.map +1 -0
  7. package/dist/_chunks/{PurchaseContentReleases-Clm0iACO.mjs → PurchaseContentReleases-_MxP6-Dt.mjs} +9 -8
  8. package/dist/_chunks/PurchaseContentReleases-_MxP6-Dt.mjs.map +1 -0
  9. package/dist/_chunks/SettingsPage-ped5WZ6Q.js +40 -0
  10. package/dist/_chunks/SettingsPage-ped5WZ6Q.js.map +1 -0
  11. package/dist/_chunks/SettingsPage-w5dOMAtL.mjs +40 -0
  12. package/dist/_chunks/SettingsPage-w5dOMAtL.mjs.map +1 -0
  13. package/dist/_chunks/{en-faJDuv3q.js → en-aH5E5UNw.js} +12 -2
  14. package/dist/_chunks/en-aH5E5UNw.js.map +1 -0
  15. package/dist/_chunks/{en-RdapH-9X.mjs → en-ahPQUZv2.mjs} +12 -2
  16. package/dist/_chunks/en-ahPQUZv2.mjs.map +1 -0
  17. package/dist/_chunks/{index-cYWov2wa.js → index-BgID5UQ7.js} +549 -525
  18. package/dist/_chunks/index-BgID5UQ7.js.map +1 -0
  19. package/dist/_chunks/{index-OD9AlD-6.mjs → index-LUuvped4.mjs} +551 -525
  20. package/dist/_chunks/index-LUuvped4.mjs.map +1 -0
  21. package/dist/admin/index.js +1 -1
  22. package/dist/admin/index.mjs +2 -2
  23. package/dist/admin/src/components/ReleaseAction.d.ts +3 -0
  24. package/dist/admin/src/components/ReleaseActionMenu.d.ts +3 -3
  25. package/dist/admin/src/components/ReleaseActionModal.d.ts +24 -0
  26. package/dist/admin/src/components/ReleaseListCell.d.ts +0 -0
  27. package/dist/admin/src/components/ReleaseModal.d.ts +3 -2
  28. package/dist/admin/src/components/ReleasesPanel.d.ts +3 -0
  29. package/dist/admin/src/pages/SettingsPage.d.ts +1 -0
  30. package/dist/admin/src/services/release.d.ts +51 -313
  31. package/dist/admin/src/utils/api.d.ts +6 -0
  32. package/dist/server/index.js +824 -579
  33. package/dist/server/index.js.map +1 -1
  34. package/dist/server/index.mjs +825 -580
  35. package/dist/server/index.mjs.map +1 -1
  36. package/dist/server/src/bootstrap.d.ts +1 -1
  37. package/dist/server/src/bootstrap.d.ts.map +1 -1
  38. package/dist/server/src/constants.d.ts +11 -2
  39. package/dist/server/src/constants.d.ts.map +1 -1
  40. package/dist/server/src/content-types/index.d.ts +3 -5
  41. package/dist/server/src/content-types/index.d.ts.map +1 -1
  42. package/dist/server/src/content-types/release-action/index.d.ts +3 -5
  43. package/dist/server/src/content-types/release-action/index.d.ts.map +1 -1
  44. package/dist/server/src/content-types/release-action/schema.d.ts +3 -5
  45. package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -1
  46. package/dist/server/src/controllers/index.d.ts +6 -2
  47. package/dist/server/src/controllers/index.d.ts.map +1 -1
  48. package/dist/server/src/controllers/release-action.d.ts +0 -1
  49. package/dist/server/src/controllers/release-action.d.ts.map +1 -1
  50. package/dist/server/src/controllers/release.d.ts +7 -1
  51. package/dist/server/src/controllers/release.d.ts.map +1 -1
  52. package/dist/server/src/controllers/settings.d.ts +11 -0
  53. package/dist/server/src/controllers/settings.d.ts.map +1 -0
  54. package/dist/server/src/controllers/validation/release-action.d.ts +7 -1
  55. package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -1
  56. package/dist/server/src/controllers/validation/release.d.ts +1 -0
  57. package/dist/server/src/controllers/validation/release.d.ts.map +1 -1
  58. package/dist/server/src/controllers/validation/settings.d.ts +2 -0
  59. package/dist/server/src/controllers/validation/settings.d.ts.map +1 -0
  60. package/dist/server/src/destroy.d.ts +1 -1
  61. package/dist/server/src/destroy.d.ts.map +1 -1
  62. package/dist/server/src/index.d.ts +73 -57
  63. package/dist/server/src/index.d.ts.map +1 -1
  64. package/dist/server/src/middlewares/documents.d.ts +6 -0
  65. package/dist/server/src/middlewares/documents.d.ts.map +1 -0
  66. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts +9 -0
  67. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts.map +1 -0
  68. package/dist/server/src/migrations/index.d.ts.map +1 -1
  69. package/dist/server/src/register.d.ts +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-action.d.ts.map +1 -1
  74. package/dist/server/src/routes/release.d.ts.map +1 -1
  75. package/dist/server/src/routes/settings.d.ts +18 -0
  76. package/dist/server/src/routes/settings.d.ts.map +1 -0
  77. package/dist/server/src/services/index.d.ts +41 -41
  78. package/dist/server/src/services/index.d.ts.map +1 -1
  79. package/dist/server/src/services/release-action.d.ts +36 -0
  80. package/dist/server/src/services/release-action.d.ts.map +1 -0
  81. package/dist/server/src/services/release.d.ts +7 -42
  82. package/dist/server/src/services/release.d.ts.map +1 -1
  83. package/dist/server/src/services/scheduling.d.ts +1 -1
  84. package/dist/server/src/services/scheduling.d.ts.map +1 -1
  85. package/dist/server/src/services/settings.d.ts +13 -0
  86. package/dist/server/src/services/settings.d.ts.map +1 -0
  87. package/dist/server/src/services/validation.d.ts +2 -2
  88. package/dist/server/src/services/validation.d.ts.map +1 -1
  89. package/dist/server/src/utils/index.d.ts +33 -12
  90. package/dist/server/src/utils/index.d.ts.map +1 -1
  91. package/dist/shared/contracts/release-actions.d.ts +6 -5
  92. package/dist/shared/contracts/release-actions.d.ts.map +1 -1
  93. package/dist/shared/contracts/releases.d.ts +23 -6
  94. package/dist/shared/contracts/releases.d.ts.map +1 -1
  95. package/dist/shared/contracts/settings.d.ts +39 -0
  96. package/dist/shared/contracts/settings.d.ts.map +1 -0
  97. package/dist/shared/validation-schemas.d.ts +1 -0
  98. package/dist/shared/validation-schemas.d.ts.map +1 -1
  99. package/package.json +19 -18
  100. package/dist/_chunks/App-1LckaIGY.js.map +0 -1
  101. package/dist/_chunks/App-X01LBg5V.mjs.map +0 -1
  102. package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +0 -1
  103. package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +0 -1
  104. package/dist/_chunks/en-RdapH-9X.mjs.map +0 -1
  105. package/dist/_chunks/en-faJDuv3q.js.map +0 -1
  106. package/dist/_chunks/index-OD9AlD-6.mjs.map +0 -1
  107. package/dist/_chunks/index-cYWov2wa.js.map +0 -1
  108. package/dist/admin/src/components/CMReleasesContainer.d.ts +0 -1
  109. package/dist/admin/src/services/axios.d.ts +0 -29
@@ -1,17 +1,15 @@
1
- import { Cross, Pencil, More, Plus, EmptyDocuments, 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, unstable_useDocument, useQueryParams } from "@strapi/admin/strapi-admin";
6
- import { IconButton, Flex, Icon, Typography, Field, FieldLabel, VisuallyHidden, FieldInput, Box, Button, ModalLayout, ModalHeader, ModalBody, SingleSelect, SingleSelectOption, ModalFooter, EmptyStateLayout } from "@strapi/design-system";
7
- import { Menu, Link, LinkButton } from "@strapi/design-system/v2";
8
- import { isAxiosError as isAxiosError$1 } from "axios";
9
- import { Formik, Form } from "formik";
1
+ import { Cursor, Cross, Pencil, More, PaperPlane } from "@strapi/icons";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import { adminApi, useRBAC, useNotification, useAPIErrorHandler, useQueryParams, isFetchError, useAuth } from "@strapi/admin/strapi-admin";
4
+ import { unstable_useDocumentLayout } from "@strapi/content-manager/strapi-admin";
5
+ import { Field, Flex, VisuallyHidden, Modal, Button, Box, SingleSelect, SingleSelectOption, EmptyStateLayout, LinkButton, Menu, Typography, AccessibleIcon } from "@strapi/design-system";
6
+ import { EmptyDocuments } from "@strapi/icons/symbols";
7
+ import { useFormik } from "formik";
10
8
  import { useIntl } from "react-intl";
11
- import { NavLink, useParams, Link as Link$1 } from "react-router-dom";
9
+ import { Link, NavLink } from "react-router-dom";
12
10
  import * as yup from "yup";
13
- import { createApi } from "@reduxjs/toolkit/query/react";
14
- import styled from "styled-components";
11
+ import { styled } from "styled-components";
12
+ import * as React from "react";
15
13
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
16
14
  const v = glob[path];
17
15
  if (v) {
@@ -93,55 +91,41 @@ const PERMISSIONS = {
93
91
  }
94
92
  ]
95
93
  };
96
- const pluginId = "content-releases";
97
- const axiosBaseQuery = async ({
98
- url,
99
- method,
100
- data,
101
- config
102
- }) => {
103
- try {
104
- const { get, post, del, put } = getFetchClient();
105
- if (method === "POST") {
106
- const result2 = await post(url, data, config);
107
- return { data: result2.data };
108
- }
109
- if (method === "DELETE") {
110
- const result2 = await del(url, config);
111
- return { data: result2.data };
112
- }
113
- if (method === "PUT") {
114
- const result2 = await put(url, data, config);
115
- return { data: result2.data };
94
+ const releaseApi = adminApi.enhanceEndpoints({
95
+ addTagTypes: ["Release", "ReleaseAction", "EntriesInRelease"],
96
+ endpoints: {
97
+ updateDocument: {
98
+ invalidatesTags: [
99
+ { type: "Release", id: "LIST" },
100
+ { type: "ReleaseAction", id: "LIST" }
101
+ ]
102
+ },
103
+ deleteDocument: {
104
+ invalidatesTags: [
105
+ { type: "Release", id: "LIST" },
106
+ { type: "ReleaseAction", id: "LIST" }
107
+ ]
108
+ },
109
+ deleteManyDocuments: {
110
+ invalidatesTags: [
111
+ { type: "Release", id: "LIST" },
112
+ { type: "ReleaseAction", id: "LIST" }
113
+ ]
114
+ },
115
+ discardDocument: {
116
+ invalidatesTags: [
117
+ { type: "Release", id: "LIST" },
118
+ { type: "ReleaseAction", id: "LIST" }
119
+ ]
116
120
  }
117
- const result = await get(url, config);
118
- return { data: result.data };
119
- } catch (error) {
120
- const err = error;
121
- return {
122
- error: {
123
- status: err.response?.status,
124
- code: err.code,
125
- response: {
126
- data: err.response?.data
127
- }
128
- }
129
- };
130
121
  }
131
- };
132
- const isAxiosError = (err) => {
133
- return typeof err === "object" && err !== null && "response" in err && typeof err.response === "object" && err.response !== null && "data" in err.response;
134
- };
135
- const releaseApi = createApi({
136
- reducerPath: pluginId,
137
- baseQuery: axiosBaseQuery,
138
- tagTypes: ["Release", "ReleaseAction"],
122
+ }).injectEndpoints({
139
123
  endpoints: (build) => {
140
124
  return {
141
125
  getReleasesForEntry: build.query({
142
126
  query(params) {
143
127
  return {
144
- url: "/content-releases",
128
+ url: "/content-releases/getByDocumentAttached",
145
129
  method: "GET",
146
130
  config: {
147
131
  params
@@ -250,6 +234,20 @@ const releaseApi = createApi({
250
234
  { type: "ReleaseAction", id: "LIST" }
251
235
  ]
252
236
  }),
237
+ createManyReleaseActions: build.mutation({
238
+ query({ body, params }) {
239
+ return {
240
+ url: `/content-releases/${params.releaseId}/actions/bulk`,
241
+ method: "POST",
242
+ data: body
243
+ };
244
+ },
245
+ invalidatesTags: [
246
+ { type: "Release", id: "LIST" },
247
+ { type: "ReleaseAction", id: "LIST" },
248
+ { type: "EntriesInRelease" }
249
+ ]
250
+ }),
253
251
  updateReleaseAction: build.mutation({
254
252
  query({ body, params }) {
255
253
  return {
@@ -265,13 +263,17 @@ const releaseApi = createApi({
265
263
  ...query
266
264
  };
267
265
  const patchResult = dispatch(
268
- releaseApi.util.updateQueryData("getReleaseActions", paramsWithoutActionId, (draft) => {
269
- const [key, index] = actionPath;
270
- const action = draft.data[key][index];
271
- if (action) {
272
- action.type = body.type;
266
+ releaseApi.util.updateQueryData(
267
+ "getReleaseActions",
268
+ paramsWithoutActionId,
269
+ (draft) => {
270
+ const [key, index] = actionPath;
271
+ const action = draft.data[key][index];
272
+ if (action) {
273
+ action.type = body.type;
274
+ }
273
275
  }
274
- })
276
+ )
275
277
  );
276
278
  try {
277
279
  await queryFulfilled;
@@ -290,7 +292,8 @@ const releaseApi = createApi({
290
292
  invalidatesTags: (result, error, arg) => [
291
293
  { type: "Release", id: "LIST" },
292
294
  { type: "Release", id: arg.params.releaseId },
293
- { type: "ReleaseAction", id: "LIST" }
295
+ { type: "ReleaseAction", id: "LIST" },
296
+ { type: "EntriesInRelease" }
294
297
  ]
295
298
  }),
296
299
  publishRelease: build.mutation({
@@ -309,7 +312,22 @@ const releaseApi = createApi({
309
312
  method: "DELETE"
310
313
  };
311
314
  },
312
- invalidatesTags: () => [{ type: "Release", id: "LIST" }]
315
+ invalidatesTags: () => [{ type: "Release", id: "LIST" }, { type: "EntriesInRelease" }]
316
+ }),
317
+ getMappedEntriesInReleases: build.query({
318
+ query(params) {
319
+ return {
320
+ url: "/content-releases/mapEntriesToReleases",
321
+ method: "GET",
322
+ config: {
323
+ params
324
+ }
325
+ };
326
+ },
327
+ transformResponse(response) {
328
+ return response.data;
329
+ },
330
+ providesTags: [{ type: "EntriesInRelease" }]
313
331
  })
314
332
  };
315
333
  }
@@ -321,209 +339,25 @@ const {
321
339
  useGetReleaseActionsQuery,
322
340
  useCreateReleaseMutation,
323
341
  useCreateReleaseActionMutation,
342
+ useCreateManyReleaseActionsMutation,
324
343
  useUpdateReleaseMutation,
325
344
  useUpdateReleaseActionMutation,
326
345
  usePublishReleaseMutation,
327
346
  useDeleteReleaseActionMutation,
328
- useDeleteReleaseMutation
347
+ useDeleteReleaseMutation,
348
+ useGetMappedEntriesInReleasesQuery
329
349
  } = releaseApi;
330
- const getTimezoneOffset = (timezone, date) => {
331
- try {
332
- const offsetPart = new Intl.DateTimeFormat("en", {
333
- timeZone: timezone,
334
- timeZoneName: "longOffset"
335
- }).formatToParts(date).find((part) => part.type === "timeZoneName");
336
- const offset = offsetPart ? offsetPart.value : "";
337
- let utcOffset = offset.replace("GMT", "UTC");
338
- if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
339
- utcOffset = `${utcOffset}+00:00`;
340
- }
341
- return utcOffset;
342
- } catch (error) {
343
- return "";
344
- }
345
- };
346
- const StyledMenuItem = styled(Menu.Item)`
347
- &:hover {
348
- background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
349
-
350
- svg {
351
- path {
352
- fill: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}600`]};
353
- }
354
- }
355
-
356
- a {
357
- color: ${({ theme }) => theme.colors.neutral800};
358
- }
359
- }
360
-
361
- svg {
362
- path {
363
- fill: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}600`]};
364
- }
365
- }
366
-
367
- a {
368
- color: ${({ theme }) => theme.colors.neutral800};
369
- }
370
-
371
- span,
372
- a {
373
- width: 100%;
374
- }
375
- `;
376
- const StyledIconButton = styled(IconButton)`
377
- /* Setting this style inline with borderColor will not apply the style */
378
- border: ${({ theme }) => `1px solid ${theme.colors.neutral200}`};
379
- `;
380
- const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
381
- const { formatMessage } = useIntl();
382
- const { toggleNotification } = useNotification();
383
- const { formatAPIError } = useAPIErrorHandler();
384
- const [deleteReleaseAction] = useDeleteReleaseActionMutation();
385
- const {
386
- allowedActions: { canDeleteAction }
387
- } = useRBAC(PERMISSIONS);
388
- const handleDeleteAction = async () => {
389
- const response = await deleteReleaseAction({
390
- params: { releaseId, actionId }
391
- });
392
- if ("data" in response) {
393
- toggleNotification({
394
- type: "success",
395
- message: formatMessage({
396
- id: "content-releases.content-manager-edit-view.remove-from-release.notification.success",
397
- defaultMessage: "Entry removed from release"
398
- })
399
- });
400
- return;
401
- }
402
- if ("error" in response) {
403
- if (isAxiosError$1(response.error)) {
404
- toggleNotification({
405
- type: "danger",
406
- message: formatAPIError(response.error)
407
- });
408
- } else {
409
- toggleNotification({
410
- type: "danger",
411
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
412
- });
413
- }
414
- }
415
- };
416
- if (!canDeleteAction) {
417
- return null;
418
- }
419
- return /* @__PURE__ */ jsx(StyledMenuItem, { variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
420
- /* @__PURE__ */ jsx(Icon, { as: Cross, width: 3, height: 3 }),
421
- /* @__PURE__ */ jsx(Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
422
- id: "content-releases.content-manager-edit-view.remove-from-release",
423
- defaultMessage: "Remove from release"
424
- }) })
425
- ] }) });
426
- };
427
- const ReleaseActionEntryLinkItem = ({
428
- contentTypeUid,
429
- entryId,
430
- locale
431
- }) => {
432
- const { formatMessage } = useIntl();
433
- const userPermissions = useAuth("ReleaseActionEntryLinkItem", (state) => state.permissions);
434
- const canUpdateEntryForLocale = React.useMemo(() => {
435
- const updatePermissions = userPermissions.find(
436
- (permission) => permission.subject === contentTypeUid && permission.action === "plugin::content-manager.explorer.update"
437
- );
438
- if (!updatePermissions) {
439
- return false;
440
- }
441
- return Boolean(!locale || updatePermissions.properties?.locales?.includes(locale));
442
- }, [contentTypeUid, locale, userPermissions]);
443
- const {
444
- allowedActions: { canUpdateContentType }
445
- } = useRBAC({
446
- updateContentType: [
447
- {
448
- action: "plugin::content-manager.explorer.update",
449
- subject: contentTypeUid
450
- }
451
- ]
452
- });
453
- if (!canUpdateContentType || !canUpdateEntryForLocale) {
454
- return null;
455
- }
456
- return /* @__PURE__ */ jsx(StyledMenuItem, { children: /* @__PURE__ */ jsx(
457
- Link,
458
- {
459
- as: NavLink,
460
- to: {
461
- pathname: `/content-manager/collection-types/${contentTypeUid}/${entryId}`,
462
- search: locale && `?plugins[i18n][locale]=${locale}`
463
- },
464
- startIcon: /* @__PURE__ */ jsx(Icon, { as: Pencil, width: 3, height: 3 }),
465
- children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
466
- id: "content-releases.content-manager-edit-view.edit-entry",
467
- defaultMessage: "Edit entry"
468
- }) })
469
- }
470
- ) });
471
- };
472
- const EditReleaseItem = ({ releaseId }) => {
473
- const { formatMessage } = useIntl();
474
- return /* @__PURE__ */ jsx(StyledMenuItem, { children: /* @__PURE__ */ jsx(
475
- Link,
476
- {
477
- href: `/admin/plugins/content-releases/${releaseId}`,
478
- startIcon: /* @__PURE__ */ jsx(Icon, { as: Pencil, width: 3, height: 3 }),
479
- isExternal: false,
480
- children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
481
- id: "content-releases.content-manager-edit-view.edit-release",
482
- defaultMessage: "Edit release"
483
- }) })
484
- }
485
- ) });
486
- };
487
- const Root = ({ children, hasTriggerBorder = false }) => {
488
- const { formatMessage } = useIntl();
489
- const { allowedActions } = useRBAC(PERMISSIONS);
490
- return (
491
- // A user can access the dropdown if they have permissions to delete a release-action OR update a release
492
- allowedActions.canDeleteAction || allowedActions.canUpdate ? /* @__PURE__ */ jsxs(Menu.Root, { children: [
493
- /* @__PURE__ */ jsx(
494
- Menu.Trigger,
495
- {
496
- as: hasTriggerBorder ? StyledIconButton : IconButton,
497
- paddingLeft: 2,
498
- paddingRight: 2,
499
- "aria-label": formatMessage({
500
- id: "content-releases.content-manager-edit-view.release-action-menu",
501
- defaultMessage: "Release action options"
502
- }),
503
- icon: /* @__PURE__ */ jsx(More, {})
504
- }
505
- ),
506
- /* @__PURE__ */ jsx(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
507
- ] }) : null
508
- );
509
- };
510
- const ReleaseActionMenu = {
511
- Root,
512
- EditReleaseItem,
513
- DeleteReleaseActionItem,
514
- ReleaseActionEntryLinkItem
515
- };
516
350
  const getBorderLeftRadiusValue = (actionType) => {
517
351
  return actionType === "publish" ? 1 : 0;
518
352
  };
519
353
  const getBorderRightRadiusValue = (actionType) => {
520
354
  return actionType === "publish" ? 0 : 1;
521
355
  };
522
- const FieldWrapper = styled(Field)`
523
- border-top-left-radius: ${({ actionType, theme }) => theme.spaces[getBorderLeftRadiusValue(actionType)]};
524
- border-bottom-left-radius: ${({ actionType, theme }) => theme.spaces[getBorderLeftRadiusValue(actionType)]};
525
- border-top-right-radius: ${({ actionType, theme }) => theme.spaces[getBorderRightRadiusValue(actionType)]};
526
- border-bottom-right-radius: ${({ actionType, theme }) => theme.spaces[getBorderRightRadiusValue(actionType)]};
356
+ const FieldWrapper = styled(Field.Root)`
357
+ border-top-left-radius: ${({ $actionType, theme }) => theme.spaces[getBorderLeftRadiusValue($actionType)]};
358
+ border-bottom-left-radius: ${({ $actionType, theme }) => theme.spaces[getBorderLeftRadiusValue($actionType)]};
359
+ border-top-right-radius: ${({ $actionType, theme }) => theme.spaces[getBorderRightRadiusValue($actionType)]};
360
+ border-bottom-right-radius: ${({ $actionType, theme }) => theme.spaces[getBorderRightRadiusValue($actionType)]};
527
361
 
528
362
  > label {
529
363
  color: inherit;
@@ -534,14 +368,14 @@ const FieldWrapper = styled(Field)`
534
368
  }
535
369
 
536
370
  &[data-checked='true'] {
537
- color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
538
- background-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary100 : theme.colors.danger100};
539
- border-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
371
+ color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
372
+ background-color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary100 : theme.colors.danger100};
373
+ border-color: ${({ theme, $actionType }) => $actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
540
374
  }
541
375
 
542
376
  &[data-checked='false'] {
543
- border-left: ${({ actionType }) => actionType === "unpublish" && "none"};
544
- border-right: ${({ actionType }) => actionType === "publish" && "none"};
377
+ border-left: ${({ $actionType }) => $actionType === "unpublish" && "none"};
378
+ border-right: ${({ $actionType }) => $actionType === "publish" && "none"};
545
379
  }
546
380
 
547
381
  &[data-checked='false'][data-disabled='false']:hover {
@@ -570,7 +404,7 @@ const ActionOption = ({
570
404
  return /* @__PURE__ */ jsx(
571
405
  FieldWrapper,
572
406
  {
573
- actionType,
407
+ $actionType: actionType,
574
408
  background: "primary0",
575
409
  borderColor: "neutral200",
576
410
  color: selected === actionType ? "primary600" : "neutral600",
@@ -578,12 +412,11 @@ const ActionOption = ({
578
412
  cursor: "pointer",
579
413
  "data-checked": selected === actionType,
580
414
  "data-disabled": disabled && selected !== actionType,
581
- children: /* @__PURE__ */ jsxs(FieldLabel, { htmlFor: `${name}-${actionType}`, children: [
415
+ children: /* @__PURE__ */ jsxs(Field.Label, { children: [
582
416
  /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx(
583
- FieldInput,
417
+ Field.Input,
584
418
  {
585
419
  type: "radio",
586
- id: `${name}-${actionType}`,
587
420
  name,
588
421
  checked: selected === actionType,
589
422
  onChange: handleChange,
@@ -638,7 +471,7 @@ const NoReleases = () => {
638
471
  return /* @__PURE__ */ jsx(
639
472
  EmptyStateLayout,
640
473
  {
641
- icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem" }),
474
+ icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "16rem" }),
642
475
  content: formatMessage({
643
476
  id: "content-releases.content-manager-edit-view.add-to-release.no-releases-message",
644
477
  defaultMessage: "No available releases. Open the list of releases and create a new one from there."
@@ -649,61 +482,259 @@ const NoReleases = () => {
649
482
  to: {
650
483
  pathname: "/plugins/content-releases"
651
484
  },
652
- as: Link$1,
485
+ tag: Link,
653
486
  variant: "secondary",
654
487
  children: formatMessage({
655
488
  id: "content-releases.content-manager-edit-view.add-to-release.redirect-button",
656
489
  defaultMessage: "Open the list of releases"
657
490
  })
658
491
  }
659
- )
492
+ ),
493
+ shadow: "none"
660
494
  }
661
495
  );
662
496
  };
663
497
  const AddActionToReleaseModal = ({
664
- handleClose,
665
- contentTypeUid,
666
- entryId
498
+ contentType,
499
+ documentId,
500
+ onInputChange,
501
+ values
667
502
  }) => {
668
- const releaseHeaderId = React.useId();
669
503
  const { formatMessage } = useIntl();
670
- const { toggleNotification } = useNotification();
671
- const { formatAPIError } = useAPIErrorHandler();
672
504
  const [{ query }] = useQueryParams();
673
505
  const locale = query.plugins?.i18n?.locale;
674
506
  const response = useGetReleasesForEntryQuery({
675
- contentTypeUid,
676
- entryId,
677
- hasEntryAttached: false
507
+ contentType,
508
+ entryDocumentId: documentId,
509
+ hasEntryAttached: false,
510
+ locale
678
511
  });
679
512
  const releases = response.data?.data;
513
+ if (releases?.length === 0) {
514
+ return /* @__PURE__ */ jsx(NoReleases, {});
515
+ }
516
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
517
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxs(Field.Root, { required: true, children: [
518
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
519
+ id: "content-releases.content-manager-edit-view.add-to-release.select-label",
520
+ defaultMessage: "Select a release"
521
+ }) }),
522
+ /* @__PURE__ */ jsx(
523
+ SingleSelect,
524
+ {
525
+ required: true,
526
+ placeholder: formatMessage({
527
+ id: "content-releases.content-manager-edit-view.add-to-release.select-placeholder",
528
+ defaultMessage: "Select"
529
+ }),
530
+ name: "releaseId",
531
+ onChange: (value) => onInputChange("releaseId", value),
532
+ value: values.releaseId,
533
+ children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
534
+ }
535
+ )
536
+ ] }) }),
537
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
538
+ id: "content-releases.content-manager-edit-view.add-to-release.action-type-label",
539
+ defaultMessage: "What do you want to do with this entry?"
540
+ }) }),
541
+ /* @__PURE__ */ jsx(
542
+ ReleaseActionOptions,
543
+ {
544
+ selected: values.type,
545
+ handleChange: (e) => onInputChange("type", e.target.value),
546
+ name: "type"
547
+ }
548
+ )
549
+ ] });
550
+ };
551
+ const ReleaseActionModalForm = ({
552
+ documentId,
553
+ model,
554
+ collectionType
555
+ }) => {
556
+ const { formatMessage } = useIntl();
557
+ const { allowedActions } = useRBAC(PERMISSIONS);
558
+ const { canCreateAction } = allowedActions;
680
559
  const [createReleaseAction, { isLoading }] = useCreateReleaseActionMutation();
681
- const handleSubmit = async (values) => {
682
- const releaseActionEntry = {
683
- contentType: contentTypeUid,
684
- id: entryId,
685
- locale
686
- };
687
- const response2 = await createReleaseAction({
688
- body: { type: values.type, entry: releaseActionEntry },
689
- params: { releaseId: values.releaseId }
560
+ const { toggleNotification } = useNotification();
561
+ const { formatAPIError } = useAPIErrorHandler();
562
+ const [{ query }] = useQueryParams();
563
+ const locale = query.plugins?.i18n?.locale;
564
+ const handleSubmit = async (e, onClose) => {
565
+ try {
566
+ await formik.handleSubmit(e);
567
+ onClose();
568
+ } catch (error) {
569
+ if (isFetchError(error)) {
570
+ toggleNotification({
571
+ type: "danger",
572
+ message: formatAPIError(error)
573
+ });
574
+ } else {
575
+ toggleNotification({
576
+ type: "danger",
577
+ message: formatMessage({
578
+ id: "notification.error",
579
+ defaultMessage: "An error occurred"
580
+ })
581
+ });
582
+ }
583
+ }
584
+ };
585
+ const formik = useFormik({
586
+ initialValues: INITIAL_VALUES,
587
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
588
+ onSubmit: async (values) => {
589
+ if (collectionType === "collection-types" && !documentId) {
590
+ throw new Error("Document id is required");
591
+ }
592
+ const response = await createReleaseAction({
593
+ body: {
594
+ type: values.type,
595
+ contentType: model,
596
+ entryDocumentId: documentId,
597
+ locale
598
+ },
599
+ params: { releaseId: values.releaseId }
600
+ });
601
+ if ("data" in response) {
602
+ toggleNotification({
603
+ type: "success",
604
+ message: formatMessage({
605
+ id: "content-releases.content-manager-edit-view.add-to-release.notification.success",
606
+ defaultMessage: "Entry added to release"
607
+ })
608
+ });
609
+ return;
610
+ }
611
+ if ("error" in response) {
612
+ throw response.error;
613
+ }
614
+ }
615
+ });
616
+ const {
617
+ edit: { options }
618
+ } = unstable_useDocumentLayout(model);
619
+ if (!window.strapi.isEE || !options?.draftAndPublish || !canCreateAction) {
620
+ return null;
621
+ }
622
+ if (collectionType === "collection-types" && (!documentId || documentId === "create")) {
623
+ return null;
624
+ }
625
+ return {
626
+ label: formatMessage({
627
+ id: "content-releases.content-manager-edit-view.add-to-release",
628
+ defaultMessage: "Add to release"
629
+ }),
630
+ icon: /* @__PURE__ */ jsx(Cursor, {}),
631
+ position: ["panel", "table-row"],
632
+ dialog: {
633
+ type: "modal",
634
+ title: formatMessage({
635
+ id: "content-releases.content-manager-edit-view.add-to-release",
636
+ defaultMessage: "Add to release"
637
+ }),
638
+ content: /* @__PURE__ */ jsx(
639
+ AddActionToReleaseModal,
640
+ {
641
+ contentType: model,
642
+ documentId,
643
+ onInputChange: formik.setFieldValue,
644
+ values: formik.values
645
+ }
646
+ ),
647
+ footer: ({ onClose }) => /* @__PURE__ */ jsxs(Modal.Footer, { children: [
648
+ /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
649
+ id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
650
+ defaultMessage: "Cancel"
651
+ }) }),
652
+ /* @__PURE__ */ jsx(
653
+ Button,
654
+ {
655
+ type: "submit",
656
+ onClick: (e) => handleSubmit(e, onClose),
657
+ disabled: !formik.values.releaseId,
658
+ loading: isLoading,
659
+ children: formatMessage({
660
+ id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
661
+ defaultMessage: "Continue"
662
+ })
663
+ }
664
+ )
665
+ ] })
666
+ }
667
+ };
668
+ };
669
+ const getTimezoneOffset = (timezone, date) => {
670
+ try {
671
+ const offsetPart = new Intl.DateTimeFormat("en", {
672
+ timeZone: timezone,
673
+ timeZoneName: "longOffset"
674
+ }).formatToParts(date).find((part) => part.type === "timeZoneName");
675
+ const offset = offsetPart ? offsetPart.value : "";
676
+ let utcOffset = offset.replace("GMT", "UTC");
677
+ if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
678
+ utcOffset = `${utcOffset}+00:00`;
679
+ }
680
+ return utcOffset;
681
+ } catch (error) {
682
+ return "";
683
+ }
684
+ };
685
+ const StyledMenuItem = styled(Menu.Item)`
686
+ &:hover {
687
+ background: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}100`]};
688
+
689
+ svg {
690
+ fill: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}600`]};
691
+ }
692
+
693
+ a {
694
+ color: ${({ theme }) => theme.colors.neutral800};
695
+ }
696
+ }
697
+
698
+ svg {
699
+ color: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}500`]};
700
+ }
701
+
702
+ span {
703
+ color: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}800`]};
704
+ }
705
+
706
+ span,
707
+ a {
708
+ width: 100%;
709
+ }
710
+ `;
711
+ const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
712
+ const { formatMessage } = useIntl();
713
+ const { toggleNotification } = useNotification();
714
+ const { formatAPIError } = useAPIErrorHandler();
715
+ const [deleteReleaseAction] = useDeleteReleaseActionMutation();
716
+ const {
717
+ allowedActions: { canDeleteAction }
718
+ } = useRBAC(PERMISSIONS);
719
+ const handleDeleteAction = async () => {
720
+ const response = await deleteReleaseAction({
721
+ params: { releaseId, actionId }
690
722
  });
691
- if ("data" in response2) {
723
+ if ("data" in response) {
692
724
  toggleNotification({
693
725
  type: "success",
694
726
  message: formatMessage({
695
- id: "content-releases.content-manager-edit-view.add-to-release.notification.success",
696
- defaultMessage: "Entry added to release"
727
+ id: "content-releases.content-manager-edit-view.remove-from-release.notification.success",
728
+ defaultMessage: "Entry removed from release"
697
729
  })
698
730
  });
699
- handleClose();
700
731
  return;
701
732
  }
702
- if ("error" in response2) {
703
- if (isAxiosError$1(response2.error)) {
733
+ if ("error" in response) {
734
+ if (isFetchError(response.error)) {
704
735
  toggleNotification({
705
736
  type: "danger",
706
- message: formatAPIError(response2.error)
737
+ message: formatAPIError(response.error)
707
738
  });
708
739
  } else {
709
740
  toggleNotification({
@@ -713,239 +744,216 @@ const AddActionToReleaseModal = ({
713
744
  }
714
745
  }
715
746
  };
716
- return /* @__PURE__ */ jsxs(ModalLayout, { onClose: handleClose, labelledBy: releaseHeaderId, children: [
717
- /* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { id: releaseHeaderId, fontWeight: "bold", textColor: "neutral800", children: formatMessage({
718
- id: "content-releases.content-manager-edit-view.add-to-release",
719
- defaultMessage: "Add to release"
720
- }) }) }),
721
- /* @__PURE__ */ jsx(
722
- Formik,
747
+ if (!canDeleteAction) {
748
+ return null;
749
+ }
750
+ return /* @__PURE__ */ jsx(StyledMenuItem, { $variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
751
+ /* @__PURE__ */ jsx(Cross, { width: "1.6rem", height: "1.6rem" }),
752
+ /* @__PURE__ */ jsx(Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
753
+ id: "content-releases.content-manager-edit-view.remove-from-release",
754
+ defaultMessage: "Remove from release"
755
+ }) })
756
+ ] }) });
757
+ };
758
+ const ReleaseActionEntryLinkItem = ({
759
+ contentTypeUid,
760
+ documentId,
761
+ locale
762
+ }) => {
763
+ const { formatMessage } = useIntl();
764
+ const userPermissions = useAuth("ReleaseActionEntryLinkItem", (state) => state.permissions);
765
+ const canUpdateEntryForLocale = React.useMemo(() => {
766
+ const updatePermissions = userPermissions.find(
767
+ (permission) => permission.subject === contentTypeUid && permission.action === "plugin::content-manager.explorer.update"
768
+ );
769
+ if (!updatePermissions) {
770
+ return false;
771
+ }
772
+ return Boolean(!locale || updatePermissions.properties?.locales?.includes(locale));
773
+ }, [contentTypeUid, locale, userPermissions]);
774
+ const {
775
+ allowedActions: { canUpdate: canUpdateContentType }
776
+ } = useRBAC({
777
+ updateContentType: [
723
778
  {
724
- onSubmit: handleSubmit,
725
- validationSchema: RELEASE_ACTION_FORM_SCHEMA,
726
- initialValues: INITIAL_VALUES,
727
- children: ({ values, setFieldValue }) => {
728
- return /* @__PURE__ */ jsxs(Form, { children: [
729
- releases?.length === 0 ? /* @__PURE__ */ jsx(NoReleases, {}) : /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
730
- /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsx(
731
- SingleSelect,
732
- {
733
- required: true,
734
- label: formatMessage({
735
- id: "content-releases.content-manager-edit-view.add-to-release.select-label",
736
- defaultMessage: "Select a release"
737
- }),
738
- placeholder: formatMessage({
739
- id: "content-releases.content-manager-edit-view.add-to-release.select-placeholder",
740
- defaultMessage: "Select"
741
- }),
742
- onChange: (value) => setFieldValue("releaseId", value),
743
- value: values.releaseId,
744
- children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
745
- }
746
- ) }),
747
- /* @__PURE__ */ jsx(FieldLabel, { children: formatMessage({
748
- id: "content-releases.content-manager-edit-view.add-to-release.action-type-label",
749
- defaultMessage: "What do you want to do with this entry?"
750
- }) }),
751
- /* @__PURE__ */ jsx(
752
- ReleaseActionOptions,
753
- {
754
- selected: values.type,
755
- handleChange: (e) => setFieldValue("type", e.target.value),
756
- name: "type"
757
- }
758
- )
759
- ] }) }),
760
- /* @__PURE__ */ jsx(
761
- ModalFooter,
762
- {
763
- startActions: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({
764
- id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
765
- defaultMessage: "Cancel"
766
- }) }),
767
- endActions: (
768
- /**
769
- * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
770
- * for yup.string().required(), even when the value is falsy (including empty string)
771
- */
772
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
773
- id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
774
- defaultMessage: "Continue"
775
- }) })
776
- )
777
- }
778
- )
779
- ] });
780
- }
779
+ action: "plugin::content-manager.explorer.update",
780
+ subject: contentTypeUid
781
781
  }
782
- )
783
- ] });
782
+ ]
783
+ });
784
+ if (!canUpdateContentType || !canUpdateEntryForLocale) {
785
+ return null;
786
+ }
787
+ return /* @__PURE__ */ jsx(
788
+ StyledMenuItem,
789
+ {
790
+ tag: NavLink,
791
+ isLink: true,
792
+ to: {
793
+ pathname: `/content-manager/collection-types/${contentTypeUid}/${documentId}`,
794
+ search: locale && `?plugins[i18n][locale]=${locale}`
795
+ },
796
+ children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
797
+ /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
798
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
799
+ id: "content-releases.content-manager-edit-view.edit-entry",
800
+ defaultMessage: "Edit entry"
801
+ }) })
802
+ ] })
803
+ }
804
+ );
784
805
  };
785
- const CMReleasesContainer = () => {
786
- const [isModalOpen, setIsModalOpen] = React.useState(false);
787
- const { formatMessage, formatDate, formatTime } = useIntl();
788
- const { id, slug, collectionType } = useParams();
789
- const isCreatingEntry = id === "create";
806
+ const EditReleaseItem = ({ releaseId }) => {
807
+ const { formatMessage } = useIntl();
808
+ return (
809
+ /* @ts-expect-error inference isn't working in DS */
810
+ /* @__PURE__ */ jsx(StyledMenuItem, { tag: NavLink, isLink: true, to: `/plugins/content-releases/${releaseId}`, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
811
+ /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
812
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", variant: "omega", children: formatMessage({
813
+ id: "content-releases.content-manager-edit-view.edit-release",
814
+ defaultMessage: "Edit release"
815
+ }) })
816
+ ] }) })
817
+ );
818
+ };
819
+ const Root = ({ children }) => {
820
+ const { formatMessage } = useIntl();
821
+ const { allowedActions } = useRBAC(PERMISSIONS);
822
+ return (
823
+ // A user can access the dropdown if they have permissions to delete a release-action OR update a release
824
+ allowedActions.canDeleteAction || allowedActions.canUpdate ? /* @__PURE__ */ jsxs(Menu.Root, { children: [
825
+ /* @__PURE__ */ jsx(Menu.Trigger, { variant: "tertiary", endIcon: null, paddingLeft: 2, paddingRight: 2, children: /* @__PURE__ */ jsx(
826
+ AccessibleIcon,
827
+ {
828
+ label: formatMessage({
829
+ id: "content-releases.content-manager-edit-view.release-action-menu",
830
+ defaultMessage: "Release action options"
831
+ }),
832
+ children: /* @__PURE__ */ jsx(More, {})
833
+ }
834
+ ) }),
835
+ /* @__PURE__ */ jsx(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
836
+ ] }) : null
837
+ );
838
+ };
839
+ const ReleaseActionMenu = {
840
+ Root,
841
+ EditReleaseItem,
842
+ DeleteReleaseActionItem,
843
+ ReleaseActionEntryLinkItem
844
+ };
845
+ const Panel = ({ model, documentId, collectionType }) => {
846
+ const [{ query }] = useQueryParams();
847
+ const locale = query.plugins?.i18n?.locale;
790
848
  const {
791
- allowedActions: { canCreateAction, canMain, canDeleteAction }
792
- } = useRBAC(PERMISSIONS);
793
- const { schema } = unstable_useDocument({
794
- collectionType,
795
- model: slug
796
- });
797
- const hasDraftAndPublish = schema?.options?.draftAndPublish;
798
- const contentTypeUid = slug;
799
- const canFetch = id != null && contentTypeUid != null;
800
- const fetchParams = canFetch ? {
801
- contentTypeUid,
802
- entryId: id,
849
+ edit: { options }
850
+ } = unstable_useDocumentLayout(model);
851
+ const { formatMessage, formatDate, formatTime } = useIntl();
852
+ const { allowedActions } = useRBAC(PERMISSIONS);
853
+ const { canRead, canDeleteAction } = allowedActions;
854
+ const response = useGetReleasesForEntryQuery({
855
+ contentType: model,
856
+ entryDocumentId: documentId,
857
+ locale,
803
858
  hasEntryAttached: true
804
- } : skipToken;
805
- const response = useGetReleasesForEntryQuery(fetchParams);
859
+ });
806
860
  const releases = response.data?.data;
807
- if (!canFetch) {
808
- return null;
809
- }
810
- if (isCreatingEntry || !hasDraftAndPublish) {
811
- return null;
812
- }
813
- const toggleModal = () => setIsModalOpen((prev) => !prev);
814
861
  const getReleaseColorVariant = (actionType, shade) => {
815
862
  if (actionType === "unpublish") {
816
863
  return `secondary${shade}`;
817
864
  }
818
865
  return `success${shade}`;
819
866
  };
820
- if (!canMain) {
867
+ if (!window.strapi.isEE || !options?.draftAndPublish || !canRead) {
821
868
  return null;
822
869
  }
823
- return /* @__PURE__ */ jsxs(
824
- Box,
825
- {
826
- as: "aside",
827
- "aria-label": formatMessage({
828
- id: "content-releases.plugin.name",
829
- defaultMessage: "Releases"
830
- }),
831
- background: "neutral0",
832
- borderColor: "neutral150",
833
- hasRadius: true,
834
- padding: 4,
835
- shadow: "tableShadow",
836
- children: [
837
- /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
838
- /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", children: formatMessage({
839
- id: "content-releases.plugin.name",
840
- defaultMessage: "Releases"
841
- }) }),
842
- releases?.map((release) => {
843
- return /* @__PURE__ */ jsxs(
844
- Flex,
845
- {
846
- direction: "column",
847
- alignItems: "start",
848
- borderWidth: "1px",
849
- borderStyle: "solid",
850
- borderColor: getReleaseColorVariant(release.action.type, "200"),
851
- overflow: "hidden",
852
- hasRadius: true,
853
- children: [
854
- /* @__PURE__ */ jsx(
855
- Box,
856
- {
857
- paddingTop: 3,
858
- paddingBottom: 3,
859
- paddingLeft: 4,
860
- paddingRight: 4,
861
- background: getReleaseColorVariant(release.action.type, "100"),
862
- width: "100%",
863
- children: /* @__PURE__ */ jsx(
864
- Typography,
865
- {
866
- fontSize: 1,
867
- variant: "pi",
868
- textColor: getReleaseColorVariant(release.action.type, "600"),
869
- children: formatMessage(
870
- {
871
- id: "content-releases.content-manager-edit-view.list-releases.title",
872
- defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
873
- },
874
- { isPublish: release.action.type === "publish" }
875
- )
876
- }
877
- )
878
- }
879
- ),
880
- /* @__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: [
881
- /* @__PURE__ */ jsx(Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
882
- release.scheduledAt && release.timezone && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
883
- {
884
- id: "content-releases.content-manager-edit-view.scheduled.date",
885
- defaultMessage: "{date} at {time} ({offset})"
886
- },
887
- {
888
- date: formatDate(new Date(release.scheduledAt), {
889
- day: "2-digit",
890
- month: "2-digit",
891
- year: "numeric",
892
- timeZone: release.timezone
893
- }),
894
- time: formatTime(new Date(release.scheduledAt), {
895
- hourCycle: "h23",
896
- timeZone: release.timezone
897
- }),
898
- offset: getTimezoneOffset(
899
- release.timezone,
900
- new Date(release.scheduledAt)
901
- )
902
- }
903
- ) }),
904
- canDeleteAction ? /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
905
- /* @__PURE__ */ jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
906
- /* @__PURE__ */ jsx(
907
- ReleaseActionMenu.DeleteReleaseActionItem,
908
- {
909
- releaseId: release.id,
910
- actionId: release.action.id
911
- }
912
- )
913
- ] }) : null
914
- ] }) })
915
- ]
916
- },
917
- release.id
918
- );
919
- }),
920
- canCreateAction ? /* @__PURE__ */ jsx(
921
- Button,
870
+ if (collectionType === "collection-types" && (!documentId || documentId === "create")) {
871
+ return null;
872
+ }
873
+ if (releases && releases.length === 0) {
874
+ return null;
875
+ }
876
+ return {
877
+ title: formatMessage({
878
+ id: "content-releases.plugin.name",
879
+ defaultMessage: "Releases"
880
+ }),
881
+ content: /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 3, width: "100%", children: releases?.map((release) => /* @__PURE__ */ jsxs(
882
+ Flex,
883
+ {
884
+ direction: "column",
885
+ alignItems: "start",
886
+ borderWidth: "1px",
887
+ borderStyle: "solid",
888
+ borderColor: getReleaseColorVariant(release.actions[0].type, "200"),
889
+ overflow: "hidden",
890
+ hasRadius: true,
891
+ children: [
892
+ /* @__PURE__ */ jsx(
893
+ Box,
922
894
  {
923
- justifyContent: "center",
895
+ paddingTop: 3,
896
+ paddingBottom: 3,
924
897
  paddingLeft: 4,
925
898
  paddingRight: 4,
926
- color: "neutral700",
927
- variant: "tertiary",
928
- startIcon: /* @__PURE__ */ jsx(Plus, {}),
929
- onClick: toggleModal,
930
- children: formatMessage({
931
- id: "content-releases.content-manager-edit-view.add-to-release",
932
- defaultMessage: "Add to release"
933
- })
899
+ background: getReleaseColorVariant(release.actions[0].type, "100"),
900
+ width: "100%",
901
+ children: /* @__PURE__ */ jsx(
902
+ Typography,
903
+ {
904
+ fontSize: 1,
905
+ variant: "pi",
906
+ textColor: getReleaseColorVariant(release.actions[0].type, "600"),
907
+ children: formatMessage(
908
+ {
909
+ id: "content-releases.content-manager-edit-view.list-releases.title",
910
+ defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
911
+ },
912
+ { isPublish: release.actions[0].type === "publish" }
913
+ )
914
+ }
915
+ )
934
916
  }
935
- ) : null
936
- ] }),
937
- isModalOpen && /* @__PURE__ */ jsx(
938
- AddActionToReleaseModal,
939
- {
940
- handleClose: toggleModal,
941
- contentTypeUid,
942
- entryId: id
943
- }
944
- )
945
- ]
946
- }
947
- );
917
+ ),
918
+ /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
919
+ /* @__PURE__ */ jsx(Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
920
+ release.scheduledAt && release.timezone && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
921
+ {
922
+ id: "content-releases.content-manager-edit-view.scheduled.date",
923
+ defaultMessage: "{date} at {time} ({offset})"
924
+ },
925
+ {
926
+ date: formatDate(new Date(release.scheduledAt), {
927
+ day: "2-digit",
928
+ month: "2-digit",
929
+ year: "numeric",
930
+ timeZone: release.timezone
931
+ }),
932
+ time: formatTime(new Date(release.scheduledAt), {
933
+ hourCycle: "h23",
934
+ timeZone: release.timezone
935
+ }),
936
+ offset: getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
937
+ }
938
+ ) }),
939
+ canDeleteAction ? /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
940
+ /* @__PURE__ */ jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
941
+ /* @__PURE__ */ jsx(
942
+ ReleaseActionMenu.DeleteReleaseActionItem,
943
+ {
944
+ releaseId: release.id,
945
+ actionId: release.actions[0].id
946
+ }
947
+ )
948
+ ] }) : null
949
+ ] })
950
+ ]
951
+ },
952
+ release.id
953
+ )) })
954
+ };
948
955
  };
956
+ const pluginId = "content-releases";
949
957
  const prefixPluginTranslations = (trad, pluginId2) => {
950
958
  if (!pluginId2) {
951
959
  throw new TypeError("pluginId can't be empty");
@@ -958,6 +966,7 @@ const prefixPluginTranslations = (trad, pluginId2) => {
958
966
  const admin = {
959
967
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
960
968
  register(app) {
969
+ app.createHook("ContentReleases/pages/ReleaseDetails/add-locale-in-releases");
961
970
  if (window.strapi.features.isEnabled("cms-content-releases")) {
962
971
  app.addMenuLink({
963
972
  to: `plugins/${pluginId}`,
@@ -966,37 +975,55 @@ const admin = {
966
975
  id: `${pluginId}.plugin.name`,
967
976
  defaultMessage: "Releases"
968
977
  },
969
- Component: () => import("./App-X01LBg5V.mjs").then((mod) => ({ default: mod.App })),
970
- permissions: PERMISSIONS.main
978
+ Component: () => import("./App-DcXlnXrr.mjs").then((mod) => ({ default: mod.App })),
979
+ permissions: PERMISSIONS.main,
980
+ position: 2
971
981
  });
972
- app.addMiddlewares([() => releaseApi.middleware]);
973
- app.addReducers({
974
- [releaseApi.reducerPath]: releaseApi.reducer
975
- });
976
- app.injectContentManagerComponent("editView", "right-links", {
977
- name: `${pluginId}-link`,
978
- Component: CMReleasesContainer
982
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
983
+ if ("addEditViewSidePanel" in contentManagerPluginApis && typeof contentManagerPluginApis.addEditViewSidePanel === "function") {
984
+ contentManagerPluginApis.addEditViewSidePanel([Panel]);
985
+ }
986
+ if ("addDocumentAction" in contentManagerPluginApis && typeof contentManagerPluginApis.addDocumentAction === "function") {
987
+ contentManagerPluginApis.addDocumentAction((actions) => {
988
+ const indexOfDeleteAction = actions.findIndex((action) => action.type === "unpublish");
989
+ actions.splice(indexOfDeleteAction, 0, ReleaseActionModalForm);
990
+ return actions;
991
+ });
992
+ }
993
+ app.addSettingsLink("global", {
994
+ id: pluginId,
995
+ to: "releases",
996
+ intlLabel: {
997
+ id: `${pluginId}.plugin.name`,
998
+ defaultMessage: "Releases"
999
+ },
1000
+ permissions: [],
1001
+ async Component() {
1002
+ const { SettingsPage } = await import("./SettingsPage-w5dOMAtL.mjs");
1003
+ return { default: SettingsPage };
1004
+ }
979
1005
  });
980
1006
  } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
981
- app.addMenuLink({
982
- to: `/plugins/purchase-content-releases`,
983
- icon: PaperPlane,
1007
+ app.addSettingsLink("global", {
1008
+ id: pluginId,
1009
+ to: "/plugins/purchase-content-releases",
984
1010
  intlLabel: {
985
1011
  id: `${pluginId}.plugin.name`,
986
1012
  defaultMessage: "Releases"
987
1013
  },
1014
+ permissions: [],
988
1015
  async Component() {
989
- const { PurchaseContentReleases } = await import("./PurchaseContentReleases-Clm0iACO.mjs");
990
- return PurchaseContentReleases;
1016
+ const { PurchaseContentReleases } = await import("./PurchaseContentReleases-_MxP6-Dt.mjs");
1017
+ return { default: PurchaseContentReleases };
991
1018
  },
992
- lockIcon: true
1019
+ licenseOnly: true
993
1020
  });
994
1021
  }
995
1022
  },
996
1023
  async registerTrads({ locales }) {
997
1024
  const importedTrads = await Promise.all(
998
1025
  locales.map((locale) => {
999
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-RdapH-9X.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1026
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-ahPQUZv2.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1000
1027
  return {
1001
1028
  data: prefixPluginTranslations(data, "content-releases"),
1002
1029
  locale
@@ -1023,11 +1050,10 @@ export {
1023
1050
  useGetReleaseActionsQuery as f,
1024
1051
  getTimezoneOffset as g,
1025
1052
  useUpdateReleaseActionMutation as h,
1026
- isAxiosError as i,
1027
- ReleaseActionMenu as j,
1028
- admin as k,
1053
+ ReleaseActionMenu as i,
1054
+ admin as j,
1029
1055
  pluginId as p,
1030
1056
  releaseApi as r,
1031
1057
  useGetReleasesQuery as u
1032
1058
  };
1033
- //# sourceMappingURL=index-OD9AlD-6.mjs.map
1059
+ //# sourceMappingURL=index-LUuvped4.mjs.map