@strapi/content-releases 0.0.0-next.0a7843dbfbff3628c1a547e687ca05eefe4ae611 → 0.0.0-next.0b1222ea20f2dddd5d4222c5d57cd3a4c1f25be8

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 (29) hide show
  1. package/dist/_chunks/{App--nWfPfW0.js → App-dLXY5ei3.js} +730 -461
  2. package/dist/_chunks/App-dLXY5ei3.js.map +1 -0
  3. package/dist/_chunks/{App-LLQiZULE.mjs → App-jrh58sXY.mjs} +735 -467
  4. package/dist/_chunks/App-jrh58sXY.mjs.map +1 -0
  5. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs +51 -0
  6. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
  7. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js +51 -0
  8. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
  9. package/dist/_chunks/{en-2DuPv5k0.js → en-HrREghh3.js} +27 -7
  10. package/dist/_chunks/en-HrREghh3.js.map +1 -0
  11. package/dist/_chunks/{en-SOqjCdyh.mjs → en-ltT1TlKQ.mjs} +27 -7
  12. package/dist/_chunks/en-ltT1TlKQ.mjs.map +1 -0
  13. package/dist/_chunks/{index-kxiJMcBr.js → index-CVO0Rqdm.js} +448 -40
  14. package/dist/_chunks/index-CVO0Rqdm.js.map +1 -0
  15. package/dist/_chunks/{index-5zt6Fms0.mjs → index-PiOGBETy.mjs} +465 -57
  16. package/dist/_chunks/index-PiOGBETy.mjs.map +1 -0
  17. package/dist/admin/index.js +1 -1
  18. package/dist/admin/index.mjs +2 -2
  19. package/dist/server/index.js +1039 -397
  20. package/dist/server/index.js.map +1 -1
  21. package/dist/server/index.mjs +1035 -394
  22. package/dist/server/index.mjs.map +1 -1
  23. package/package.json +15 -12
  24. package/dist/_chunks/App--nWfPfW0.js.map +0 -1
  25. package/dist/_chunks/App-LLQiZULE.mjs.map +0 -1
  26. package/dist/_chunks/en-2DuPv5k0.js.map +0 -1
  27. package/dist/_chunks/en-SOqjCdyh.mjs.map +0 -1
  28. package/dist/_chunks/index-5zt6Fms0.mjs.map +0 -1
  29. package/dist/_chunks/index-kxiJMcBr.js.map +0 -1
