@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,16 +1,15 @@
1
- import { Cross, Pencil, More, Plus, PaperPlane } from "@strapi/icons";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import * as React from "react";
4
- import { skipToken } from "@reduxjs/toolkit/query";
5
- import { adminApi, useNotification, useAPIErrorHandler, useRBAC, useAuth, isFetchError, useQueryParams } from "@strapi/admin/strapi-admin";
6
- import { unstable_useDocument } from "@strapi/content-manager/strapi-admin";
7
- import { Menu, Flex, Typography, AccessibleIcon, Field, VisuallyHidden, Box, Button, ModalLayout, ModalHeader, ModalBody, SingleSelect, SingleSelectOption, ModalFooter, EmptyStateLayout, LinkButton } from "@strapi/design-system";
1
+ import { Cursor, Cross, Pencil, More, PaperPlane } from "@strapi/icons";
2
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
3
+ import { adminApi, useRBAC, useNotification, useAPIErrorHandler, useQueryParams, isFetchError, useAuth } from "@strapi/admin/strapi-admin";
4
+ import { unstable_useDocumentLayout } from "@strapi/content-manager/strapi-admin";
5
+ import { Field, Flex, VisuallyHidden, Button, Box, SingleSelect, SingleSelectOption, EmptyStateLayout, LinkButton, Menu, Typography, AccessibleIcon } from "@strapi/design-system";
8
6
  import { EmptyDocuments } from "@strapi/icons/symbols";
9
- import { Formik, Form } from "formik";
7
+ import { useFormik } from "formik";
10
8
  import { useIntl } from "react-intl";
11
- import { Link, useParams } from "react-router-dom";
9
+ import { Link, NavLink } from "react-router-dom";
12
10
  import * as yup from "yup";
13
11
  import { styled } from "styled-components";
12
+ import * as React from "react";
14
13
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
15
14
  const v = glob[path];
16
15
  if (v) {
@@ -92,15 +91,52 @@ const PERMISSIONS = {
92
91
  }
93
92
  ]
94
93
  };
