@strapi/content-releases 0.0.0-experimental.c3e9d4b26f9fd3d9eb530b5c11f9baa1d09b13ad → 0.0.0-experimental.c5235059f5636c4549ea2118c75c43b92e2615c8

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