@strapi/content-releases 5.0.0-beta.9 → 5.0.0-rc.0

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 (98) hide show
  1. package/LICENSE +17 -1
  2. package/dist/_chunks/{App-D_6Y9N2F.mjs → App-6gbM0io-.mjs} +215 -255
  3. package/dist/_chunks/App-6gbM0io-.mjs.map +1 -0
  4. package/dist/_chunks/{App-DUmziQ17.js → App-zzUitryC.js} +216 -257
  5. package/dist/_chunks/App-zzUitryC.js.map +1 -0
  6. package/dist/_chunks/SettingsPage-CTOl3Qtw.js +157 -0
  7. package/dist/_chunks/SettingsPage-CTOl3Qtw.js.map +1 -0
  8. package/dist/_chunks/SettingsPage-CuSH193e.mjs +157 -0
  9. package/dist/_chunks/SettingsPage-CuSH193e.mjs.map +1 -0
  10. package/dist/_chunks/{en-DtFJ5ViE.js → en-1_1re1mc.js} +7 -2
  11. package/dist/_chunks/en-1_1re1mc.js.map +1 -0
  12. package/dist/_chunks/{en-B9Ur3VsE.mjs → en-C3sq5KNP.mjs} +7 -2
  13. package/dist/_chunks/en-C3sq5KNP.mjs.map +1 -0
  14. package/dist/_chunks/{index-C5Hc767q.js → index-BxRiXenX.js} +518 -437
  15. package/dist/_chunks/index-BxRiXenX.js.map +1 -0
  16. package/dist/_chunks/{index-BomF0-yY.mjs → index-CuchqQ4_.mjs} +525 -444
  17. package/dist/_chunks/index-CuchqQ4_.mjs.map +1 -0
  18. package/dist/_chunks/validation-schemas-C7P2rhPu.mjs +29 -0
  19. package/dist/_chunks/validation-schemas-C7P2rhPu.mjs.map +1 -0
  20. package/dist/_chunks/validation-schemas-bib1fBc7.js +47 -0
  21. package/dist/_chunks/validation-schemas-bib1fBc7.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/ReleaseModal.d.ts +2 -1
  27. package/dist/admin/src/components/ReleasesPanel.d.ts +3 -0
  28. package/dist/admin/src/pages/SettingsPage.d.ts +1 -0
  29. package/dist/admin/src/services/release.d.ts +37 -32
  30. package/dist/admin/src/utils/time.d.ts +9 -0
  31. package/dist/server/index.js +784 -600
  32. package/dist/server/index.js.map +1 -1
  33. package/dist/server/index.mjs +785 -601
  34. package/dist/server/index.mjs.map +1 -1
  35. package/dist/server/src/bootstrap.d.ts.map +1 -1
  36. package/dist/server/src/constants.d.ts +11 -2
  37. package/dist/server/src/constants.d.ts.map +1 -1
  38. package/dist/server/src/content-types/index.d.ts +3 -5
  39. package/dist/server/src/content-types/index.d.ts.map +1 -1
  40. package/dist/server/src/content-types/release-action/index.d.ts +3 -5
  41. package/dist/server/src/content-types/release-action/index.d.ts.map +1 -1
  42. package/dist/server/src/content-types/release-action/schema.d.ts +3 -5
  43. package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -1
  44. package/dist/server/src/controllers/index.d.ts +6 -3
  45. package/dist/server/src/controllers/index.d.ts.map +1 -1
  46. package/dist/server/src/controllers/release-action.d.ts +0 -1
  47. package/dist/server/src/controllers/release-action.d.ts.map +1 -1
  48. package/dist/server/src/controllers/release.d.ts +7 -2
  49. package/dist/server/src/controllers/release.d.ts.map +1 -1
  50. package/dist/server/src/controllers/settings.d.ts +11 -0
  51. package/dist/server/src/controllers/settings.d.ts.map +1 -0
  52. package/dist/server/src/controllers/validation/release-action.d.ts +7 -1
  53. package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -1
  54. package/dist/server/src/controllers/validation/release.d.ts +1 -0
  55. package/dist/server/src/controllers/validation/release.d.ts.map +1 -1
  56. package/dist/server/src/controllers/validation/settings.d.ts +2 -0
  57. package/dist/server/src/controllers/validation/settings.d.ts.map +1 -0
  58. package/dist/server/src/index.d.ts +66 -51
  59. package/dist/server/src/index.d.ts.map +1 -1
  60. package/dist/server/src/middlewares/documents.d.ts +6 -0
  61. package/dist/server/src/middlewares/documents.d.ts.map +1 -0
  62. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts +9 -0
  63. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts.map +1 -0
  64. package/dist/server/src/migrations/index.d.ts.map +1 -1
  65. package/dist/server/src/register.d.ts.map +1 -1
  66. package/dist/server/src/routes/index.d.ts +16 -0
  67. package/dist/server/src/routes/index.d.ts.map +1 -1
  68. package/dist/server/src/routes/release-action.d.ts.map +1 -1
  69. package/dist/server/src/routes/release.d.ts.map +1 -1
  70. package/dist/server/src/routes/settings.d.ts +18 -0
  71. package/dist/server/src/routes/settings.d.ts.map +1 -0
  72. package/dist/server/src/services/index.d.ts +38 -38
  73. package/dist/server/src/services/index.d.ts.map +1 -1
  74. package/dist/server/src/services/release-action.d.ts +36 -0
  75. package/dist/server/src/services/release-action.d.ts.map +1 -0
  76. package/dist/server/src/services/release.d.ts +6 -41
  77. package/dist/server/src/services/release.d.ts.map +1 -1
  78. package/dist/server/src/services/settings.d.ts +13 -0
  79. package/dist/server/src/services/settings.d.ts.map +1 -0
  80. package/dist/server/src/services/validation.d.ts +1 -1
  81. package/dist/server/src/services/validation.d.ts.map +1 -1
  82. package/dist/server/src/utils/index.d.ts +29 -8
  83. package/dist/server/src/utils/index.d.ts.map +1 -1
  84. package/dist/shared/contracts/release-actions.d.ts +6 -5
  85. package/dist/shared/contracts/release-actions.d.ts.map +1 -1
  86. package/dist/shared/contracts/releases.d.ts +6 -5
  87. package/dist/shared/contracts/releases.d.ts.map +1 -1
  88. package/dist/shared/contracts/settings.d.ts +39 -0
  89. package/dist/shared/contracts/settings.d.ts.map +1 -0
  90. package/dist/shared/validation-schemas.d.ts +1 -0
  91. package/dist/shared/validation-schemas.d.ts.map +1 -1
  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