@@ -159,7 +159,7 @@ const isAxiosError = (err) => {
159
159
  const releaseApi = react.createApi({
160
160
  reducerPath: pluginId,
161
161
  baseQuery: axiosBaseQuery,
162
- tagTypes: ["Release", "ReleaseAction"],
162
+ tagTypes: ["Release", "ReleaseAction", "EntriesInRelease"],
163
163
  endpoints: (build) => {
164
164
  return {
165
165
  getReleasesForEntry: build.query({
@@ -274,6 +274,20 @@ const releaseApi = react.createApi({
274
274
  { type: "ReleaseAction", id: "LIST" }
275
275
  ]
276
276
  }),
277
+ createManyReleaseActions: build.mutation({
278
+ query({ body, params }) {
279
+ return {
280
+ url: `/content-releases/${params.releaseId}/actions/bulk`,
281
+ method: "POST",
282
+ data: body
283
+ };
284
+ },
285
+ invalidatesTags: [
286
+ { type: "Release", id: "LIST" },
287
+ { type: "ReleaseAction", id: "LIST" },
288
+ { type: "EntriesInRelease" }
289
+ ]
290
+ }),
277
291
  updateReleaseAction: build.mutation({
278
292
  query({ body, params }) {
279
293
  return {
@@ -311,9 +325,11 @@ const releaseApi = react.createApi({
311
325
  method: "DELETE"
312
326
  };
313
327
  },
314
- invalidatesTags: [
328
+ invalidatesTags: (result, error, arg) => [
315
329
  { type: "Release", id: "LIST" },
316
- { type: "ReleaseAction", id: "LIST" }
330
+ { type: "Release", id: arg.params.releaseId },
331
+ { type: "ReleaseAction", id: "LIST" },
332
+ { type: "EntriesInRelease" }
317
333
  ]
318
334
  }),
319
335
  publishRelease: build.mutation({
@@ -332,7 +348,22 @@ const releaseApi = react.createApi({
332
348
  method: "DELETE"
333
349
  };
334
350
  },
335
- invalidatesTags: (result, error, arg) => [{ type: "Release", id: arg.id }]
351
+ invalidatesTags: () => [{ type: "Release", id: "LIST" }, { type: "EntriesInRelease" }]
352
+ }),
353
+ getMappedEntriesInReleases: build.query({
354
+ query(params) {
355
+ return {
356
+ url: "/content-releases/mapEntriesToReleases",
357
+ method: "GET",
358
+ config: {
359
+ params
360
+ }
361
+ };
362
+ },
363
+ transformResponse(response) {
364
+ return response.data;
365
+ },
366
+ providesTags: [{ type: "EntriesInRelease" }]
336
367
  })
337
368
  };
338
369
  }
@@ -344,12 +375,30 @@ const {
344
375
  useGetReleaseActionsQuery,
345
376
  useCreateReleaseMutation,
346
377
  useCreateReleaseActionMutation,
378
+ useCreateManyReleaseActionsMutation,
347
379
  useUpdateReleaseMutation,
348
380
  useUpdateReleaseActionMutation,
349
381
  usePublishReleaseMutation,
350
382
  useDeleteReleaseActionMutation,
351
- useDeleteReleaseMutation
383
+ useDeleteReleaseMutation,
384
+ useGetMappedEntriesInReleasesQuery
352
385
  } = releaseApi;
386
+ const getTimezoneOffset = (timezone, date) => {
387
+ try {
388
+ const offsetPart = new Intl.DateTimeFormat("en", {
389
+ timeZone: timezone,
390
+ timeZoneName: "longOffset"
391
+ }).formatToParts(date).find((part) => part.type === "timeZoneName");
392
+ const offset = offsetPart ? offsetPart.value : "";
393
+ let utcOffset = offset.replace("GMT", "UTC");
394
+ if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
395
+ utcOffset = `${utcOffset}+00:00`;
396
+ }
397
+ return utcOffset;
398
+ } catch (error) {
399
+ return "";
400
+ }
401
+ };
353
402
  const useTypedDispatch = reactRedux.useDispatch;
354
403
  const useTypedSelector = reactRedux.useSelector;
355
404
  const StyledMenuItem = styled__default.default(v2.Menu.Item)`
@@ -420,7 +469,7 @@ const DeleteReleaseActionItem = ({ releaseId, actionId }) => {
420
469
  }
421
470
  };
422
471
  return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { variant: "danger", onSelect: handleDeleteAction, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
423
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { as: icons.Cross, padding: 1 }),
472
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { as: icons.Cross, width: 3, height: 3 }),
424
473
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger600", variant: "omega", children: formatMessage({
425
474
  id: "content-releases.content-manager-edit-view.remove-from-release",
426
475
  defaultMessage: "Remove from release"
@@ -459,7 +508,7 @@ const ReleaseActionEntryLinkItem = ({
459
508
  pathname: `/content-manager/collection-types/${contentTypeUid}/${entryId}`,
460
509
  search: locale && `?plugins[i18n][locale]=${locale}`
461
510
  },
462
- startIcon: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { as: icons.Pencil, padding: 1 }),
511
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { as: icons.Pencil, width: 3, height: 3 }),
463
512
  children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: formatMessage({
464
513
  id: "content-releases.content-manager-edit-view.edit-entry",
465
514
  defaultMessage: "Edit entry"
@@ -469,6 +518,21 @@ const ReleaseActionEntryLinkItem = ({
469
518
  }
470
519
  );
471
520
  };
521
+ const EditReleaseItem = ({ releaseId }) => {
522
+ const { formatMessage } = reactIntl.useIntl();
523
+ return /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsx(
524
+ v2.Link,
525
+ {
526
+ href: `/admin/plugins/content-releases/${releaseId}`,
527
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { as: icons.Pencil, width: 3, height: 3 }),
528
+ isExternal: false,
529
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: formatMessage({
530
+ id: "content-releases.content-manager-edit-view.edit-release",
531
+ defaultMessage: "Edit release"
532
+ }) })
533
+ }
534
+ ) });
535
+ };
472
536
  const Root = ({ children, hasTriggerBorder = false }) => {
473
537
  const { formatMessage } = reactIntl.useIntl();
474
538
  return (
@@ -493,6 +557,7 @@ const Root = ({ children, hasTriggerBorder = false }) => {
493
557
  };
494
558
  const ReleaseActionMenu = {
495
559
  Root,
560
+ EditReleaseItem,
496
561
  DeleteReleaseActionItem,
497
562
  ReleaseActionEntryLinkItem
498
563
  };
@@ -516,19 +581,40 @@ const FieldWrapper = styled__default.default(designSystem.Field)`
516
581
  text-transform: capitalize;
517
582
  }
518
583
 
519
- &:active,
520
584
  &[data-checked='true'] {
521
- color: ${({ theme }) => theme.colors.primary700};
522
- background-color: ${({ theme }) => theme.colors.primary100};
523
- border-color: ${({ theme }) => theme.colors.primary700};
585
+ color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
586
+ background-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary100 : theme.colors.danger100};
587
+ border-color: ${({ theme, actionType }) => actionType === "publish" ? theme.colors.primary700 : theme.colors.danger600};
524
588
  }
525
589
 
526
590
  &[data-checked='false'] {
527
591
  border-left: ${({ actionType }) => actionType === "unpublish" && "none"};
528
592
  border-right: ${({ actionType }) => actionType === "publish" && "none"};
529
593
  }
594
+
595
+ &[data-checked='false'][data-disabled='false']:hover {
596
+ color: ${({ theme }) => theme.colors.neutral700};
597
+ background-color: ${({ theme }) => theme.colors.neutral100};
598
+ border-color: ${({ theme }) => theme.colors.neutral200};
599
+
600
+ & > label {
601
+ cursor: pointer;
602
+ }
603
+ }
604
+
605
+ &[data-disabled='true'] {
606
+ color: ${({ theme }) => theme.colors.neutral600};
607
+ background-color: ${({ theme }) => theme.colors.neutral150};
608
+ border-color: ${({ theme }) => theme.colors.neutral300};
609
+ }
530
610
  `;
531
- const ActionOption = ({ selected, actionType, handleChange, name }) => {
611
+ const ActionOption = ({
612
+ selected,
613
+ actionType,
614
+ handleChange,
615
+ name,
616
+ disabled = false
617
+ }) => {
532
618
  return /* @__PURE__ */ jsxRuntime.jsx(
533
619
  FieldWrapper,
534
620
  {
@@ -539,6 +625,7 @@ const ActionOption = ({ selected, actionType, handleChange, name }) => {
539
625
  position: "relative",
540
626
  cursor: "pointer",
541
627
  "data-checked": selected === actionType,
628
+ "data-disabled": disabled && selected !== actionType,
542
629
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.FieldLabel, { htmlFor: `${name}-${actionType}`, children: [
543
630
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { children: /* @__PURE__ */ jsxRuntime.jsx(
544
631
  designSystem.FieldInput,
@@ -548,7 +635,8 @@ const ActionOption = ({ selected, actionType, handleChange, name }) => {
548
635
  name,
549
636
  checked: selected === actionType,
550
637
  onChange: handleChange,
551
- value: actionType
638
+ value: actionType,
639
+ disabled
552
640
  }
553
641
  ) }),
554
642
  actionType
@@ -556,7 +644,12 @@ const ActionOption = ({ selected, actionType, handleChange, name }) => {
556
644
  }
557
645
  );
558
646
  };
559
- const ReleaseActionOptions = ({ selected, handleChange, name }) => {
647
+ const ReleaseActionOptions = ({
648
+ selected,
649
+ handleChange,
650
+ name,
651
+ disabled = false
652
+ }) => {
560
653
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { children: [
561
654
  /* @__PURE__ */ jsxRuntime.jsx(
562
655
  ActionOption,
@@ -564,7 +657,8 @@ const ReleaseActionOptions = ({ selected, handleChange, name }) => {
564
657
  actionType: "publish",
565
658
  selected,
566
659
  handleChange,
567
- name
660
+ name,
661
+ disabled
568
662
  }
569
663
  ),
570
664
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -573,7 +667,8 @@ const ReleaseActionOptions = ({ selected, handleChange, name }) => {
573
667
  actionType: "unpublish",
574
668
  selected,
575
669
  handleChange,
576
- name
670
+ name,
671
+ disabled
577
672
  }
578
673
  )
579
674
  ] });
@@ -617,6 +712,7 @@ const AddActionToReleaseModal = ({
617
712
  contentTypeUid,
618
713
  entryId
619
714
  }) => {
715
+ const releaseHeaderId = React__namespace.useId();
620
716
  const { formatMessage } = reactIntl.useIntl();
621
717
  const toggleNotification = helperPlugin.useNotification();
622
718
  const { formatAPIError } = helperPlugin.useAPIErrorHandler();
@@ -664,8 +760,8 @@ const AddActionToReleaseModal = ({
664
760
  }
665
761
  }
666
762
  };
667
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
668
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage({
763
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { onClose: handleClose, labelledBy: releaseHeaderId, children: [
764
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: releaseHeaderId, fontWeight: "bold", textColor: "neutral800", children: formatMessage({
669
765
  id: "content-releases.content-manager-edit-view.add-to-release",
670
766
  defaultMessage: "Add to release"
671
767
  }) }) }),
@@ -735,16 +831,18 @@ const AddActionToReleaseModal = ({
735
831
  };
736
832
  const CMReleasesContainer = () => {
737
833
  const [isModalOpen, setIsModalOpen] = React__namespace.useState(false);
738
- const { formatMessage } = reactIntl.useIntl();
834
+ const { formatMessage, formatDate, formatTime } = reactIntl.useIntl();
739
835
  const {
740
836
  isCreatingEntry,
741
- allLayoutData: { contentType }
837
+ hasDraftAndPublish,
838
+ initialData: { id: entryId },
839
+ slug
742
840
  } = helperPlugin.useCMEditViewDataManager();
743
- const params = reactRouterDom.useParams();
744
- const canFetch = params?.id != null && contentType?.uid != null;
841
+ const contentTypeUid = slug;
842
+ const canFetch = entryId != null && contentTypeUid != null;
745
843
  const fetchParams = canFetch ? {
746
- contentTypeUid: contentType.uid,
747
- entryId: params.id,
844
+ contentTypeUid,
845
+ entryId,
748
846
  hasEntryAttached: true
749
847
  } : query.skipToken;
750
848
  const response = useGetReleasesForEntryQuery(fetchParams);
@@ -752,7 +850,7 @@ const CMReleasesContainer = () => {
752
850
  if (!canFetch) {
753
851
  return null;
754
852
  }
755
- if (isCreatingEntry || !contentType?.options?.draftAndPublish) {
853
+ if (isCreatingEntry || !hasDraftAndPublish) {
756
854
  return null;
757
855
  }
758
856
  const toggleModal = () => setIsModalOpen((prev) => !prev);
@@ -789,7 +887,7 @@ const CMReleasesContainer = () => {
789
887
  alignItems: "start",
790
888
  borderWidth: "1px",
791
889
  borderStyle: "solid",
792
- borderColor: getReleaseColorVariant(release.action.type, "200"),
890
+ borderColor: getReleaseColorVariant(release.actions[0].type, "200"),
793
891
  overflow: "hidden",
794
892
  hasRadius: true,
795
893
  children: [
@@ -800,34 +898,59 @@ const CMReleasesContainer = () => {
800
898
  paddingBottom: 3,
801
899
  paddingLeft: 4,
802
900
  paddingRight: 4,
803
- background: getReleaseColorVariant(release.action.type, "100"),
901
+ background: getReleaseColorVariant(release.actions[0].type, "100"),
804
902
  width: "100%",
805
903
  children: /* @__PURE__ */ jsxRuntime.jsx(
806
904
  designSystem.Typography,
807
905
  {
808
906
  fontSize: 1,
809
907
  variant: "pi",
810
- textColor: getReleaseColorVariant(release.action.type, "600"),
908
+ textColor: getReleaseColorVariant(release.actions[0].type, "600"),
811
909
  children: formatMessage(
812
910
  {
813
911
  id: "content-releases.content-manager-edit-view.list-releases.title",
814
912
  defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
815
913
  },
816
- { isPublish: release.action.type === "publish" }
914
+ { isPublish: release.actions[0].type === "publish" }
817
915
  )
818
916
  }
819
917
  )
820
918
  }
821
919
  ),
822
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { padding: 4, direction: "column", gap: 3, width: "100%", alignItems: "flex-start", children: [
920
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
823
921
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
824
- /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsxRuntime.jsx(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: /* @__PURE__ */ jsxRuntime.jsx(
825
- ReleaseActionMenu.DeleteReleaseActionItem,
922
+ release.scheduledAt && release.timezone && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
826
923
  {
827
- releaseId: release.id,
828
- actionId: release.action.id
924
+ id: "content-releases.content-manager-edit-view.scheduled.date",
925
+ defaultMessage: "{date} at {time} ({offset})"
926
+ },
927
+ {
928
+ date: formatDate(new Date(release.scheduledAt), {
929
+ day: "2-digit",
930
+ month: "2-digit",
931
+ year: "numeric",
932
+ timeZone: release.timezone
933
+ }),
934
+ time: formatTime(new Date(release.scheduledAt), {
935
+ hourCycle: "h23",
936
+ timeZone: release.timezone
937
+ }),
938
+ offset: getTimezoneOffset(
939
+ release.timezone,
940
+ new Date(release.scheduledAt)
941
+ )
829
942
  }
830
- ) }) })
943
+ ) }),
944
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsxRuntime.jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
945
+ /* @__PURE__ */ jsxRuntime.jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
946
+ /* @__PURE__ */ jsxRuntime.jsx(
947
+ ReleaseActionMenu.DeleteReleaseActionItem,
948
+ {
949
+ releaseId: release.id,
950
+ actionId: release.actions[0].id
951
+ }
952
+ )
953
+ ] }) })
831
954
  ] })
832
955
  ]
833
956
  },
@@ -855,17 +978,280 @@ const CMReleasesContainer = () => {
855
978
  AddActionToReleaseModal,
856
979
  {
857
980
  handleClose: toggleModal,
858
- contentTypeUid: contentType.uid,
859
- entryId: params.id
981
+ contentTypeUid,
982
+ entryId
860
983
  }
861
984
  )
862
985
  ]
863
986
  }
864
987
  ) });
865
988
  };
989
+ const getContentPermissions = (subject) => {
990
+ const permissions = {
991
+ publish: [
992
+ {
993
+ action: "plugin::content-manager.explorer.publish",
994
+ subject,
995
+ id: "",
996
+ actionParameters: {},
997
+ properties: {},
998
+ conditions: []
999
+ }
1000
+ ]
1001
+ };
1002
+ return permissions;
1003
+ };
1004
+ const ReleaseAction = ({ ids, model }) => {
1005
+ const { formatMessage } = reactIntl.useIntl();
1006
+ const toggleNotification = helperPlugin.useNotification();
1007
+ const { formatAPIError } = helperPlugin.useAPIErrorHandler();
1008
+ const { modifiedData } = helperPlugin.useCMEditViewDataManager();
1009
+ const contentPermissions = getContentPermissions(model);
1010
+ const {
1011
+ allowedActions: { canPublish }
1012
+ } = helperPlugin.useRBAC(contentPermissions);
1013
+ const {
1014
+ allowedActions: { canCreate }
1015
+ } = helperPlugin.useRBAC(PERMISSIONS);
1016
+ const response = useGetReleasesQuery();
1017
+ const releases = response.data?.data;
1018
+ const [createManyReleaseActions, { isLoading }] = useCreateManyReleaseActionsMutation();
1019
+ const handleSubmit = async (values) => {
1020
+ const locale = modifiedData.locale;
1021
+ const releaseActionEntries = ids.map((id) => ({
1022
+ type: values.type,
1023
+ entry: {
1024
+ contentType: model,
1025
+ id,
1026
+ locale
1027
+ }
1028
+ }));
1029
+ const response2 = await createManyReleaseActions({
1030
+ body: releaseActionEntries,
1031
+ params: { releaseId: values.releaseId }
1032
+ });
1033
+ if ("data" in response2) {
1034
+ const notificationMessage = formatMessage(
1035
+ {
1036
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.message",
1037
+ defaultMessage: "{entriesAlreadyInRelease} out of {totalEntries} entries were already in the release."
1038
+ },
1039
+ {
1040
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
1041
+ totalEntries: response2.data.meta.totalEntries
1042
+ }
1043
+ );
1044
+ const notification = {
1045
+ type: "success",
1046
+ title: formatMessage(
1047
+ {
1048
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.title",
1049
+ defaultMessage: "Successfully added to release."
1050
+ },
1051
+ {
1052
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
1053
+ totalEntries: response2.data.meta.totalEntries
1054
+ }
1055
+ ),
1056
+ message: response2.data.meta.entriesAlreadyInRelease ? notificationMessage : ""
1057
+ };
1058
+ toggleNotification(notification);
1059
+ return true;
1060
+ }
1061
+ if ("error" in response2) {
1062
+ if (axios.isAxiosError(response2.error)) {
1063
+ toggleNotification({
1064
+ type: "warning",
1065
+ message: formatAPIError(response2.error)
1066
+ });
1067
+ } else {
1068
+ toggleNotification({
1069
+ type: "warning",
1070
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1071
+ });
1072
+ }
1073
+ }
1074
+ };
1075
+ if (!canCreate || !canPublish)
1076
+ return null;
1077
+ return {
1078
+ actionType: "release",
1079
+ variant: "tertiary",
1080
+ label: formatMessage({
1081
+ id: "content-manager-list-view.add-to-release",
1082
+ defaultMessage: "Add to Release"
1083
+ }),
1084
+ dialog: {
1085
+ type: "modal",
1086
+ title: formatMessage({
1087
+ id: "content-manager-list-view.add-to-release",
1088
+ defaultMessage: "Add to Release"
1089
+ }),
1090
+ content: ({ onClose }) => {
1091
+ return /* @__PURE__ */ jsxRuntime.jsx(
1092
+ formik.Formik,
1093
+ {
1094
+ onSubmit: async (values) => {
1095
+ const data = await handleSubmit(values);
1096
+ if (data) {
1097
+ return onClose();
1098
+ }
1099
+ },
1100
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
1101
+ initialValues: INITIAL_VALUES,
1102
+ children: ({ values, setFieldValue }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
1103
+ 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: [
1104
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 6, children: /* @__PURE__ */ jsxRuntime.jsx(
1105
+ designSystem.SingleSelect,
1106
+ {
1107
+ required: true,
1108
+ label: formatMessage({
1109
+ id: "content-releases.content-manager-list-view.add-to-release.select-label",
1110
+ defaultMessage: "Select a release"
1111
+ }),
1112
+ placeholder: formatMessage({
1113
+ id: "content-releases.content-manager-list-view.add-to-release.select-placeholder",
1114
+ defaultMessage: "Select"
1115
+ }),
1116
+ onChange: (value) => setFieldValue("releaseId", value),
1117
+ value: values.releaseId,
1118
+ children: releases?.map((release) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: release.id, children: release.name }, release.id))
1119
+ }
1120
+ ) }),
1121
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.FieldLabel, { children: formatMessage({
1122
+ id: "content-releases.content-manager-list-view.add-to-release.action-type-label",
1123
+ defaultMessage: "What do you want to do with these entries?"
1124
+ }) }),
1125
+ /* @__PURE__ */ jsxRuntime.jsx(
1126
+ ReleaseActionOptions,
1127
+ {
1128
+ selected: values.type,
1129
+ handleChange: (e) => setFieldValue("type", e.target.value),
1130
+ name: "type"
1131
+ }
1132
+ )
1133
+ ] }) }),
1134
+ /* @__PURE__ */ jsxRuntime.jsx(
1135
+ designSystem.ModalFooter,
1136
+ {
1137
+ startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
1138
+ id: "content-releases.content-manager-list-view.add-to-release.cancel-button",
1139
+ defaultMessage: "Cancel"
1140
+ }) }),
1141
+ endActions: (
1142
+ /**
1143
+ * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
1144
+ * for yup.string().required(), even when the value is falsy (including empty string)
1145
+ */
1146
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
1147
+ id: "content-releases.content-manager-list-view.add-to-release.continue-button",
1148
+ defaultMessage: "Continue"
1149
+ }) })
1150
+ )
1151
+ }
1152
+ )
1153
+ ] })
1154
+ }
1155
+ );
1156
+ }
1157
+ }
1158
+ };
1159
+ };
1160
+ const Button = styled__default.default.button`
1161
+ svg {
1162
+ > g,
1163
+ path {
1164
+ fill: ${({ theme }) => theme.colors.neutral500};
1165
+ }
1166
+ }
1167
+ &:hover {
1168
+ svg {
1169
+ > g,
1170
+ path {
1171
+ fill: ${({ theme }) => theme.colors.neutral600};
1172
+ }
1173
+ }
1174
+ }
1175
+ &:active {
1176
+ svg {
1177
+ > g,
1178
+ path {
1179
+ fill: ${({ theme }) => theme.colors.neutral400};
1180
+ }
1181
+ }
1182
+ }
1183
+ `;
1184
+ const ActionWrapper = styled__default.default(designSystem.Flex)`
1185
+ svg {
1186
+ height: ${4 / 16}rem;
1187
+ }
1188
+ `;
1189
+ const useReleasesList = (entryId) => {
1190
+ const { uid: contentTypeUid } = useTypedSelector(
1191
+ (state) => state["content-manager_listView"].contentType
1192
+ );
1193
+ const listViewData = useTypedSelector((state) => state["content-manager_listView"].data);
1194
+ const entriesIds = listViewData.map((entry) => entry.id);
1195
+ const response = useGetMappedEntriesInReleasesQuery(
1196
+ { contentTypeUid, entriesIds },
1197
+ { skip: !entriesIds || !contentTypeUid || entriesIds.length === 0 }
1198
+ );
1199
+ const mappedEntriesInReleases = response.data || {};
1200
+ return mappedEntriesInReleases?.[entryId] || [];
1201
+ };
1202
+ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1203
+ const { contentType } = layout;
1204
+ if (!contentType.options?.draftAndPublish) {
1205
+ return { displayedHeaders, layout };
1206
+ }
1207
+ return {
1208
+ displayedHeaders: [
1209
+ ...displayedHeaders,
1210
+ {
1211
+ key: "__release_key__",
1212
+ fieldSchema: { type: "string" },
1213
+ metadatas: { label: "To be released in", searchable: true, sortable: false },
1214
+ name: "releasedAt",
1215
+ cellFormatter: (props) => /* @__PURE__ */ jsxRuntime.jsx(ReleaseListCell, { ...props })
1216
+ }
1217
+ ],
1218
+ layout
1219
+ };
1220
+ };
1221
+ const ReleaseListCell = ({ id }) => {
1222
+ const releases = useReleasesList(id);
1223
+ const [visible, setVisible] = React__namespace.useState(false);
1224
+ const buttonRef = React__namespace.useRef(null);
1225
+ const { formatMessage } = reactIntl.useIntl();
1226
+ const handleTogglePopover = () => setVisible((prev) => !prev);
1227
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", onClick: handleTogglePopover, ref: buttonRef, children: /* @__PURE__ */ jsxRuntime.jsxs(ActionWrapper, { height: "2rem", width: "2rem", children: [
1228
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { style: { maxWidth: "252px", cursor: "pointer" }, textColor: "neutral800", children: releases.length > 0 ? formatMessage(
1229
+ {
1230
+ id: "content-releases.content-manager.list-view.releases-number",
1231
+ defaultMessage: "{number} {number, plural, one {release} other {releases}}"
1232
+ },
1233
+ {
1234
+ number: releases.length
1235
+ }
1236
+ ) : "-" }),
1237
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { children: [
1238
+ releases.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.SortIcon, {}),
1239
+ visible && /* @__PURE__ */ jsxRuntime.jsx(
1240
+ designSystem.Popover,
1241
+ {
1242
+ onDismiss: handleTogglePopover,
1243
+ source: buttonRef,
1244
+ spacing: 16,
1245
+ children: /* @__PURE__ */ jsxRuntime.jsx("ul", { children: releases.map(({ id: id2, name }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 3, as: "li", children: /* @__PURE__ */ jsxRuntime.jsx(v2.Link, { href: `/admin/plugins/content-releases/${id2}`, isExternal: false, children: name }) }, id2)) })
1246
+ }
1247
+ )
1248
+ ] })
1249
+ ] }) }) });
1250
+ };
866
1251
  const admin = {
867
1252
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
868
1253
  register(app) {
1254
+ app.createHook("ContentReleases/pages/ReleaseDetails/add-locale-in-releases");
869
1255
  if (window.strapi.features.isEnabled("cms-content-releases")) {
870
1256
  app.addMenuLink({
871
1257
  to: `/plugins/${pluginId}`,
@@ -875,7 +1261,7 @@ const admin = {
875
1261
  defaultMessage: "Releases"
876
1262
  },
877
1263
  async Component() {
878
- const { App } = await Promise.resolve().then(() => require("./App--nWfPfW0.js"));
1264
+ const { App } = await Promise.resolve().then(() => require("./App-dLXY5ei3.js"));
879
1265
  return App;
880
1266
  },
881
1267
  permissions: PERMISSIONS.main
@@ -888,12 +1274,33 @@ const admin = {
888
1274
  name: `${pluginId}-link`,
889
1275
  Component: CMReleasesContainer
890
1276
  });
1277
+ app.plugins["content-manager"].apis.addBulkAction((actions) => {
1278
+ const deleteActionIndex = actions.findIndex((action) => action.name === "DeleteAction");
1279
+ actions.splice(deleteActionIndex, 0, ReleaseAction);
1280
+ return actions;
1281
+ });
1282
+ app.registerHook("Admin/CM/pages/ListView/inject-column-in-table", addColumnToTableHook);
1283
+ } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
1284
+ app.addMenuLink({
1285
+ to: `/plugins/purchase-content-releases`,
1286
+ icon: icons.PaperPlane,
1287
+ intlLabel: {
1288
+ id: `${pluginId}.plugin.name`,
1289
+ defaultMessage: "Releases"
1290
+ },
1291
+ async Component() {
1292
+ const { PurchaseContentReleases } = await Promise.resolve().then(() => require("./PurchaseContentReleases-bpIYXOfu.js"));
1293
+ return PurchaseContentReleases;
1294
+ },
1295
+ lockIcon: true
1296
+ // TODO: to replace with another name in v5
1297
+ });
891
1298
  }
892
1299
  },
893
1300
  async registerTrads({ locales }) {
894
1301
  const importedTrads = await Promise.all(
895
1302
  locales.map((locale) => {
896
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-2DuPv5k0.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
1303
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-HrREghh3.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
897
1304
  return {
898
1305
  data: helperPlugin.prefixPluginTranslations(data, "content-releases"),
899
1306
  locale
@@ -913,6 +1320,7 @@ exports.PERMISSIONS = PERMISSIONS;
913
1320
  exports.ReleaseActionMenu = ReleaseActionMenu;
914
1321
  exports.ReleaseActionOptions = ReleaseActionOptions;
915
1322
  exports.admin = admin;
1323
+ exports.getTimezoneOffset = getTimezoneOffset;
916
1324
  exports.isAxiosError = isAxiosError;
917
1325
  exports.pluginId = pluginId;
918
1326
  exports.releaseApi = releaseApi;
@@ -925,4 +1333,4 @@ exports.usePublishReleaseMutation = usePublishReleaseMutation;
925
1333
  exports.useTypedDispatch = useTypedDispatch;
926
1334
  exports.useUpdateReleaseActionMutation = useUpdateReleaseActionMutation;
927
1335
  exports.useUpdateReleaseMutation = useUpdateReleaseMutation;
928
- //# sourceMappingURL=index-kxiJMcBr.js.map
1336
+ //# sourceMappingURL=index-CVO0Rqdm.js.map