@strapi/content-releases 0.0.0-experimental.d362bf200f5f9359a4bbd4a549603de5ee1f04ca → 0.0.0-experimental.d5b46d578a5c055b8dcc66939e1b5d540976fafb

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 (108) hide show
  1. package/dist/_chunks/{App-1LckaIGY.js → App-OP70yd5M.js} +210 -224
  2. package/dist/_chunks/App-OP70yd5M.js.map +1 -0
  3. package/dist/_chunks/{App-X01LBg5V.mjs → App-x6Tjj3HN.mjs} +202 -216
  4. package/dist/_chunks/App-x6Tjj3HN.mjs.map +1 -0
  5. package/dist/_chunks/{PurchaseContentReleases-Clm0iACO.mjs → PurchaseContentReleases-3tRbmbY3.mjs} +2 -2
  6. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
  7. package/dist/_chunks/{PurchaseContentReleases-YhAPgpG9.js → PurchaseContentReleases-bpIYXOfu.js} +2 -2
  8. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
  9. package/dist/_chunks/{en-faJDuv3q.js → en-3SGjiVyR.js} +10 -2
  10. package/dist/_chunks/en-3SGjiVyR.js.map +1 -0
  11. package/dist/_chunks/{en-RdapH-9X.mjs → en-bpHsnU0n.mjs} +10 -2
  12. package/dist/_chunks/en-bpHsnU0n.mjs.map +1 -0
  13. package/dist/_chunks/{index-OD9AlD-6.mjs → index-1ejXLtzt.mjs} +273 -103
  14. package/dist/_chunks/index-1ejXLtzt.mjs.map +1 -0
  15. package/dist/_chunks/{index-cYWov2wa.js → index-ydocdaZ0.js} +270 -100
  16. package/dist/_chunks/index-ydocdaZ0.js.map +1 -0
  17. package/dist/admin/index.js +15 -1
  18. package/dist/admin/index.js.map +1 -1
  19. package/dist/admin/index.mjs +16 -2
  20. package/dist/admin/index.mjs.map +1 -1
  21. package/dist/server/index.js +62 -60
  22. package/dist/server/index.js.map +1 -1
  23. package/dist/server/index.mjs +62 -61
  24. package/dist/server/index.mjs.map +1 -1
  25. package/package.json +28 -21
  26. package/dist/_chunks/App-1LckaIGY.js.map +0 -1
  27. package/dist/_chunks/App-X01LBg5V.mjs.map +0 -1
  28. package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +0 -1
  29. package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +0 -1
  30. package/dist/_chunks/en-RdapH-9X.mjs.map +0 -1
  31. package/dist/_chunks/en-faJDuv3q.js.map +0 -1
  32. package/dist/_chunks/index-OD9AlD-6.mjs.map +0 -1
  33. package/dist/_chunks/index-cYWov2wa.js.map +0 -1
  34. package/dist/admin/src/components/CMReleasesContainer.d.ts +0 -1
  35. package/dist/admin/src/components/RelativeTime.d.ts +0 -28
  36. package/dist/admin/src/components/ReleaseActionMenu.d.ts +0 -26
  37. package/dist/admin/src/components/ReleaseActionOptions.d.ts +0 -9
  38. package/dist/admin/src/components/ReleaseModal.d.ts +0 -16
  39. package/dist/admin/src/constants.d.ts +0 -58
  40. package/dist/admin/src/index.d.ts +0 -3
  41. package/dist/admin/src/pages/App.d.ts +0 -1
  42. package/dist/admin/src/pages/PurchaseContentReleases.d.ts +0 -2
  43. package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +0 -2
  44. package/dist/admin/src/pages/ReleasesPage.d.ts +0 -8
  45. package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +0 -181
  46. package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +0 -39
  47. package/dist/admin/src/pluginId.d.ts +0 -1
  48. package/dist/admin/src/services/axios.d.ts +0 -29
  49. package/dist/admin/src/services/release.d.ts +0 -369
  50. package/dist/admin/src/store/hooks.d.ts +0 -7
  51. package/dist/admin/src/utils/prefixPluginTranslations.d.ts +0 -3
  52. package/dist/admin/src/utils/time.d.ts +0 -1
  53. package/dist/server/src/bootstrap.d.ts +0 -5
  54. package/dist/server/src/bootstrap.d.ts.map +0 -1
  55. package/dist/server/src/constants.d.ts +0 -12
  56. package/dist/server/src/constants.d.ts.map +0 -1
  57. package/dist/server/src/content-types/index.d.ts +0 -99
  58. package/dist/server/src/content-types/index.d.ts.map +0 -1
  59. package/dist/server/src/content-types/release/index.d.ts +0 -48
  60. package/dist/server/src/content-types/release/index.d.ts.map +0 -1
  61. package/dist/server/src/content-types/release/schema.d.ts +0 -47
  62. package/dist/server/src/content-types/release/schema.d.ts.map +0 -1
  63. package/dist/server/src/content-types/release-action/index.d.ts +0 -50
  64. package/dist/server/src/content-types/release-action/index.d.ts.map +0 -1
  65. package/dist/server/src/content-types/release-action/schema.d.ts +0 -49
  66. package/dist/server/src/content-types/release-action/schema.d.ts.map +0 -1
  67. package/dist/server/src/controllers/index.d.ts +0 -19
  68. package/dist/server/src/controllers/index.d.ts.map +0 -1
  69. package/dist/server/src/controllers/release-action.d.ts +0 -10
  70. package/dist/server/src/controllers/release-action.d.ts.map +0 -1
  71. package/dist/server/src/controllers/release.d.ts +0 -11
  72. package/dist/server/src/controllers/release.d.ts.map +0 -1
  73. package/dist/server/src/controllers/validation/release-action.d.ts +0 -8
  74. package/dist/server/src/controllers/validation/release-action.d.ts.map +0 -1
  75. package/dist/server/src/controllers/validation/release.d.ts +0 -2
  76. package/dist/server/src/controllers/validation/release.d.ts.map +0 -1
  77. package/dist/server/src/destroy.d.ts +0 -5
  78. package/dist/server/src/destroy.d.ts.map +0 -1
  79. package/dist/server/src/index.d.ts +0 -2095
  80. package/dist/server/src/index.d.ts.map +0 -1
  81. package/dist/server/src/migrations/index.d.ts +0 -13
  82. package/dist/server/src/migrations/index.d.ts.map +0 -1
  83. package/dist/server/src/register.d.ts +0 -5
  84. package/dist/server/src/register.d.ts.map +0 -1
  85. package/dist/server/src/routes/index.d.ts +0 -35
  86. package/dist/server/src/routes/index.d.ts.map +0 -1
  87. package/dist/server/src/routes/release-action.d.ts +0 -18
  88. package/dist/server/src/routes/release-action.d.ts.map +0 -1
  89. package/dist/server/src/routes/release.d.ts +0 -18
  90. package/dist/server/src/routes/release.d.ts.map +0 -1
  91. package/dist/server/src/services/index.d.ts +0 -1826
  92. package/dist/server/src/services/index.d.ts.map +0 -1
  93. package/dist/server/src/services/release.d.ts +0 -66
  94. package/dist/server/src/services/release.d.ts.map +0 -1
  95. package/dist/server/src/services/scheduling.d.ts +0 -18
  96. package/dist/server/src/services/scheduling.d.ts.map +0 -1
  97. package/dist/server/src/services/validation.d.ts +0 -18
  98. package/dist/server/src/services/validation.d.ts.map +0 -1
  99. package/dist/server/src/utils/index.d.ts +0 -14
  100. package/dist/server/src/utils/index.d.ts.map +0 -1
  101. package/dist/shared/contracts/release-actions.d.ts +0 -131
  102. package/dist/shared/contracts/release-actions.d.ts.map +0 -1
  103. package/dist/shared/contracts/releases.d.ts +0 -166
  104. package/dist/shared/contracts/releases.d.ts.map +0 -1
  105. package/dist/shared/types.d.ts +0 -24
  106. package/dist/shared/types.d.ts.map +0 -1
  107. package/dist/shared/validation-schemas.d.ts +0 -2
  108. package/dist/shared/validation-schemas.d.ts.map +0 -1