@@ -1,8 +1,6 @@
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
5
  const strapiAdmin$1 = require("@strapi/content-manager/strapi-admin");
8
6
  const designSystem = require("@strapi/design-system");
@@ -12,6 +10,7 @@ const reactIntl = require("react-intl");
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,54 +537,262 @@ 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 }
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)) {
618
+ toggleNotification({
619
+ type: "danger",
620
+ message: formatAPIError(error)
621
+ });
622
+ } else {
623
+ toggleNotification({
624
+ type: "danger",
625
+ message: formatMessage({
626
+ id: "notification.error",
627
+ defaultMessage: "An error occurred"
628
+ })
629
+ });
630
+ }
631
+ }
632
+ };
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({
675
+ id: "content-releases.content-manager-edit-view.add-to-release",
676
+ defaultMessage: "Add to release"
677
+ }),
678
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Cursor, {}),
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(jsxRuntime.Fragment, { 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 getTimezoneOffset = (timezone, date) => {
718
+ try {
719
+ const offsetPart = new Intl.DateTimeFormat("en", {
720
+ timeZone: timezone,
721
+ timeZoneName: "longOffset"
722
+ }).formatToParts(date).find((part) => part.type === "timeZoneName");
723
+ const offset = offsetPart ? offsetPart.value : "";
724
+ let utcOffset = offset.replace("GMT", "UTC");
725
+ if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
726
+ utcOffset = `${utcOffset}+00:00`;
727
+ }
728
+ return utcOffset;
729
+ } catch (error) {
730
+ return "";
731
+ }
732
+ };
733
+ const getTimezones = (selectedDate) => {
734
+ const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
735
+ const utcOffset = getTimezoneOffset(timezone, selectedDate);
736
+ return { offset: utcOffset, value: `${utcOffset}&${timezone}` };
737
+ });
738
+ const systemTimezone = timezoneList.find(
739
+ (timezone) => timezone.value.split("&")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
740
+ );
741
+ return { timezoneList, systemTimezone };
742
+ };
743
+ const StyledMenuItem = styledComponents.styled(designSystem.Menu.Item)`
744
+ &:hover {
745
+ background: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}100`]};
746
+
747
+ svg {
748
+ fill: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}600`]};
749
+ }
750
+
751
+ a {
752
+ color: ${({ theme }) => theme.colors.neutral800};
753
+ }
754
+ }
755
+
756
+ svg {
757
+ color: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}500`]};
758
+ }
759
+
760
+ span {
761
+ color: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}800`]};
762
+ }
763
+
764
+ span,
765
+ a {
766
+ width: 100%;
767
+ }
768
+ `;
769
+ const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
770
+ const { formatMessage } = reactIntl.useIntl();
771
+ const { toggleNotification } = strapiAdmin.useNotification();
772
+ const { formatAPIError } = strapiAdmin.useAPIErrorHandler();
773
+ const [deleteReleaseAction] = useDeleteReleaseActionMutation();
774
+ const {
775
+ allowedActions: { canDeleteAction }
776
+ } = strapiAdmin.useRBAC(PERMISSIONS);
777
+ const handleDeleteAction = async () => {
778
+ const response = await deleteReleaseAction({
779
+ params: { releaseId, actionId }
695
780
  });
696
- if ("data" in response2) {
781
+ if ("data" in response) {
697
782
  toggleNotification({
698
783
  type: "success",
699
784
  message: formatMessage({
700
- id: "content-releases.content-manager-edit-view.add-to-release.notification.success",
701
- defaultMessage: "Entry added to release"
785
+ id: "content-releases.content-manager-edit-view.remove-from-release.notification.success",
786
+ defaultMessage: "Entry removed from release"
702
787
  })
703
788
  });
704
- handleClose();
705
789
  return;
706
790
  }
707
- if ("error" in response2) {
708
- if (strapiAdmin.isFetchError(response2.error)) {
791
+ if ("error" in response) {
792
+ if (strapiAdmin.isFetchError(response.error)) {
709
793
  toggleNotification({
710
794
  type: "danger",
711
- message: formatAPIError(response2.error)
795
+ message: formatAPIError(response.error)
712
796
  });
713
797
  } else {
714
798
  toggleNotification({
@@ -718,239 +802,214 @@ const AddActionToReleaseModal = ({
718
802
  }
719
803
  }
720
804
  };
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({
723
- id: "content-releases.content-manager-edit-view.add-to-release",
724
- defaultMessage: "Add to release"
725
- }) }) }),
726
- /* @__PURE__ */ jsxRuntime.jsx(
727
- formik.Formik,
805
+ if (!canDeleteAction) {
806
+ return null;
807
+ }
808
+ return /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { $variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
809
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Cross, { width: "1.6rem", height: "1.6rem" }),
810
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
811
+ id: "content-releases.content-manager-edit-view.remove-from-release",
812
+ defaultMessage: "Remove from release"
813
+ }) })
814
+ ] }) });
815
+ };
816
+ const ReleaseActionEntryLinkItem = ({
817
+ contentTypeUid,
818
+ documentId,
819
+ locale
820
+ }) => {
821
+ const { formatMessage } = reactIntl.useIntl();
822
+ const userPermissions = strapiAdmin.useAuth("ReleaseActionEntryLinkItem", (state) => state.permissions);
823
+ const canUpdateEntryForLocale = React__namespace.useMemo(() => {
824
+ const updatePermissions = userPermissions.find(
825
+ (permission) => permission.subject === contentTypeUid && permission.action === "plugin::content-manager.explorer.update"
826
+ );
827
+ if (!updatePermissions) {
828
+ return false;
829
+ }
830
+ return Boolean(!locale || updatePermissions.properties?.locales?.includes(locale));
831
+ }, [contentTypeUid, locale, userPermissions]);
832
+ const {
833
+ allowedActions: { canUpdate: canUpdateContentType }
834
+ } = strapiAdmin.useRBAC({
835
+ updateContentType: [
728
836
  {
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,
742
- {
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))
750
- }
751
- )
752
- ] }) }),
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",
771
- defaultMessage: "Cancel"
772
- }) }),
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
- }
837
+ action: "plugin::content-manager.explorer.update",
838
+ subject: contentTypeUid
787
839
  }
