@strapi/content-releases 0.0.0-next.c5f067b5650921187770124e9b6c8186e805e242 → 0.0.0-next.cfecf3ad808761571ce11e528113e5c1ea5f87fd

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-5PsAyVt2.js → App-HjWtUYmc.js} +728 -459
  2. package/dist/_chunks/App-HjWtUYmc.js.map +1 -0
  3. package/dist/_chunks/{App-3ycH2d3s.mjs → App-gu1aiP6i.mjs} +738 -470
  4. package/dist/_chunks/App-gu1aiP6i.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-D57Rztnc.js → index-ZNwxYN8H.js} +437 -32
  14. package/dist/_chunks/index-ZNwxYN8H.js.map +1 -0
  15. package/dist/_chunks/{index-4gUWuCQV.mjs → index-mvj9PSKd.mjs} +453 -48
  16. package/dist/_chunks/index-mvj9PSKd.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 +1037 -421
  20. package/dist/server/index.js.map +1 -1
  21. package/dist/server/index.mjs +1036 -421
  22. package/dist/server/index.mjs.map +1 -1
  23. package/package.json +15 -12
  24. package/dist/_chunks/App-3ycH2d3s.mjs.map +0 -1
  25. package/dist/_chunks/App-5PsAyVt2.js.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-4gUWuCQV.mjs.map +0 -1
  29. package/dist/_chunks/index-D57Rztnc.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,7 +831,7 @@ 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
837
  hasDraftAndPublish,
@@ -791,7 +887,7 @@ const CMReleasesContainer = () => {
791
887
  alignItems: "start",
792
888
  borderWidth: "1px",
793
889
  borderStyle: "solid",
794
- borderColor: getReleaseColorVariant(release.action.type, "200"),
890
+ borderColor: getReleaseColorVariant(release.actions[0].type, "200"),
795
891
  overflow: "hidden",
796
892
  hasRadius: true,
797
893
  children: [
@@ -802,34 +898,59 @@ const CMReleasesContainer = () => {
802
898
  paddingBottom: 3,
803
899
  paddingLeft: 4,
804
900
  paddingRight: 4,
805
- background: getReleaseColorVariant(release.action.type, "100"),
901
+ background: getReleaseColorVariant(release.actions[0].type, "100"),
806
902
  width: "100%",
807
903
  children: /* @__PURE__ */ jsxRuntime.jsx(
808
904
  designSystem.Typography,
809
905
  {
810
906
  fontSize: 1,
811
907
  variant: "pi",
812
- textColor: getReleaseColorVariant(release.action.type, "600"),
908
+ textColor: getReleaseColorVariant(release.actions[0].type, "600"),
813
909
  children: formatMessage(
814
910
  {
815
911
  id: "content-releases.content-manager-edit-view.list-releases.title",
816
912
  defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
817
913
  },
818
- { isPublish: release.action.type === "publish" }
914
+ { isPublish: release.actions[0].type === "publish" }
819
915
  )
820
916
  }
821
917
  )
822
918
  }
823
919
  ),
824
- /* @__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: [
825
921
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
826
- /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsxRuntime.jsx(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: /* @__PURE__ */ jsxRuntime.jsx(
827
- ReleaseActionMenu.DeleteReleaseActionItem,
922
+ release.scheduledAt && release.timezone && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
923
+ {
924
+ id: "content-releases.content-manager-edit-view.scheduled.date",
925
+ defaultMessage: "{date} at {time} ({offset})"
926
+ },
828
927
  {
829
- releaseId: release.id,
830
- actionId: release.action.id
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
+ )
831
942
  }
832
- ) }) })
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
+ ] }) })
833
954
  ] })
834
955
  ]
835
956
  },
@@ -865,9 +986,272 @@ const CMReleasesContainer = () => {
865
986
  }
866
987
  ) });
867
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
+ };
868
1251
  const admin = {
869
1252
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
870
1253
  register(app) {
1254
+ app.createHook("ContentReleases/pages/ReleaseDetails/add-locale-in-releases");
871
1255
  if (window.strapi.features.isEnabled("cms-content-releases")) {
872
1256
  app.addMenuLink({
873
1257
  to: `/plugins/${pluginId}`,
@@ -877,7 +1261,7 @@ const admin = {
877
1261
  defaultMessage: "Releases"
878
1262
  },
879
1263
  async Component() {
880
- const { App } = await Promise.resolve().then(() => require("./App-5PsAyVt2.js"));
1264
+ const { App } = await Promise.resolve().then(() => require("./App-HjWtUYmc.js"));
881
1265
  return App;
882
1266
  },
883
1267
  permissions: PERMISSIONS.main
@@ -890,12 +1274,32 @@ const admin = {
890
1274
  name: `${pluginId}-link`,
891
1275
  Component: CMReleasesContainer
892
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
+ });
893
1297
  }
894
1298
  },
895
1299
  async registerTrads({ locales }) {
896
1300
  const importedTrads = await Promise.all(
897
1301
  locales.map((locale) => {
898
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-2DuPv5k0.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
1302
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-HrREghh3.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
899
1303
  return {
900
1304
  data: helperPlugin.prefixPluginTranslations(data, "content-releases"),
901
1305
  locale
@@ -915,6 +1319,7 @@ exports.PERMISSIONS = PERMISSIONS;
915
1319
  exports.ReleaseActionMenu = ReleaseActionMenu;
916
1320
  exports.ReleaseActionOptions = ReleaseActionOptions;
917
1321
  exports.admin = admin;
1322
+ exports.getTimezoneOffset = getTimezoneOffset;
918
1323
  exports.isAxiosError = isAxiosError;
919
1324
  exports.pluginId = pluginId;
920
1325
  exports.releaseApi = releaseApi;
@@ -927,4 +1332,4 @@ exports.usePublishReleaseMutation = usePublishReleaseMutation;
927
1332
  exports.useTypedDispatch = useTypedDispatch;
928
1333
  exports.useUpdateReleaseActionMutation = useUpdateReleaseActionMutation;
929
1334
  exports.useUpdateReleaseMutation = useUpdateReleaseMutation;
930
- //# sourceMappingURL=index-D57Rztnc.js.map
1335
+ //# sourceMappingURL=index-ZNwxYN8H.js.map