@@ -1,17 +1,18 @@
1
- import { Cross, Pencil, More, Plus, EmptyDocuments, PaperPlane } from "@strapi/icons";
1
+ import { getFetchClient, useNotification, useAPIErrorHandler, CheckPermissions, useCMEditViewDataManager, NoContent, useRBAC, prefixPluginTranslations } from "@strapi/helper-plugin";
2
+ import { Cross, Pencil, More, Plus, PaperPlane } from "@strapi/icons";
2
3
  import { jsx, jsxs } from "react/jsx-runtime";
3
4
  import * as React from "react";
4
5
  import { skipToken } from "@reduxjs/toolkit/query";
5
- import { getFetchClient, useNotification, useAPIErrorHandler, useRBAC, useAuth, unstable_useDocument, useQueryParams } from "@strapi/admin/strapi-admin";
6
- import { IconButton, Flex, Icon, Typography, Field, FieldLabel, VisuallyHidden, FieldInput, Box, Button, ModalLayout, ModalHeader, ModalBody, SingleSelect, SingleSelectOption, ModalFooter, EmptyStateLayout } from "@strapi/design-system";
6
+ import { IconButton, Flex, Icon, Typography, Field, FieldLabel, VisuallyHidden, FieldInput, Box, Button, ModalLayout, ModalHeader, ModalBody, SingleSelect, SingleSelectOption, ModalFooter } from "@strapi/design-system";
7
7
  import { Menu, Link, LinkButton } from "@strapi/design-system/v2";