788
- )
789
- ] });
840
+ ]
841
+ });
842
+ if (!canUpdateContentType || !canUpdateEntryForLocale) {
843
+ return null;
844
+ }
845
+ return /* @__PURE__ */ jsxRuntime.jsx(
846
+ StyledMenuItem,
847
+ {
848
+ tag: reactRouterDom.NavLink,
849
+ isLink: true,
850
+ to: {
851
+ pathname: `/content-manager/collection-types/${contentTypeUid}/${documentId}`,
852
+ search: locale && `?plugins[i18n][locale]=${locale}`
853
+ },
854
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
855
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Pencil, { width: "1.6rem", height: "1.6rem" }),
856
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: formatMessage({
857
+ id: "content-releases.content-manager-edit-view.edit-entry",
858
+ defaultMessage: "Edit entry"
859
+ }) })
860
+ ] })
861
+ }
862
+ );
863
+ };
864
+ const EditReleaseItem = ({ releaseId }) => {
865
+ const { formatMessage } = reactIntl.useIntl();
866
+ return (
867
+ /* @ts-expect-error inference isn't working in DS */
868
+ /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { tag: reactRouterDom.NavLink, isLink: true, to: `/plugins/content-releases/${releaseId}`, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
869
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Pencil, { width: "1.6rem", height: "1.6rem" }),
870
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", variant: "omega", children: formatMessage({
871
+ id: "content-releases.content-manager-edit-view.edit-release",
872
+ defaultMessage: "Edit release"
873
+ }) })
874
+ ] }) })
875
+ );
876
+ };
877
+ const Root = ({ children }) => {
878
+ const { formatMessage } = reactIntl.useIntl();
879
+ const { allowedActions } = strapiAdmin.useRBAC(PERMISSIONS);
880
+ return (
881
+ // A user can access the dropdown if they have permissions to delete a release-action OR update a release
882
+ allowedActions.canDeleteAction || allowedActions.canUpdate ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { children: [
883
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Menu.Trigger, { variant: "tertiary", endIcon: null, paddingLeft: 2, paddingRight: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
884
+ designSystem.AccessibleIcon,
885
+ {
886
+ label: formatMessage({
887
+ id: "content-releases.content-manager-edit-view.release-action-menu",
888
+ defaultMessage: "Release action options"
889
+ }),
890
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {})
891
+ }
892
+ ) }),
893
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
894
+ ] }) : null
895
+ );
896
+ };
897
+ const ReleaseActionMenu = {
898
+ Root,
899
+ EditReleaseItem,
900
+ DeleteReleaseActionItem,
901
+ ReleaseActionEntryLinkItem
790
902
  };