94
+ const extendInvalidatesTags = (endpoint, extraTags) => {
95
+ if (!endpoint) {
96
+ return;
97
+ }
98
+ const originalInvalidatesTags = endpoint.invalidatesTags;
99
+ const newInvalidatesTags = (result, err, args, meta) => {
100
+ const originalTags = typeof originalInvalidatesTags === "function" ? originalInvalidatesTags(result, err, args, meta) : originalInvalidatesTags;
101
+ return [...originalTags ?? [], ...extraTags];
102
+ };
103
+ Object.assign(endpoint, { invalidatesTags: newInvalidatesTags });
104
+ };
95
105
  const releaseApi = adminApi.enhanceEndpoints({
96
- addTagTypes: ["Release", "ReleaseAction", "EntriesInRelease"]
106
+ addTagTypes: ["Release", "ReleaseAction", "EntriesInRelease", "ReleaseSettings"],
107
+ endpoints: {
108
+ updateDocument(endpoint) {
109
+ extendInvalidatesTags(endpoint, [
110
+ { type: "Release", id: "LIST" },
111
+ { type: "ReleaseAction", id: "LIST" }
112
+ ]);
113
+ },
114
+ deleteDocument(endpoint) {
115
+ extendInvalidatesTags(endpoint, [
116
+ { type: "Release", id: "LIST" },
117
+ { type: "ReleaseAction", id: "LIST" }
118
+ ]);
119
+ },
120
+ deleteManyDocuments(endpoint) {
121
+ extendInvalidatesTags(endpoint, [
122
+ { type: "Release", id: "LIST" },
123
+ { type: "ReleaseAction", id: "LIST" }
124
+ ]);
125
+ },
126
+ discardDocument(endpoint) {
127
+ extendInvalidatesTags(endpoint, [
128
+ { type: "Release", id: "LIST" },
129
+ { type: "ReleaseAction", id: "LIST" }
130
+ ]);
131
+ }
132
+ }
97
133
  }).injectEndpoints({
98
134
  endpoints: (build) => {
99
135
  return {
100
136
  getReleasesForEntry: build.query({
101
137
  query(params) {
102
138
  return {
103
- url: "/content-releases",
139
+ url: "/content-releases/getByDocumentAttached",
104
140
  method: "GET",
105
141
  config: {
106
142
  params
@@ -303,6 +339,20 @@ const releaseApi = adminApi.enhanceEndpoints({
303
339
  return response.data;
304
340
  },
305
341
  providesTags: [{ type: "EntriesInRelease" }]
342
+ }),
343
+ getReleaseSettings: build.query({
344
+ query: () => "/content-releases/settings",
345
+ providesTags: [{ type: "ReleaseSettings" }]
346
+ }),
347
+ updateReleaseSettings: build.mutation({
348
+ query(data) {
349
+ return {
350
+ url: "/content-releases/settings",
351
+ method: "PUT",
352
+ data
353
+ };
354
+ },
355
+ invalidatesTags: (result, error, arg) => [{ type: "ReleaseSettings" }]
306
356
  })
307
357
  };
308
358
  }
@@ -320,184 +370,10 @@ const {
320
370
  usePublishReleaseMutation,
321
371
  useDeleteReleaseActionMutation,
322
372
  useDeleteReleaseMutation,
323
- useGetMappedEntriesInReleasesQuery
373
+ useGetMappedEntriesInReleasesQuery,
374
+ useGetReleaseSettingsQuery,
375
+ useUpdateReleaseSettingsMutation
324
376
  } = releaseApi;
325
- const getTimezoneOffset = (timezone, date) => {
326
- try {
327
- const offsetPart = new Intl.DateTimeFormat("en", {
328
- timeZone: timezone,
329
- timeZoneName: "longOffset"
330
- }).formatToParts(date).find((part) => part.type === "timeZoneName");
331
- const offset = offsetPart ? offsetPart.value : "";
332
- let utcOffset = offset.replace("GMT", "UTC");
333
- if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
334
- utcOffset = `${utcOffset}+00:00`;
335
- }
336
- return utcOffset;
337
- } catch (error) {
338
- return "";
339
- }
340
- };
341
- const StyledMenuItem = styled(Menu.Item)`
342
- &:hover {
343
- background: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}100`]};
344
-
345
- svg {
346
- fill: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}600`]};
347
- }
348
-
349
- a {
350
- color: ${({ theme }) => theme.colors.neutral800};
351
- }
352
- }
353
-
354
- svg {
355
- fill: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}600`]};
356
- }
357
-
358
- a {
359
- color: ${({ theme }) => theme.colors.neutral800};
360
- }
361
-
362
- span,
363
- a {
364
- width: 100%;
365
- }
366
- `;
367
- const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
368
- const { formatMessage } = useIntl();
369
- const { toggleNotification } = useNotification();
370
- const { formatAPIError } = useAPIErrorHandler();
371
- const [deleteReleaseAction] = useDeleteReleaseActionMutation();
372
- const {
373
- allowedActions: { canDeleteAction }
374
- } = useRBAC(PERMISSIONS);
375
- const handleDeleteAction = async () => {
376
- const response = await deleteReleaseAction({
377
- params: { releaseId, actionId }
378
- });
379
- if ("data" in response) {
380
- toggleNotification({
381
- type: "success",
382
- message: formatMessage({
383
- id: "content-releases.content-manager-edit-view.remove-from-release.notification.success",
384
- defaultMessage: "Entry removed from release"
385
- })
386
- });
387
- return;
388
- }
389
- if ("error" in response) {
390
- if (isFetchError(response.error)) {
391
- toggleNotification({
392
- type: "danger",
393
- message: formatAPIError(response.error)
394
- });
395
- } else {
396
- toggleNotification({
397
- type: "danger",
398
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
399
- });
400
- }
401
- }
402
- };
403
- if (!canDeleteAction) {
404
- return null;
405
- }
406
- return /* @__PURE__ */ jsx(StyledMenuItem, { $variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
407
- /* @__PURE__ */ jsx(Cross, { width: "1.6rem", height: "1.6rem" }),
408
- /* @__PURE__ */ jsx(Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
409
- id: "content-releases.content-manager-edit-view.remove-from-release",
410
- defaultMessage: "Remove from release"
411
- }) })
412
- ] }) });
413
- };
414
- const ReleaseActionEntryLinkItem = ({
415
- contentTypeUid,
416
- entryId,
417
- locale
418
- }) => {
419
- const { formatMessage } = useIntl();
420
- const userPermissions = useAuth("ReleaseActionEntryLinkItem", (state) => state.permissions);
421
- const canUpdateEntryForLocale = React.useMemo(() => {
422
- const updatePermissions = userPermissions.find(
423
- (permission) => permission.subject === contentTypeUid && permission.action === "plugin::content-manager.explorer.update"
424
- );
425
- if (!updatePermissions) {
426
- return false;
427
- }
428
- return Boolean(!locale || updatePermissions.properties?.locales?.includes(locale));
429
- }, [contentTypeUid, locale, userPermissions]);
430
- const {
431
- allowedActions: { canUpdate: canUpdateContentType }
432
- } = useRBAC({
433
- updateContentType: [
434
- {
435
- action: "plugin::content-manager.explorer.update",
436
- subject: contentTypeUid
437
- }
438
- ]
439
- });
440
- if (!canUpdateContentType || !canUpdateEntryForLocale) {
441
- return null;
442
- }
443
- return /* @__PURE__ */ jsx(
444
- StyledMenuItem,
445
- {
446
- tag: Link,
447
- isLink: true,
448
- to: {
449
- pathname: `/content-manager/collection-types/${contentTypeUid}/${entryId}`,
450
- search: locale && `?plugins[i18n][locale]=${locale}`
451
- },
452
- children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
453
- /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
454
- /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
455
- id: "content-releases.content-manager-edit-view.edit-entry",
456
- defaultMessage: "Edit entry"
457
- }) })
458
- ] })
459
- }
460
- );
461
- };
462
- const EditReleaseItem = ({ releaseId }) => {
463
- const { formatMessage } = useIntl();
464
- return (
465
- /* @ts-expect-error inference isn't working in DS */
466
- /* @__PURE__ */ jsx(StyledMenuItem, { tag: Link, isLink: true, to: `/plugins/content-releases/${releaseId}`, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
467
- /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
468
- /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
469
- id: "content-releases.content-manager-edit-view.edit-release",
470
- defaultMessage: "Edit release"
471
- }) })
472
- ] }) })
473
- );
474
- };
475
- const Root = ({ children }) => {
476
- const { formatMessage } = useIntl();
477
- const { allowedActions } = useRBAC(PERMISSIONS);
478
- return (
479
- // A user can access the dropdown if they have permissions to delete a release-action OR update a release
480
- allowedActions.canDeleteAction || allowedActions.canUpdate ? /* @__PURE__ */ jsxs(Menu.Root, { children: [
481
- /* @__PURE__ */ jsx(Menu.Trigger, { paddingLeft: 2, paddingRight: 2, children: /* @__PURE__ */ jsx(
482
- AccessibleIcon,
483
- {
484
- label: formatMessage({
485
- id: "content-releases.content-manager-edit-view.release-action-menu",
486
- defaultMessage: "Release action options"
487
- }),
488
- children: /* @__PURE__ */ jsx(More, {})
489
- }
490
- ) }),
491
- /* @__PURE__ */ jsx(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
492
- ] }) : null
493
- );
494
- };
495
- const ReleaseActionMenu = {
496
- Root,
497
- EditReleaseItem,
498
- DeleteReleaseActionItem,
499
- ReleaseActionEntryLinkItem
500
- };
501
377
  const getBorderLeftRadiusValue = (actionType) => {
502
378
  return actionType === "publish" ? 1 : 0;
503
379
  };
@@ -640,54 +516,262 @@ const NoReleases = () => {
640
516
  defaultMessage: "Open the list of releases"
641
517
  })
642
518
  }
643
- )
519
+ ),
520
+ shadow: "none"
644
521
  }
645
522
  );
646
523
  };
647
524
  const AddActionToReleaseModal = ({
648
- handleClose,
649
- contentTypeUid,
650
- entryId
525
+ contentType,
526
+ documentId,
527
+ onInputChange,
528
+ values
651
529
  }) => {
652
- const releaseHeaderId = React.useId();
653
530
  const { formatMessage } = useIntl();
654
- const { toggleNotification } = useNotification();
655
- const { formatAPIError } = useAPIErrorHandler();
656
531
  const [{ query }] = useQueryParams();
657
532
  const locale = query.plugins?.i18n?.locale;
658
533
  const response = useGetReleasesForEntryQuery({
659
- contentTypeUid,
660
- entryId,
661
- hasEntryAttached: false
534
+ contentType,
535
+ entryDocumentId: documentId,
536
+ hasEntryAttached: false,
537
+ locale
662
538
  });
663
539
  const releases = response.data?.data;
540
+ if (releases?.length === 0) {
541
+ return /* @__PURE__ */ jsx(NoReleases, {});
542
+ }
543
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
544
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxs(Field.Root, { required: true, children: [
545
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
546
+ id: "content-releases.content-manager-edit-view.add-to-release.select-label",
547
+ defaultMessage: "Select a release"
548
+ }) }),
549
+ /* @__PURE__ */ jsx(
550
+ SingleSelect,
551
+ {
552
+ required: true,
553
+ placeholder: formatMessage({
554
+ id: "content-releases.content-manager-edit-view.add-to-release.select-placeholder",
555
+ defaultMessage: "Select"
556
+ }),
557
+ name: "releaseId",
558
+ onChange: (value) => onInputChange("releaseId", value),
559
+ value: values.releaseId,
560
+ children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
561
+ }
562
+ )
563
+ ] }) }),
564
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
565
+ id: "content-releases.content-manager-edit-view.add-to-release.action-type-label",
566
+ defaultMessage: "What do you want to do with this entry?"
567
+ }) }),
568
+ /* @__PURE__ */ jsx(
569
+ ReleaseActionOptions,
570
+ {
571
+ selected: values.type,
572
+ handleChange: (e) => onInputChange("type", e.target.value),
573
+ name: "type"
574
+ }
575
+ )
576
+ ] });
577
+ };
578
+ const ReleaseActionModalForm = ({
579
+ documentId,
580
+ model,
581
+ collectionType
582
+ }) => {
583
+ const { formatMessage } = useIntl();
584
+ const { allowedActions } = useRBAC(PERMISSIONS);
585
+ const { canCreateAction } = allowedActions;
664
586
  const [createReleaseAction, { isLoading }] = useCreateReleaseActionMutation();
665
- const handleSubmit = async (values) => {
666
- const releaseActionEntry = {
667
- contentType: contentTypeUid,
668
- id: entryId,
669
- locale
670
- };
671
- const response2 = await createReleaseAction({
672
- body: { type: values.type, entry: releaseActionEntry },
673
- params: { releaseId: values.releaseId }
587
+ const { toggleNotification } = useNotification();
588
+ const { formatAPIError } = useAPIErrorHandler();
589
+ const [{ query }] = useQueryParams();
590
+ const locale = query.plugins?.i18n?.locale;
591
+ const handleSubmit = async (e, onClose) => {
592
+ try {
593
+ await formik.handleSubmit(e);
594
+ onClose();
595
+ } catch (error) {
596
+ if (isFetchError(error)) {
597
+ toggleNotification({
598
+ type: "danger",
599
+ message: formatAPIError(error)
600
+ });
601
+ } else {
602
+ toggleNotification({
603
+ type: "danger",
604
+ message: formatMessage({
605
+ id: "notification.error",
606
+ defaultMessage: "An error occurred"
607
+ })
608
+ });
609
+ }
610
+ }
611
+ };
612
+ const formik = useFormik({
613
+ initialValues: INITIAL_VALUES,
614
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
615
+ onSubmit: async (values) => {
616
+ if (collectionType === "collection-types" && !documentId) {
617
+ throw new Error("Document id is required");
618
+ }
619
+ const response = await createReleaseAction({
620
+ body: {
621
+ type: values.type,
622
+ contentType: model,
623
+ entryDocumentId: documentId,
624
+ locale
625
+ },
626
+ params: { releaseId: values.releaseId }
627
+ });
628
+ if ("data" in response) {
629
+ toggleNotification({
630
+ type: "success",
631
+ message: formatMessage({
632
+ id: "content-releases.content-manager-edit-view.add-to-release.notification.success",
633
+ defaultMessage: "Entry added to release"
634
+ })
635
+ });
636
+ return;
637
+ }
638
+ if ("error" in response) {
639
+ throw response.error;
640
+ }
641
+ }
642
+ });
643
+ const {
644
+ edit: { options }
645
+ } = unstable_useDocumentLayout(model);
646
+ if (!window.strapi.isEE || !options?.draftAndPublish || !canCreateAction) {
647
+ return null;
648
+ }
649
+ if (collectionType === "collection-types" && (!documentId || documentId === "create")) {
650
+ return null;
651
+ }
652
+ return {
653
+ label: formatMessage({
654
+ id: "content-releases.content-manager-edit-view.add-to-release",
655
+ defaultMessage: "Add to release"
656
+ }),
657
+ icon: /* @__PURE__ */ jsx(Cursor, {}),
658
+ position: ["panel", "table-row"],
659
+ dialog: {
660
+ type: "modal",
661
+ title: formatMessage({
662
+ id: "content-releases.content-manager-edit-view.add-to-release",
663
+ defaultMessage: "Add to release"
664
+ }),
665
+ content: /* @__PURE__ */ jsx(
666
+ AddActionToReleaseModal,
667
+ {
668
+ contentType: model,
669
+ documentId,
670
+ onInputChange: formik.setFieldValue,
671
+ values: formik.values
672
+ }
673
+ ),
674
+ footer: ({ onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [
675
+ /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
676
+ id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
677
+ defaultMessage: "Cancel"
678
+ }) }),
679
+ /* @__PURE__ */ jsx(
680
+ Button,
681
+ {
682
+ type: "submit",
683
+ onClick: (e) => handleSubmit(e, onClose),
684
+ disabled: !formik.values.releaseId,
685
+ loading: isLoading,
686
+ children: formatMessage({
687
+ id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
688
+ defaultMessage: "Continue"
689
+ })
690
+ }
691
+ )
692
+ ] })
693
+ }
694
+ };
695
+ };
696
+ const getTimezoneOffset = (timezone, date) => {
697
+ try {
698
+ const offsetPart = new Intl.DateTimeFormat("en", {
699
+ timeZone: timezone,
700
+ timeZoneName: "longOffset"
701
+ }).formatToParts(date).find((part) => part.type === "timeZoneName");
702
+ const offset = offsetPart ? offsetPart.value : "";
703
+ let utcOffset = offset.replace("GMT", "UTC");
704
+ if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
705
+ utcOffset = `${utcOffset}+00:00`;
706
+ }
707
+ return utcOffset;
708
+ } catch (error) {
709
+ return "";
710
+ }
711
+ };
712
+ const getTimezones = (selectedDate) => {
713
+ const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
714
+ const utcOffset = getTimezoneOffset(timezone, selectedDate);
715
+ return { offset: utcOffset, value: `${utcOffset}&${timezone}` };
716
+ });
717
+ const systemTimezone = timezoneList.find(
718
+ (timezone) => timezone.value.split("&")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
719
+ );
720
+ return { timezoneList, systemTimezone };
721
+ };
722
+ const StyledMenuItem = styled(Menu.Item)`
723
+ &:hover {
724
+ background: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}100`]};
725
+
726
+ svg {
727
+ fill: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}600`]};
728
+ }
729
+
730
+ a {
731
+ color: ${({ theme }) => theme.colors.neutral800};
732
+ }
733
+ }
734
+
735
+ svg {
736
+ color: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}500`]};
737
+ }
738
+
739
+ span {
740
+ color: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}800`]};
741
+ }
742
+
743
+ span,
744
+ a {
745
+ width: 100%;
746
+ }
747
+ `;
748
+ const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
749
+ const { formatMessage } = useIntl();
750
+ const { toggleNotification } = useNotification();
751
+ const { formatAPIError } = useAPIErrorHandler();
752
+ const [deleteReleaseAction] = useDeleteReleaseActionMutation();
753
+ const {
754
+ allowedActions: { canDeleteAction }
755
+ } = useRBAC(PERMISSIONS);
756
+ const handleDeleteAction = async () => {
757
+ const response = await deleteReleaseAction({
758
+ params: { releaseId, actionId }
674
759
  });
675
- if ("data" in response2) {
760
+ if ("data" in response) {
676
761
  toggleNotification({
677
762
  type: "success",
678
763
  message: formatMessage({
679
- id: "content-releases.content-manager-edit-view.add-to-release.notification.success",
680
- defaultMessage: "Entry added to release"
764
+ id: "content-releases.content-manager-edit-view.remove-from-release.notification.success",
765
+ defaultMessage: "Entry removed from release"
681
766
  })
682
767
  });
683
- handleClose();
684
768
  return;
685
769
  }
686
- if ("error" in response2) {
687
- if (isFetchError(response2.error)) {
770
+ if ("error" in response) {
771
+ if (isFetchError(response.error)) {
688
772
  toggleNotification({
689
773
  type: "danger",
690
- message: formatAPIError(response2.error)
774
+ message: formatAPIError(response.error)
691
775
  });
692
776
  } else {
693
777
  toggleNotification({
@@ -697,239 +781,214 @@ const AddActionToReleaseModal = ({
697
781
  }
698
782
  }
699
783
  };
700
- return /* @__PURE__ */ jsxs(ModalLayout, { onClose: handleClose, labelledBy: releaseHeaderId, children: [
701
- /* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { id: releaseHeaderId, fontWeight: "bold", textColor: "neutral800", children: formatMessage({
702
- id: "content-releases.content-manager-edit-view.add-to-release",
703
- defaultMessage: "Add to release"
704
- }) }) }),
705
- /* @__PURE__ */ jsx(
706
- Formik,
784
+ if (!canDeleteAction) {
785
+ return null;
786
+ }
787
+ return /* @__PURE__ */ jsx(StyledMenuItem, { $variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
788
+ /* @__PURE__ */ jsx(Cross, { width: "1.6rem", height: "1.6rem" }),
789
+ /* @__PURE__ */ jsx(Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
790
+ id: "content-releases.content-manager-edit-view.remove-from-release",
791
+ defaultMessage: "Remove from release"
792
+ }) })
793
+ ] }) });
794
+ };
795
+ const ReleaseActionEntryLinkItem = ({
796
+ contentTypeUid,
797
+ documentId,
798
+ locale
799
+ }) => {
800
+ const { formatMessage } = useIntl();
801
+ const userPermissions = useAuth("ReleaseActionEntryLinkItem", (state) => state.permissions);
802
+ const canUpdateEntryForLocale = React.useMemo(() => {
803
+ const updatePermissions = userPermissions.find(
804
+ (permission) => permission.subject === contentTypeUid && permission.action === "plugin::content-manager.explorer.update"
805
+ );
806
+ if (!updatePermissions) {
807
+ return false;
808
+ }
809
+ return Boolean(!locale || updatePermissions.properties?.locales?.includes(locale));
810
+ }, [contentTypeUid, locale, userPermissions]);
811
+ const {
812
+ allowedActions: { canUpdate: canUpdateContentType }
813
+ } = useRBAC({
814
+ updateContentType: [
707
815
  {
708
- onSubmit: handleSubmit,
709
- validationSchema: RELEASE_ACTION_FORM_SCHEMA,
710
- initialValues: INITIAL_VALUES,
711
- children: ({ values, setFieldValue }) => {
712
- return /* @__PURE__ */ jsxs(Form, { children: [
713
- releases?.length === 0 ? /* @__PURE__ */ jsx(NoReleases, {}) : /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
714
- /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxs(Field.Root, { required: true, children: [
715
- /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
716
- id: "content-releases.content-manager-edit-view.add-to-release.select-label",
717
- defaultMessage: "Select a release"
718
- }) }),
719
- /* @__PURE__ */ jsx(
720
- SingleSelect,
721
- {
722
- placeholder: formatMessage({
723
- id: "content-releases.content-manager-edit-view.add-to-release.select-placeholder",
724
- defaultMessage: "Select"
725
- }),
726
- onChange: (value) => setFieldValue("releaseId", value),
727
- value: values.releaseId,
728
- children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
729
- }
730
- )
731
- ] }) }),
732
- /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
733
- id: "content-releases.content-manager-edit-view.add-to-release.action-type-label",
734
- defaultMessage: "What do you want to do with this entry?"
735
- }) }),
736
- /* @__PURE__ */ jsx(
737
- ReleaseActionOptions,
738
- {
739
- selected: values.type,
740
- handleChange: (e) => setFieldValue("type", e.target.value),
741
- name: "type"
742
- }
743
- )
744
- ] }) }),
745
- /* @__PURE__ */ jsx(
746
- ModalFooter,
747
- {
748
- startActions: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({
749
- id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
750
- defaultMessage: "Cancel"
751
- }) }),
752
- endActions: (
753
- /**
754
- * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
755
- * for yup.string().required(), even when the value is falsy (including empty string)
756
- */
757
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
758
- id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
759
- defaultMessage: "Continue"
760
- }) })
761
- )
762
- }
763
- )
764
- ] });
765
- }
816
+ action: "plugin::content-manager.explorer.update",
817
+ subject: contentTypeUid
766
818
  }
767
- )
768
- ] });
819
+ ]
820
+ });
821
+ if (!canUpdateContentType || !canUpdateEntryForLocale) {
822
+ return null;
823
+ }
824
+ return /* @__PURE__ */ jsx(
825
+ StyledMenuItem,
826
+ {
827
+ tag: NavLink,
828
+ isLink: true,
829
+ to: {
830
+ pathname: `/content-manager/collection-types/${contentTypeUid}/${documentId}`,
831
+ search: locale && `?plugins[i18n][locale]=${locale}`
832
+ },
833
+ children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
834
+ /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
835
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
836
+ id: "content-releases.content-manager-edit-view.edit-entry",
837
+ defaultMessage: "Edit entry"
838
+ }) })
839
+ ] })
840
+ }
841
+ );
842
+ };
843
+ const EditReleaseItem = ({ releaseId }) => {
844
+ const { formatMessage } = useIntl();
845
+ return (
846
+ /* @ts-expect-error inference isn't working in DS */
847
+ /* @__PURE__ */ jsx(StyledMenuItem, { tag: NavLink, isLink: true, to: `/plugins/content-releases/${releaseId}`, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
848
+ /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" }),
849
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", variant: "omega", children: formatMessage({
850
+ id: "content-releases.content-manager-edit-view.edit-release",
851
+ defaultMessage: "Edit release"
852
+ }) })
853
+ ] }) })
854
+ );
769
855
  };
770
- const CMReleasesContainer = () => {
771
- const [isModalOpen, setIsModalOpen] = React.useState(false);
856
+ const Root = ({ children }) => {
857
+ const { formatMessage } = useIntl();
858
+ const { allowedActions } = useRBAC(PERMISSIONS);
859
+ return (
860
+ // A user can access the dropdown if they have permissions to delete a release-action OR update a release
861
+ allowedActions.canDeleteAction || allowedActions.canUpdate ? /* @__PURE__ */ jsxs(Menu.Root, { children: [
862
+ /* @__PURE__ */ jsx(Menu.Trigger, { variant: "tertiary", endIcon: null, paddingLeft: 2, paddingRight: 2, children: /* @__PURE__ */ jsx(
863
+ AccessibleIcon,
864
+ {
865
+ label: formatMessage({
866
+ id: "content-releases.content-manager-edit-view.release-action-menu",
867
+ defaultMessage: "Release action options"
868
+ }),
869
+ children: /* @__PURE__ */ jsx(More, {})
870
+ }
871
+ ) }),
872
+ /* @__PURE__ */ jsx(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
873
+ ] }) : null
874
+ );
875
+ };
876
+ const ReleaseActionMenu = {
877
+ Root,
878
+ EditReleaseItem,
879
+ DeleteReleaseActionItem,
880
+ ReleaseActionEntryLinkItem
881
+ };
882
+ const Panel = ({ model, documentId, collectionType }) => {
883
+ const [{ query }] = useQueryParams();
884
+ const locale = query.plugins?.i18n?.locale;
885
+ const {
886
+ edit: { options }
887
+ } = unstable_useDocumentLayout(model);
772
888
  const { formatMessage, formatDate, formatTime } = useIntl();
773
- const { id, slug, collectionType } = useParams();
774
- const isCreatingEntry = id === "create";
775
- const entryId = parseInt(id, 10);
776
889
  const { allowedActions } = useRBAC(PERMISSIONS);
777
- const { canCreateAction, canRead: canMain, canDeleteAction } = allowedActions;
778
- const { schema } = unstable_useDocument({
779
- collectionType,
780
- model: slug
781
- });
782
- const hasDraftAndPublish = schema?.options?.draftAndPublish;
783
- const contentTypeUid = slug;
784
- const canFetch = id != null && contentTypeUid != null;
785
- const fetchParams = canFetch ? {
786
- contentTypeUid,
787
- entryId,
890
+ const { canRead, canDeleteAction } = allowedActions;
891
+ const response = useGetReleasesForEntryQuery({
892
+ contentType: model,
893
+ entryDocumentId: documentId,
894
+ locale,
788
895
  hasEntryAttached: true
789
- } : skipToken;
790
- const response = useGetReleasesForEntryQuery(fetchParams);
896
+ });
791
897
  const releases = response.data?.data;
792
- if (!canFetch) {
793
- return null;
794
- }
795
- if (isCreatingEntry || !hasDraftAndPublish) {
796
- return null;
797
- }
798
- const toggleModal = () => setIsModalOpen((prev) => !prev);
799
898
  const getReleaseColorVariant = (actionType, shade) => {
800
899
  if (actionType === "unpublish") {
801
900
  return `secondary${shade}`;
802
901
  }
803
902
  return `success${shade}`;
804
903
  };
805
- if (!canMain) {
904
+ if (!window.strapi.isEE || !options?.draftAndPublish || !canRead) {
806
905
  return null;
807
906
  }
808
- return /* @__PURE__ */ jsxs(
809
- Box,
810
- {
811
- tag: "aside",
812
- "aria-label": formatMessage({
813
- id: "content-releases.plugin.name",
814
- defaultMessage: "Releases"
815
- }),
816
- background: "neutral0",
817
- borderColor: "neutral150",
818
- hasRadius: true,
819
- padding: 4,
820
- shadow: "tableShadow",
821
- children: [
822
- /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
823
- /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", children: formatMessage({
824
- id: "content-releases.plugin.name",
825
- defaultMessage: "Releases"
826
- }) }),
827
- releases?.map((release) => {
828
- return /* @__PURE__ */ jsxs(
829
- Flex,
830
- {
831
- direction: "column",
832
- alignItems: "start",
833
- borderWidth: "1px",
834
- borderStyle: "solid",
835
- borderColor: getReleaseColorVariant(release.actions[0].type, "200"),
836
- overflow: "hidden",
837
- hasRadius: true,
838
- children: [
839
- /* @__PURE__ */ jsx(
840
- Box,
841
- {
842
- paddingTop: 3,
843
- paddingBottom: 3,
844
- paddingLeft: 4,
845
- paddingRight: 4,
846
- background: getReleaseColorVariant(release.actions[0].type, "100"),
847
- width: "100%",
848
- children: /* @__PURE__ */ jsx(
849
- Typography,
850
- {
851
- fontSize: 1,
852
- variant: "pi",
853
- textColor: getReleaseColorVariant(release.actions[0].type, "600"),
854
- children: formatMessage(
855
- {
856
- id: "content-releases.content-manager-edit-view.list-releases.title",
857
- defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
858
- },
859
- { isPublish: release.actions[0].type === "publish" }
860
- )
861
- }
862
- )
863
- }
864
- ),
865
- /* @__PURE__ */ jsx(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
866
- /* @__PURE__ */ jsx(Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
867
- release.scheduledAt && release.timezone && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
868
- {
869
- id: "content-releases.content-manager-edit-view.scheduled.date",
870
- defaultMessage: "{date} at {time} ({offset})"
871
- },
872
- {
873
- date: formatDate(new Date(release.scheduledAt), {
874
- day: "2-digit",
875
- month: "2-digit",
876
- year: "numeric",
877
- timeZone: release.timezone
878
- }),
879
- time: formatTime(new Date(release.scheduledAt), {
880
- hourCycle: "h23",
881
- timeZone: release.timezone
882
- }),
883
- offset: getTimezoneOffset(
884
- release.timezone,
885
- new Date(release.scheduledAt)
886
- )
887
- }
888
- ) }),
889
- canDeleteAction ? /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
890
- /* @__PURE__ */ jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
891
- /* @__PURE__ */ jsx(
892
- ReleaseActionMenu.DeleteReleaseActionItem,
893
- {
894
- releaseId: release.id,
895
- actionId: release.actions[0].id
896
- }
897
- )
898
- ] }) : null
899
- ] }) })
900
- ]
901
- },
902
- release.id
903
- );
904
- }),
905
- canCreateAction ? /* @__PURE__ */ jsx(
906
- Button,
907
+ if (collectionType === "collection-types" && (!documentId || documentId === "create")) {
908
+ return null;
909
+ }
910
+ if (releases && releases.length === 0) {
911
+ return null;
912
+ }
913
+ return {
914
+ title: formatMessage({
915
+ id: "content-releases.plugin.name",
916
+ defaultMessage: "Releases"
917
+ }),
918
+ content: /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 3, width: "100%", children: releases?.map((release) => /* @__PURE__ */ jsxs(
919
+ Flex,
920
+ {
921
+ direction: "column",
922
+ alignItems: "start",
923
+ borderWidth: "1px",
924
+ borderStyle: "solid",
925
+ borderColor: getReleaseColorVariant(release.actions[0].type, "200"),
926
+ overflow: "hidden",
927
+ hasRadius: true,
928
+ children: [
929
+ /* @__PURE__ */ jsx(
930
+ Box,
907
931
  {
908
- justifyContent: "center",
932
+ paddingTop: 3,
933
+ paddingBottom: 3,
909
934
  paddingLeft: 4,
910
935
  paddingRight: 4,
911
- color: "neutral700",
912
- variant: "tertiary",
913
- startIcon: /* @__PURE__ */ jsx(Plus, {}),
914
- onClick: toggleModal,
915
- children: formatMessage({
916
- id: "content-releases.content-manager-edit-view.add-to-release",
917
- defaultMessage: "Add to release"
918
- })
936
+ background: getReleaseColorVariant(release.actions[0].type, "100"),
937
+ width: "100%",
938
+ children: /* @__PURE__ */ jsx(
939
+ Typography,
940
+ {
941
+ fontSize: 1,
942
+ variant: "pi",
943
+ textColor: getReleaseColorVariant(release.actions[0].type, "600"),
944
+ children: formatMessage(
945
+ {
946
+ id: "content-releases.content-manager-edit-view.list-releases.title",
947
+ defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
948
+ },
949
+ { isPublish: release.actions[0].type === "publish" }
950
+ )
951
+ }
952
+ )
919
953
  }
920
- ) : null
921
- ] }),
922
- isModalOpen && /* @__PURE__ */ jsx(
923
- AddActionToReleaseModal,
924
- {
925
- handleClose: toggleModal,
926
- contentTypeUid,
927
- entryId
928
- }
929
- )
930
- ]
931
- }
932
- );
954
+ ),
955
+ /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
956
+ /* @__PURE__ */ jsx(Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
957
+ release.scheduledAt && release.timezone && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
958
+ {
959
+ id: "content-releases.content-manager-edit-view.scheduled.date",
960
+ defaultMessage: "{date} at {time} ({offset})"
961
+ },
962
+ {
963
+ date: formatDate(new Date(release.scheduledAt), {
964
+ day: "2-digit",
965
+ month: "2-digit",
966
+ year: "numeric",
967
+ timeZone: release.timezone
968
+ }),
969
+ time: formatTime(new Date(release.scheduledAt), {
970
+ hourCycle: "h23",
971
+ timeZone: release.timezone
972
+ }),
973
+ offset: getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
974
+ }
975
+ ) }),
976
+ canDeleteAction ? /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
977
+ /* @__PURE__ */ jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
978
+ /* @__PURE__ */ jsx(
979
+ ReleaseActionMenu.DeleteReleaseActionItem,
980
+ {
981
+ releaseId: release.id,
982
+ actionId: release.actions[0].id
983
+ }
984
+ )
985
+ ] }) : null
986
+ ] })
987
+ ]
988
+ },
989
+ release.id
990
+ )) })
991
+ };
933
992
  };
934
993
  const pluginId = "content-releases";
935
994
  const prefixPluginTranslations = (trad, pluginId2) => {
@@ -953,18 +1012,38 @@ const admin = {
953
1012
  id: `${pluginId}.plugin.name`,
954
1013
  defaultMessage: "Releases"
955
1014
  },
956
- Component: () => import("./App-D_6Y9N2F.mjs").then((mod) => ({ default: mod.App })),
1015
+ Component: () => import("./App-6gbM0io-.mjs").then((mod) => ({ default: mod.App })),
957
1016
  permissions: PERMISSIONS.main,
958
1017
  position: 2
959
1018
  });
960
- app.getPlugin("content-manager").injectComponent("editView", "right-links", {
961
- name: `${pluginId}-link`,
962
- Component: CMReleasesContainer
1019
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
1020
+ if ("addEditViewSidePanel" in contentManagerPluginApis && typeof contentManagerPluginApis.addEditViewSidePanel === "function") {
1021
+ contentManagerPluginApis.addEditViewSidePanel([Panel]);
1022
+ }
1023
+ if ("addDocumentAction" in contentManagerPluginApis && typeof contentManagerPluginApis.addDocumentAction === "function") {
1024
+ contentManagerPluginApis.addDocumentAction((actions) => {
1025
+ const indexOfDeleteAction = actions.findIndex((action) => action.type === "unpublish");
1026
+ actions.splice(indexOfDeleteAction, 0, ReleaseActionModalForm);
1027
+ return actions;
1028
+ });
1029
+ }
1030
+ app.addSettingsLink("global", {
1031
+ id: pluginId,
1032
+ to: "releases",
1033
+ intlLabel: {
1034
+ id: `${pluginId}.plugin.name`,
1035
+ defaultMessage: "Releases"
1036
+ },
1037
+ permissions: [],
1038
+ async Component() {
1039
+ const { SettingsPage } = await import("./SettingsPage-CuSH193e.mjs");
1040
+ return { default: SettingsPage };
1041
+ }
963
1042
  });
964
1043
  } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
965
- app.addMenuLink({
966
- to: `/plugins/purchase-content-releases`,
967
- icon: PaperPlane,
1044
+ app.addSettingsLink("global", {
1045
+ id: pluginId,
1046
+ to: "/plugins/purchase-content-releases",
968
1047
  intlLabel: {
969
1048
  id: `${pluginId}.plugin.name`,
970
1049
  defaultMessage: "Releases"
@@ -974,15 +1053,14 @@ const admin = {
974
1053
  const { PurchaseContentReleases } = await import("./PurchaseContentReleases-_MxP6-Dt.mjs");
975
1054
  return { default: PurchaseContentReleases };
976
1055
  },
977
- lockIcon: true,
978
- position: 2
1056
+ licenseOnly: true
979
1057
  });
980
1058
  }
981
1059
  },
982
1060
  async registerTrads({ locales }) {
983
1061
  const importedTrads = await Promise.all(
984
1062
  locales.map((locale) => {
985
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-B9Ur3VsE.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1063
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-C3sq5KNP.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
986
1064
  return {
987
1065
  data: prefixPluginTranslations(data, "content-releases"),
988
1066
  locale
@@ -1006,13 +1084,16 @@ export {
1006
1084
  useUpdateReleaseMutation as c,
1007
1085
  useDeleteReleaseMutation as d,
1008
1086
  usePublishReleaseMutation as e,
1009
- useGetReleaseActionsQuery as f,
1010
- getTimezoneOffset as g,
1011
- useUpdateReleaseActionMutation as h,
1012
- ReleaseActionMenu as i,
1013
- admin as j,
1087
+ getTimezoneOffset as f,
1088
+ getTimezones as g,
1089
+ useGetReleaseActionsQuery as h,
1090
+ useUpdateReleaseActionMutation as i,
1091
+ ReleaseActionMenu as j,
1092
+ useGetReleaseSettingsQuery as k,
1093
+ useUpdateReleaseSettingsMutation as l,
1094
+ admin as m,
1014
1095
  pluginId as p,
1015
1096
  releaseApi as r,
1016
1097
  useGetReleasesQuery as u
1017
1098
  };
1018
- //# sourceMappingURL=index-BomF0-yY.mjs.map
1099
+ //# sourceMappingURL=index-CuchqQ4_.mjs.map