8
8
  import { isAxiosError as isAxiosError$1 } from "axios";
9
9
  import { Formik, Form } from "formik";
10
10
  import { useIntl } from "react-intl";
11
- import { NavLink, useParams, Link as Link$1 } from "react-router-dom";
11
+ import { NavLink, Link as Link$1 } from "react-router-dom";
12
12
  import * as yup from "yup";
13
13
  import { createApi } from "@reduxjs/toolkit/query/react";
14
14
  import styled from "styled-components";
15
+ import { useDispatch, useSelector } from "react-redux";
15
16
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
16
17
  const v = glob[path];
17
18
  if (v) {
@@ -250,6 +251,19 @@ const releaseApi = createApi({
250
251
  { type: "ReleaseAction", id: "LIST" }
251
252
  ]
252
253
  }),
254
+ createManyReleaseActions: build.mutation({
255
+ query({ body, params }) {
256
+ return {
257
+ url: `/content-releases/${params.releaseId}/actions/bulk`,
258
+ method: "POST",
259
+ data: body
260
+ };
261
+ },
262
+ invalidatesTags: [
263
+ { type: "Release", id: "LIST" },
264
+ { type: "ReleaseAction", id: "LIST" }
265
+ ]
266
+ }),
253
267
  updateReleaseAction: build.mutation({
254
268
  query({ body, params }) {
255
269
  return {
@@ -321,6 +335,7 @@ const {
321
335
  useGetReleaseActionsQuery,
322
336
  useCreateReleaseMutation,
323
337
  useCreateReleaseActionMutation,
338
+ useCreateManyReleaseActionsMutation,
324
339
  useUpdateReleaseMutation,
325
340
  useUpdateReleaseActionMutation,
326
341
  usePublishReleaseMutation,
@@ -343,6 +358,8 @@ const getTimezoneOffset = (timezone, date) => {
343
358
  return "";
344
359
  }
345
360
  };
361
+ const useTypedDispatch = useDispatch;
362
+ const useTypedSelector = useSelector;
346
363
  const StyledMenuItem = styled(Menu.Item)`
347
364
  &:hover {
348
365
  background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
@@ -379,12 +396,9 @@ const StyledIconButton = styled(IconButton)`
379
396
  `;
380
397
  const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
381
398
  const { formatMessage } = useIntl();
382
- const { toggleNotification } = useNotification();
399
+ const toggleNotification = useNotification();
383
400
  const { formatAPIError } = useAPIErrorHandler();
384
401
  const [deleteReleaseAction] = useDeleteReleaseActionMutation();
385
- const {
386
- allowedActions: { canDeleteAction }
387
- } = useRBAC(PERMISSIONS);
388
402
  const handleDeleteAction = async () => {
389
403
  const response = await deleteReleaseAction({
390
404
  params: { releaseId, actionId }
@@ -402,27 +416,24 @@ const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
402
416
  if ("error" in response) {
403
417
  if (isAxiosError$1(response.error)) {
404
418
  toggleNotification({
405
- type: "danger",
419
+ type: "warning",
406
420
  message: formatAPIError(response.error)
407
421
  });
408
422
  } else {
409
423
  toggleNotification({
410
- type: "danger",
424
+ type: "warning",
411
425
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
412
426
  });
413
427
  }
414
428
  }
415
429
  };
416
- if (!canDeleteAction) {
417
- return null;
418
- }
419
- return /* @__PURE__ */ jsx(StyledMenuItem, { variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
430
+ return /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsx(StyledMenuItem, { variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
420
431
  /* @__PURE__ */ jsx(Icon, { as: Cross, width: 3, height: 3 }),
421
432
  /* @__PURE__ */ jsx(Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
422
433
  id: "content-releases.content-manager-edit-view.remove-from-release",
423
434
  defaultMessage: "Remove from release"
424
435
  }) })
425
- ] }) });
436
+ ] }) }) });
426
437
  };
427
438
  const ReleaseActionEntryLinkItem = ({
428
439
  contentTypeUid,
@@ -430,44 +441,41 @@ const ReleaseActionEntryLinkItem = ({
430
441
  locale
431
442
  }) => {
432
443
  const { formatMessage } = useIntl();
433
- const userPermissions = useAuth("ReleaseActionEntryLinkItem", (state) => state.permissions);
434
- const canUpdateEntryForLocale = React.useMemo(() => {
435
- const updatePermissions = userPermissions.find(
436
- (permission) => permission.subject === contentTypeUid && permission.action === "plugin::content-manager.explorer.update"
437
- );
438
- if (!updatePermissions) {
439
- return false;
440
- }
441
- return Boolean(!locale || updatePermissions.properties?.locales?.includes(locale));
442
- }, [contentTypeUid, locale, userPermissions]);
443
- const {
444
- allowedActions: { canUpdateContentType }
445
- } = useRBAC({
446
- updateContentType: [
447
- {
448
- action: "plugin::content-manager.explorer.update",
449
- subject: contentTypeUid
450
- }
451
- ]
452
- });
453
- if (!canUpdateContentType || !canUpdateEntryForLocale) {
454
- return null;
455
- }
456
- return /* @__PURE__ */ jsx(StyledMenuItem, { children: /* @__PURE__ */ jsx(
457
- Link,
444
+ const collectionTypePermissions = useTypedSelector(
445
+ (state) => state.rbacProvider.collectionTypesRelatedPermissions
446
+ );
447
+ const updatePermissions = contentTypeUid ? collectionTypePermissions[contentTypeUid]?.["plugin::content-manager.explorer.update"] : [];
448
+ const canUpdateEntryForLocale = Boolean(
449
+ !locale || updatePermissions?.find(
450
+ (permission) => permission.properties?.locales?.includes(locale)
451
+ )
452
+ );
453
+ return /* @__PURE__ */ jsx(
454
+ CheckPermissions,
458
455
  {
459
- as: NavLink,
460
- to: {
461
- pathname: `/content-manager/collection-types/${contentTypeUid}/${entryId}`,
462
- search: locale && `?plugins[i18n][locale]=${locale}`
463
- },
464
- startIcon: /* @__PURE__ */ jsx(Icon, { as: Pencil, width: 3, height: 3 }),
465
- children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
466
- id: "content-releases.content-manager-edit-view.edit-entry",
467
- defaultMessage: "Edit entry"
468
- }) })
456
+ permissions: [
457
+ {
458
+ action: "plugin::content-manager.explorer.update",
459
+ subject: contentTypeUid
460
+ }
461
+ ],
462
+ children: canUpdateEntryForLocale && /* @__PURE__ */ jsx(StyledMenuItem, { children: /* @__PURE__ */ jsx(
463
+ Link,
464
+ {
465
+ as: NavLink,
466
+ to: {
467
+ pathname: `/content-manager/collection-types/${contentTypeUid}/${entryId}`,
468
+ search: locale && `?plugins[i18n][locale]=${locale}`
469
+ },
470
+ startIcon: /* @__PURE__ */ jsx(Icon, { as: Pencil, width: 3, height: 3 }),
471
+ children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
472
+ id: "content-releases.content-manager-edit-view.edit-entry",
473
+ defaultMessage: "Edit entry"
474
+ }) })
475
+ }
476
+ ) })
469
477
  }
470
- ) });
478
+ );
471
479
  };
472
480
  const EditReleaseItem = ({ releaseId }) => {
473
481
  const { formatMessage } = useIntl();
@@ -486,10 +494,9 @@ const EditReleaseItem = ({ releaseId }) => {
486
494
  };
487
495
  const Root = ({ children, hasTriggerBorder = false }) => {
488
496
  const { formatMessage } = useIntl();
489
- const { allowedActions } = useRBAC(PERMISSIONS);
490
497
  return (
491
498
  // A user can access the dropdown if they have permissions to delete a release-action OR update a release
492
- allowedActions.canDeleteAction || allowedActions.canUpdate ? /* @__PURE__ */ jsxs(Menu.Root, { children: [
499
+ /* @__PURE__ */ jsx(CheckPermissions, { permissions: [...PERMISSIONS.deleteAction, ...PERMISSIONS.update], children: /* @__PURE__ */ jsxs(Menu.Root, { children: [
493
500
  /* @__PURE__ */ jsx(
494
501
  Menu.Trigger,
495
502
  {
@@ -504,7 +511,7 @@ const Root = ({ children, hasTriggerBorder = false }) => {
504
511
  }
505
512
  ),
506
513
  /* @__PURE__ */ jsx(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children })
507
- ] }) : null
514
+ ] }) })
508
515
  );
509
516
  };
510
517
  const ReleaseActionMenu = {
@@ -636,13 +643,12 @@ const INITIAL_VALUES = {
636
643
  const NoReleases = () => {
637
644
  const { formatMessage } = useIntl();
638
645
  return /* @__PURE__ */ jsx(
639
- EmptyStateLayout,
646
+ NoContent,
640
647
  {
641
- icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem" }),
642
- content: formatMessage({
648
+ content: {
643
649
  id: "content-releases.content-manager-edit-view.add-to-release.no-releases-message",
644
650
  defaultMessage: "No available releases. Open the list of releases and create a new one from there."
645
- }),
651
+ },
646
652
  action: /* @__PURE__ */ jsx(
647
653
  LinkButton,
648
654
  {
@@ -667,10 +673,9 @@ const AddActionToReleaseModal = ({
667
673
  }) => {
668
674
  const releaseHeaderId = React.useId();
669
675
  const { formatMessage } = useIntl();
670
- const { toggleNotification } = useNotification();
676
+ const toggleNotification = useNotification();
671
677
  const { formatAPIError } = useAPIErrorHandler();
672
- const [{ query }] = useQueryParams();
673
- const locale = query.plugins?.i18n?.locale;
678
+ const { modifiedData } = useCMEditViewDataManager();
674
679
  const response = useGetReleasesForEntryQuery({
675
680
  contentTypeUid,
676
681
  entryId,
@@ -679,6 +684,7 @@ const AddActionToReleaseModal = ({
679
684
  const releases = response.data?.data;
680
685
  const [createReleaseAction, { isLoading }] = useCreateReleaseActionMutation();
681
686
  const handleSubmit = async (values) => {
687
+ const locale = modifiedData.locale;
682
688
  const releaseActionEntry = {
683
689
  contentType: contentTypeUid,
684
690
  id: entryId,
@@ -702,12 +708,12 @@ const AddActionToReleaseModal = ({
702
708
  if ("error" in response2) {
703
709
  if (isAxiosError$1(response2.error)) {
704
710
  toggleNotification({
705
- type: "danger",
711
+ type: "warning",
706
712
  message: formatAPIError(response2.error)
707
713
  });
708
714
  } else {
709
715
  toggleNotification({
710
- type: "danger",
716
+ type: "warning",
711
717
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
712
718
  });
713
719
  }
@@ -785,21 +791,17 @@ const AddActionToReleaseModal = ({
785
791
  const CMReleasesContainer = () => {
786
792
  const [isModalOpen, setIsModalOpen] = React.useState(false);
787
793
  const { formatMessage, formatDate, formatTime } = useIntl();
788
- const { id, slug, collectionType } = useParams();
789
- const isCreatingEntry = id === "create";
790
794
  const {
791
- allowedActions: { canCreateAction, canMain, canDeleteAction }
792
- } = useRBAC(PERMISSIONS);
793
- const { schema } = unstable_useDocument({
794
- collectionType,
795
- model: slug
796
- });
797
- const hasDraftAndPublish = schema?.options?.draftAndPublish;
795
+ isCreatingEntry,
796
+ hasDraftAndPublish,
797
+ initialData: { id: entryId },
798
+ slug
799
+ } = useCMEditViewDataManager();
798
800
  const contentTypeUid = slug;
799
- const canFetch = id != null && contentTypeUid != null;
801
+ const canFetch = entryId != null && contentTypeUid != null;
800
802
  const fetchParams = canFetch ? {
801
803
  contentTypeUid,
802
- entryId: id,
804
+ entryId,
803
805
  hasEntryAttached: true
804
806
  } : skipToken;
805
807
  const response = useGetReleasesForEntryQuery(fetchParams);
@@ -817,10 +819,7 @@ const CMReleasesContainer = () => {
817
819
  }
818
820
  return `success${shade}`;
819
821
  };
820
- if (!canMain) {
821
- return null;
822
- }
823
- return /* @__PURE__ */ jsxs(
822
+ return /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(
824
823
  Box,
825
824
  {
826
825
  as: "aside",
@@ -877,7 +876,7 @@ const CMReleasesContainer = () => {
877
876
  )
878
877
  }
879
878
  ),
880
- /* @__PURE__ */ jsx(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
879
+ /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
881
880
  /* @__PURE__ */ jsx(Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
882
881
  release.scheduledAt && release.timezone && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
883
882
  {
@@ -901,7 +900,7 @@ const CMReleasesContainer = () => {
901
900
  )
902
901
  }
903
902
  ) }),
904
- canDeleteAction ? /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
903
+ /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
905
904
  /* @__PURE__ */ jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
906
905
  /* @__PURE__ */ jsx(
907
906
  ReleaseActionMenu.DeleteReleaseActionItem,
@@ -910,14 +909,14 @@ const CMReleasesContainer = () => {
910
909
  actionId: release.action.id
911
910
  }
912
911
  )
913
- ] }) : null
914
- ] }) })
912
+ ] }) })
913
+ ] })
915
914
  ]
916
915
  },
917
916
  release.id
918
917
  );
919
918
  }),
920
- canCreateAction ? /* @__PURE__ */ jsx(
919
+ /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.createAction, children: /* @__PURE__ */ jsx(
921
920
  Button,
922
921
  {
923
922
  justifyContent: "center",
@@ -932,41 +931,206 @@ const CMReleasesContainer = () => {
932
931
  defaultMessage: "Add to release"
933
932
  })
934
933
  }
935
- ) : null
934
+ ) })
936
935
  ] }),
937
936
  isModalOpen && /* @__PURE__ */ jsx(
938
937
  AddActionToReleaseModal,
939
938
  {
940
939
  handleClose: toggleModal,
941
940
  contentTypeUid,
942
- entryId: id
941
+ entryId
943
942
  }
944
943
  )
945
944
  ]
946
945
  }
947
- );
946
+ ) });
948
947
  };
949
- const prefixPluginTranslations = (trad, pluginId2) => {
950
- if (!pluginId2) {
951
- throw new TypeError("pluginId can't be empty");
952
- }
953
- return Object.keys(trad).reduce((acc, current) => {
954
- acc[`${pluginId2}.${current}`] = trad[current];
955
- return acc;
956
- }, {});
948
+ const getContentPermissions = (subject) => {
949
+ const permissions = {
950
+ publish: [
951
+ {
952
+ action: "plugin::content-manager.explorer.publish",
953
+ subject,
954
+ id: "",
955
+ actionParameters: {},
956
+ properties: {},
957
+ conditions: []
958
+ }
959
+ ]
960
+ };
961
+ return permissions;
962
+ };
963
+ const ReleaseAction = ({ ids, model }) => {
964
+ const { formatMessage } = useIntl();
965
+ const toggleNotification = useNotification();
966
+ const { formatAPIError } = useAPIErrorHandler();
967
+ const { modifiedData } = useCMEditViewDataManager();
968
+ const contentPermissions = getContentPermissions(model);
969
+ const {
970
+ allowedActions: { canPublish }
971
+ } = useRBAC(contentPermissions);
972
+ const {
973
+ allowedActions: { canCreate }
974
+ } = useRBAC(PERMISSIONS);
975
+ const response = useGetReleasesQuery();
976
+ const releases = response.data?.data;
977
+ const [createManyReleaseActions, { isLoading }] = useCreateManyReleaseActionsMutation();
978
+ const handleSubmit = async (values) => {
979
+ const locale = modifiedData.locale;
980
+ const releaseActionEntries = ids.map((id) => ({
981
+ type: values.type,
982
+ entry: {
983
+ contentType: model,
984
+ id,
985
+ locale
986
+ }
987
+ }));
988
+ const response2 = await createManyReleaseActions({
989
+ body: releaseActionEntries,
990
+ params: { releaseId: values.releaseId }
991
+ });
992
+ if ("data" in response2) {
993
+ const notificationMessage = formatMessage(
994
+ {
995
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.message",
996
+ defaultMessage: "{entriesAlreadyInRelease} out of {totalEntries} entries were already in the release."
997
+ },
998
+ {
999
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
1000
+ totalEntries: response2.data.meta.totalEntries
1001
+ }
1002
+ );
1003
+ const notification = {
1004
+ type: "success",
1005
+ title: formatMessage(
1006
+ {
1007
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.title",
1008
+ defaultMessage: "Successfully added to release."
1009
+ },
1010
+ {
1011
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
1012
+ totalEntries: response2.data.meta.totalEntries
1013
+ }
1014
+ ),
1015
+ message: response2.data.meta.entriesAlreadyInRelease ? notificationMessage : ""
1016
+ };
1017
+ toggleNotification(notification);
1018
+ return true;
1019
+ }
1020
+ if ("error" in response2) {
1021
+ if (isAxiosError$1(response2.error)) {
1022
+ toggleNotification({
1023
+ type: "warning",
1024
+ message: formatAPIError(response2.error)
1025
+ });
1026
+ } else {
1027
+ toggleNotification({
1028
+ type: "warning",
1029
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1030
+ });
1031
+ }
1032
+ }
1033
+ };
1034
+ if (!canCreate || !canPublish)
1035
+ return null;
1036
+ return {
1037
+ actionType: "release",
1038
+ variant: "tertiary",
1039
+ label: formatMessage({
1040
+ id: "content-manager-list-view.add-to-release",
1041
+ defaultMessage: "Add to Release"
1042
+ }),
1043
+ dialog: {
1044
+ type: "modal",
1045
+ title: formatMessage({
1046
+ id: "content-manager-list-view.add-to-release",
1047
+ defaultMessage: "Add to Release"
1048
+ }),
1049
+ content: ({ onClose }) => {
1050
+ return /* @__PURE__ */ jsx(
1051
+ Formik,
1052
+ {
1053
+ onSubmit: async (values) => {
1054
+ const data = await handleSubmit(values);
1055
+ if (data) {
1056
+ return onClose();
1057
+ }
1058
+ },
1059
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
1060
+ initialValues: INITIAL_VALUES,
1061
+ children: ({ values, setFieldValue }) => /* @__PURE__ */ jsxs(Form, { children: [
1062
+ releases?.length === 0 ? /* @__PURE__ */ jsx(NoReleases, {}) : /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
1063
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsx(
1064
+ SingleSelect,
1065
+ {
1066
+ required: true,
1067
+ label: formatMessage({
1068
+ id: "content-releases.content-manager-list-view.add-to-release.select-label",
1069
+ defaultMessage: "Select a release"
1070
+ }),
1071
+ placeholder: formatMessage({
1072
+ id: "content-releases.content-manager-list-view.add-to-release.select-placeholder",
1073
+ defaultMessage: "Select"
1074
+ }),
1075
+ onChange: (value) => setFieldValue("releaseId", value),
1076
+ value: values.releaseId,
1077
+ children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
1078
+ }
1079
+ ) }),
1080
+ /* @__PURE__ */ jsx(FieldLabel, { children: formatMessage({
1081
+ id: "content-releases.content-manager-list-view.add-to-release.action-type-label",
1082
+ defaultMessage: "What do you want to do with these entries?"
1083
+ }) }),
1084
+ /* @__PURE__ */ jsx(
1085
+ ReleaseActionOptions,
1086
+ {
1087
+ selected: values.type,
1088
+ handleChange: (e) => setFieldValue("type", e.target.value),
1089
+ name: "type"
1090
+ }
1091
+ )
1092
+ ] }) }),
1093
+ /* @__PURE__ */ jsx(
1094
+ ModalFooter,
1095
+ {
1096
+ startActions: /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
1097
+ id: "content-releases.content-manager-list-view.add-to-release.cancel-button",
1098
+ defaultMessage: "Cancel"
1099
+ }) }),
1100
+ endActions: (
1101
+ /**
1102
+ * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
1103
+ * for yup.string().required(), even when the value is falsy (including empty string)
1104
+ */
1105
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
1106
+ id: "content-releases.content-manager-list-view.add-to-release.continue-button",
1107
+ defaultMessage: "Continue"
1108
+ }) })
1109
+ )
1110
+ }
1111
+ )
1112
+ ] })
1113
+ }
1114
+ );
1115
+ }
1116
+ }
1117
+ };
957
1118
  };
958
1119
  const admin = {
959
1120
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
960
1121
  register(app) {
961
1122
  if (window.strapi.features.isEnabled("cms-content-releases")) {
962
1123
  app.addMenuLink({
963
- to: `plugins/${pluginId}`,
1124
+ to: `/plugins/${pluginId}`,
964
1125
  icon: PaperPlane,
965
1126
  intlLabel: {
966
1127
  id: `${pluginId}.plugin.name`,
967
1128
  defaultMessage: "Releases"
968
1129
  },
969
- Component: () => import("./App-X01LBg5V.mjs").then((mod) => ({ default: mod.App })),
1130
+ async Component() {
1131
+ const { App } = await import("./App-x6Tjj3HN.mjs");
1132
+ return App;
1133
+ },
970
1134
  permissions: PERMISSIONS.main
971
1135
  });
972
1136
  app.addMiddlewares([() => releaseApi.middleware]);
@@ -977,6 +1141,11 @@ const admin = {
977
1141
  name: `${pluginId}-link`,
978
1142
  Component: CMReleasesContainer
979
1143
  });
1144
+ app.plugins["content-manager"].apis.addBulkAction((actions) => {
1145
+ const deleteActionIndex = actions.findIndex((action) => action.name === "DeleteAction");
1146
+ actions.splice(deleteActionIndex, 0, ReleaseAction);
1147
+ return actions;
1148
+ });
980
1149
  } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
981
1150
  app.addMenuLink({
982
1151
  to: `/plugins/purchase-content-releases`,
@@ -986,7 +1155,7 @@ const admin = {
986
1155
  defaultMessage: "Releases"
987
1156
  },
988
1157
  async Component() {
989
- const { PurchaseContentReleases } = await import("./PurchaseContentReleases-Clm0iACO.mjs");
1158
+ const { PurchaseContentReleases } = await import("./PurchaseContentReleases-3tRbmbY3.mjs");
990
1159
  return PurchaseContentReleases;
991
1160
  },
992
1161
  lockIcon: true
@@ -996,7 +1165,7 @@ const admin = {
996
1165
  async registerTrads({ locales }) {
997
1166
  const importedTrads = await Promise.all(
998
1167
  locales.map((locale) => {
999
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-RdapH-9X.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1168
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-bpHsnU0n.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1000
1169
  return {
1001
1170
  data: prefixPluginTranslations(data, "content-releases"),
1002
1171
  locale
@@ -1020,14 +1189,15 @@ export {
1020
1189
  useUpdateReleaseMutation as c,
1021
1190
  useDeleteReleaseMutation as d,
1022
1191
  usePublishReleaseMutation as e,
1023
- useGetReleaseActionsQuery as f,
1192
+ useTypedDispatch as f,
1024
1193
  getTimezoneOffset as g,
1025
- useUpdateReleaseActionMutation as h,
1194
+ useGetReleaseActionsQuery as h,
1026
1195
  isAxiosError as i,
1027
- ReleaseActionMenu as j,
1028
- admin as k,
1196
+ useUpdateReleaseActionMutation as j,
1197
+ ReleaseActionMenu as k,
1198
+ admin as l,
1029
1199
  pluginId as p,
1030
1200
  releaseApi as r,
1031
1201
  useGetReleasesQuery as u
1032
1202
  };
1033
- //# sourceMappingURL=index-OD9AlD-6.mjs.map
1203
+ //# sourceMappingURL=index-1ejXLtzt.mjs.map