791
- const CMReleasesContainer = () => {
792
- const [isModalOpen, setIsModalOpen] = React__namespace.useState(false);
903
+ const Panel = ({ model, documentId, collectionType }) => {
904
+ const [{ query }] = strapiAdmin.useQueryParams();
905
+ const locale = query.plugins?.i18n?.locale;
906
+ const {
907
+ edit: { options }
908
+ } = strapiAdmin$1.unstable_useDocumentLayout(model);
793
909
  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
910
  const { allowedActions } = strapiAdmin.useRBAC(PERMISSIONS);
798
- const { canCreateAction, canRead: canMain, canDeleteAction } = allowedActions;
799
- const { schema } = strapiAdmin$1.unstable_useDocument({
800
- collectionType,
801
- model: slug
802
- });
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,
911
+ const { canRead, canDeleteAction } = allowedActions;
912
+ const response = useGetReleasesForEntryQuery({
913
+ contentType: model,
914
+ entryDocumentId: documentId,
915
+ locale,
809
916
  hasEntryAttached: true
810
- } : query.skipToken;
811
- const response = useGetReleasesForEntryQuery(fetchParams);
917
+ });
812
918
  const releases = response.data?.data;
813
- if (!canFetch) {
814
- return null;
815
- }
816
- if (isCreatingEntry || !hasDraftAndPublish) {
817
- return null;
818
- }
819
- const toggleModal = () => setIsModalOpen((prev) => !prev);
820
919
  const getReleaseColorVariant = (actionType, shade) => {
821
920
  if (actionType === "unpublish") {
822
921
  return `secondary${shade}`;
823
922
  }
824
923
  return `success${shade}`;
825
924
  };
826
- if (!canMain) {
925
+ if (!window.strapi.isEE || !options?.draftAndPublish || !canRead) {
827
926
  return null;
828
927
  }
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,
928
+ if (collectionType === "collection-types" && (!documentId || documentId === "create")) {
929
+ return null;
930
+ }
931
+ if (releases && releases.length === 0) {
932
+ return null;
933
+ }
934
+ return {
935
+ title: formatMessage({
936
+ id: "content-releases.plugin.name",
937
+ defaultMessage: "Releases"
938
+ }),
939
+ content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 3, width: "100%", children: releases?.map((release) => /* @__PURE__ */ jsxRuntime.jsxs(
940
+ designSystem.Flex,
941
+ {
942
+ direction: "column",
943
+ alignItems: "start",
944
+ borderWidth: "1px",
945
+ borderStyle: "solid",
946
+ borderColor: getReleaseColorVariant(release.actions[0].type, "200"),
947
+ overflow: "hidden",
948
+ hasRadius: true,
949
+ children: [
950
+ /* @__PURE__ */ jsxRuntime.jsx(
951
+ designSystem.Box,
928
952
  {
929
- justifyContent: "center",
953
+ paddingTop: 3,
954
+ paddingBottom: 3,
930
955
  paddingLeft: 4,
931
956
  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
- })
957
+ background: getReleaseColorVariant(release.actions[0].type, "100"),
958
+ width: "100%",
959
+ children: /* @__PURE__ */ jsxRuntime.jsx(
960
+ designSystem.Typography,
961
+ {
962
+ fontSize: 1,
963
+ variant: "pi",
964
+ textColor: getReleaseColorVariant(release.actions[0].type, "600"),
965
+ children: formatMessage(
966
+ {
967
+ id: "content-releases.content-manager-edit-view.list-releases.title",
968
+ defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
969
+ },
970
+ { isPublish: release.actions[0].type === "publish" }
971
+ )
972
+ }
973
+ )
940
974
  }
941
- ) : null
942
- ] }),
943
- isModalOpen && /* @__PURE__ */ jsxRuntime.jsx(
944
- AddActionToReleaseModal,
945
- {
946
- handleClose: toggleModal,
947
- contentTypeUid,
948
- entryId
949
- }
950
- )
951
- ]
952
- }
953
- );
975
+ ),
976
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
977
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
978
+ release.scheduledAt && release.timezone && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
979
+ {
980
+ id: "content-releases.content-manager-edit-view.scheduled.date",
981
+ defaultMessage: "{date} at {time} ({offset})"
982
+ },
983
+ {
984
+ date: formatDate(new Date(release.scheduledAt), {
985
+ day: "2-digit",
986
+ month: "2-digit",
987
+ year: "numeric",
988
+ timeZone: release.timezone
989
+ }),
990
+ time: formatTime(new Date(release.scheduledAt), {
991
+ hourCycle: "h23",
992
+ timeZone: release.timezone
993
+ }),
994
+ offset: getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
995
+ }
996
+ ) }),
997
+ canDeleteAction ? /* @__PURE__ */ jsxRuntime.jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
998
+ /* @__PURE__ */ jsxRuntime.jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
999
+ /* @__PURE__ */ jsxRuntime.jsx(
1000
+ ReleaseActionMenu.DeleteReleaseActionItem,
1001
+ {
1002
+ releaseId: release.id,
1003
+ actionId: release.actions[0].id
1004
+ }
1005
+ )
1006
+ ] }) : null
1007
+ ] })
1008
+ ]
1009
+ },
1010
+ release.id
1011
+ )) })
1012
+ };
954
1013
  };
955
1014
  const pluginId = "content-releases";
956
1015
  const prefixPluginTranslations = (trad, pluginId2) => {
@@ -974,18 +1033,38 @@ const admin = {
974
1033
  id: `${pluginId}.plugin.name`,
975
1034
  defaultMessage: "Releases"
976
1035
  },
977
- Component: () => Promise.resolve().then(() => require("./App-DUmziQ17.js")).then((mod) => ({ default: mod.App })),
1036
+ Component: () => Promise.resolve().then(() => require("./App-zzUitryC.js")).then((mod) => ({ default: mod.App })),
978
1037
  permissions: PERMISSIONS.main,
979
1038
  position: 2
980
1039
  });
981
- app.getPlugin("content-manager").injectComponent("editView", "right-links", {
982
- name: `${pluginId}-link`,
983
- Component: CMReleasesContainer
1040
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
1041
+ if ("addEditViewSidePanel" in contentManagerPluginApis && typeof contentManagerPluginApis.addEditViewSidePanel === "function") {
1042
+ contentManagerPluginApis.addEditViewSidePanel([Panel]);
1043
+ }
1044
+ if ("addDocumentAction" in contentManagerPluginApis && typeof contentManagerPluginApis.addDocumentAction === "function") {
1045
+ contentManagerPluginApis.addDocumentAction((actions) => {
1046
+ const indexOfDeleteAction = actions.findIndex((action) => action.type === "unpublish");
1047
+ actions.splice(indexOfDeleteAction, 0, ReleaseActionModalForm);
1048
+ return actions;
1049
+ });
1050
+ }
1051
+ app.addSettingsLink("global", {
1052
+ id: pluginId,
1053
+ to: "releases",
1054
+ intlLabel: {
1055
+ id: `${pluginId}.plugin.name`,
1056
+ defaultMessage: "Releases"
1057
+ },
1058
+ permissions: [],
1059
+ async Component() {
1060
+ const { SettingsPage } = await Promise.resolve().then(() => require("./SettingsPage-CTOl3Qtw.js"));
1061
+ return { default: SettingsPage };
1062
+ }
984
1063
  });
985
1064
  } 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,
1065
+ app.addSettingsLink("global", {
1066
+ id: pluginId,
1067
+ to: "/plugins/purchase-content-releases",
989
1068
  intlLabel: {
990
1069
  id: `${pluginId}.plugin.name`,
991
1070
  defaultMessage: "Releases"
@@ -995,15 +1074,14 @@ const admin = {
995
1074
  const { PurchaseContentReleases } = await Promise.resolve().then(() => require("./PurchaseContentReleases-Be3acS2L.js"));
996
1075
  return { default: PurchaseContentReleases };
997
1076
  },
998
- lockIcon: true,
999
- position: 2
1077
+ licenseOnly: true
1000
1078
  });
1001
1079
  }
1002
1080
  },
1003
1081
  async registerTrads({ locales }) {
1004
1082
  const importedTrads = await Promise.all(
1005
1083
  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 }) => {
1084
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-1_1re1mc.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
1007
1085
  return {
1008
1086
  data: prefixPluginTranslations(data, "content-releases"),
1009
1087
  locale
@@ -1024,14 +1102,17 @@ exports.ReleaseActionMenu = ReleaseActionMenu;
1024
1102
  exports.ReleaseActionOptions = ReleaseActionOptions;
1025
1103
  exports.admin = admin;
1026
1104
  exports.getTimezoneOffset = getTimezoneOffset;
1105
+ exports.getTimezones = getTimezones;
1027
1106
  exports.pluginId = pluginId;
1028
1107
  exports.releaseApi = releaseApi;
1029
1108
  exports.useCreateReleaseMutation = useCreateReleaseMutation;
1030
1109
  exports.useDeleteReleaseMutation = useDeleteReleaseMutation;
1031
1110
  exports.useGetReleaseActionsQuery = useGetReleaseActionsQuery;
1032
1111
  exports.useGetReleaseQuery = useGetReleaseQuery;
1112
+ exports.useGetReleaseSettingsQuery = useGetReleaseSettingsQuery;
1033
1113
  exports.useGetReleasesQuery = useGetReleasesQuery;
1034
1114
  exports.usePublishReleaseMutation = usePublishReleaseMutation;
1035
1115
  exports.useUpdateReleaseActionMutation = useUpdateReleaseActionMutation;
1036
1116
  exports.useUpdateReleaseMutation = useUpdateReleaseMutation;
1037
- //# sourceMappingURL=index-C5Hc767q.js.map
1117
+ exports.useUpdateReleaseSettingsMutation = useUpdateReleaseSettingsMutation;
1118
+ //# sourceMappingURL=index-BxRiXenX.js.map