@strapi/content-releases 0.0.0-next.d470b4f75cf00f24f440b80300f1c833c322b871 → 0.0.0-next.d54a672641d83234230d3d80d92aaf87f60f8c75

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 (32) hide show
  1. package/LICENSE +17 -1
  2. package/dist/_chunks/{App-1hHIqUoZ.js → App-dLXY5ei3.js} +636 -382
  3. package/dist/_chunks/App-dLXY5ei3.js.map +1 -0
  4. package/dist/_chunks/{App-U6GbyLIE.mjs → App-jrh58sXY.mjs} +647 -394
  5. package/dist/_chunks/App-jrh58sXY.mjs.map +1 -0
  6. package/dist/_chunks/{PurchaseContentReleases-Clm0iACO.mjs → PurchaseContentReleases-3tRbmbY3.mjs} +2 -2
  7. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
  8. package/dist/_chunks/{PurchaseContentReleases-YhAPgpG9.js → PurchaseContentReleases-bpIYXOfu.js} +2 -2
  9. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
  10. package/dist/_chunks/{en-bDhIlw-B.js → en-HrREghh3.js} +23 -6
  11. package/dist/_chunks/en-HrREghh3.js.map +1 -0
  12. package/dist/_chunks/{en-GqXgfmzl.mjs → en-ltT1TlKQ.mjs} +23 -6
  13. package/dist/_chunks/en-ltT1TlKQ.mjs.map +1 -0
  14. package/dist/_chunks/{index-l-FvkQlQ.js → index-CVO0Rqdm.js} +385 -20
  15. package/dist/_chunks/index-CVO0Rqdm.js.map +1 -0
  16. package/dist/_chunks/{index-gkExFBa0.mjs → index-PiOGBETy.mjs} +401 -36
  17. package/dist/_chunks/index-PiOGBETy.mjs.map +1 -0
  18. package/dist/admin/index.js +1 -1
  19. package/dist/admin/index.mjs +2 -2
  20. package/dist/server/index.js +948 -450
  21. package/dist/server/index.js.map +1 -1
  22. package/dist/server/index.mjs +947 -450
  23. package/dist/server/index.mjs.map +1 -1
  24. package/package.json +15 -13
  25. package/dist/_chunks/App-1hHIqUoZ.js.map +0 -1
  26. package/dist/_chunks/App-U6GbyLIE.mjs.map +0 -1
  27. package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +0 -1
  28. package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +0 -1
  29. package/dist/_chunks/en-GqXgfmzl.mjs.map +0 -1
  30. package/dist/_chunks/en-bDhIlw-B.js.map +0 -1
  31. package/dist/_chunks/index-gkExFBa0.mjs.map +0 -1
  32. package/dist/_chunks/index-l-FvkQlQ.js.map +0 -1
@@ -1,9 +1,9 @@
1
- import { getFetchClient, useNotification, useAPIErrorHandler, CheckPermissions, useCMEditViewDataManager, NoContent, prefixPluginTranslations } from "@strapi/helper-plugin";
1
+ import { getFetchClient, useNotification, useAPIErrorHandler, CheckPermissions, useCMEditViewDataManager, NoContent, useRBAC, SortIcon, prefixPluginTranslations } from "@strapi/helper-plugin";
2
2
  import { Cross, Pencil, More, Plus, PaperPlane } from "@strapi/icons";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  import * as React from "react";
5
5
  import { skipToken } from "@reduxjs/toolkit/query";
6
- import { IconButton, Flex, Icon, Typography, Field, FieldLabel, VisuallyHidden, FieldInput, Box, Button, ModalLayout, ModalHeader, ModalBody, SingleSelect, SingleSelectOption, ModalFooter } from "@strapi/design-system";
6
+ import { IconButton, Flex, Icon, Typography, Field, FieldLabel, VisuallyHidden, FieldInput, Box, Button as Button$1, ModalLayout, ModalHeader, ModalBody, SingleSelect, SingleSelectOption, ModalFooter, Popover } 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";
@@ -136,7 +136,7 @@ const isAxiosError = (err) => {
136
136
  const releaseApi = createApi({
137
137
  reducerPath: pluginId,
138
138
  baseQuery: axiosBaseQuery,
139
- tagTypes: ["Release", "ReleaseAction"],
139
+ tagTypes: ["Release", "ReleaseAction", "EntriesInRelease"],
140
140
  endpoints: (build) => {
141
141
  return {
142
142
  getReleasesForEntry: build.query({
@@ -251,6 +251,20 @@ const releaseApi = createApi({
251
251
  { type: "ReleaseAction", id: "LIST" }
252
252
  ]
253
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
+ { type: "EntriesInRelease" }
266
+ ]
267
+ }),
254
268
  updateReleaseAction: build.mutation({
255
269
  query({ body, params }) {
256
270
  return {
@@ -288,9 +302,11 @@ const releaseApi = createApi({
288
302
  method: "DELETE"
289
303
  };
290
304
  },
291
- invalidatesTags: [
305
+ invalidatesTags: (result, error, arg) => [
292
306
  { type: "Release", id: "LIST" },
293
- { type: "ReleaseAction", id: "LIST" }
307
+ { type: "Release", id: arg.params.releaseId },
308
+ { type: "ReleaseAction", id: "LIST" },
309
+ { type: "EntriesInRelease" }
294
310
  ]
295
311
  }),
296
312
  publishRelease: build.mutation({
@@ -309,7 +325,22 @@ const releaseApi = createApi({
309
325
  method: "DELETE"
310
326
  };
311
327
  },
312
- invalidatesTags: (result, error, arg) => [{ type: "Release", id: arg.id }]
328
+ invalidatesTags: () => [{ type: "Release", id: "LIST" }, { type: "EntriesInRelease" }]
329
+ }),
330
+ getMappedEntriesInReleases: build.query({
331
+ query(params) {
332
+ return {
333
+ url: "/content-releases/mapEntriesToReleases",
334
+ method: "GET",
335
+ config: {
336
+ params
337
+ }
338
+ };
339
+ },
340
+ transformResponse(response) {
341
+ return response.data;
342
+ },
343
+ providesTags: [{ type: "EntriesInRelease" }]
313
344
  })
314
345
  };
315
346
  }
@@ -321,12 +352,30 @@ const {
321
352
  useGetReleaseActionsQuery,
322
353
  useCreateReleaseMutation,
323
354
  useCreateReleaseActionMutation,
355
+ useCreateManyReleaseActionsMutation,
324
356
  useUpdateReleaseMutation,
325
357
  useUpdateReleaseActionMutation,
326
358
  usePublishReleaseMutation,
327
359
  useDeleteReleaseActionMutation,
328
- useDeleteReleaseMutation
360
+ useDeleteReleaseMutation,
361
+ useGetMappedEntriesInReleasesQuery
329
362
  } = releaseApi;
363
+ const getTimezoneOffset = (timezone, date) => {
364
+ try {
365
+ const offsetPart = new Intl.DateTimeFormat("en", {
366
+ timeZone: timezone,
367
+ timeZoneName: "longOffset"
368
+ }).formatToParts(date).find((part) => part.type === "timeZoneName");
369
+ const offset = offsetPart ? offsetPart.value : "";
370
+ let utcOffset = offset.replace("GMT", "UTC");
371
+ if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
372
+ utcOffset = `${utcOffset}+00:00`;
373
+ }
374
+ return utcOffset;
375
+ } catch (error) {
376
+ return "";
377
+ }
378
+ };
330
379
  const useTypedDispatch = useDispatch;
331
380
  const useTypedSelector = useSelector;
332
381
  const StyledMenuItem = styled(Menu.Item)`
@@ -446,6 +495,21 @@ const ReleaseActionEntryLinkItem = ({
446
495
  }
447
496
  );
448
497
  };
498
+ const EditReleaseItem = ({ releaseId }) => {
499
+ const { formatMessage } = useIntl();
500
+ return /* @__PURE__ */ jsx(StyledMenuItem, { children: /* @__PURE__ */ jsx(
501
+ Link,
502
+ {
503
+ href: `/admin/plugins/content-releases/${releaseId}`,
504
+ startIcon: /* @__PURE__ */ jsx(Icon, { as: Pencil, width: 3, height: 3 }),
505
+ isExternal: false,
506
+ children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: formatMessage({
507
+ id: "content-releases.content-manager-edit-view.edit-release",
508
+ defaultMessage: "Edit release"
509
+ }) })
510
+ }
511
+ ) });
512
+ };
449
513
  const Root = ({ children, hasTriggerBorder = false }) => {
450
514
  const { formatMessage } = useIntl();
451
515
  return (
@@ -470,6 +534,7 @@ const Root = ({ children, hasTriggerBorder = false }) => {
470
534
  };
471
535
  const ReleaseActionMenu = {
472
536
  Root,
537
+ EditReleaseItem,
473
538
  DeleteReleaseActionItem,
474
539
  ReleaseActionEntryLinkItem
475
540
  };
@@ -508,6 +573,10 @@ const FieldWrapper = styled(Field)`
508
573
  color: ${({ theme }) => theme.colors.neutral700};
509
574
  background-color: ${({ theme }) => theme.colors.neutral100};
510
575
  border-color: ${({ theme }) => theme.colors.neutral200};
576
+
577
+ & > label {
578
+ cursor: pointer;
579
+ }
511
580
  }
512
581
 
513
582
  &[data-disabled='true'] {
@@ -715,7 +784,7 @@ const AddActionToReleaseModal = ({
715
784
  /* @__PURE__ */ jsx(
716
785
  ModalFooter,
717
786
  {
718
- startActions: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({
787
+ startActions: /* @__PURE__ */ jsx(Button$1, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({
719
788
  id: "content-releases.content-manager-edit-view.add-to-release.cancel-button",
720
789
  defaultMessage: "Cancel"
721
790
  }) }),
@@ -724,7 +793,7 @@ const AddActionToReleaseModal = ({
724
793
  * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
725
794
  * for yup.string().required(), even when the value is falsy (including empty string)
726
795
  */
727
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
796
+ /* @__PURE__ */ jsx(Button$1, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
728
797
  id: "content-releases.content-manager-edit-view.add-to-release.continue-button",
729
798
  defaultMessage: "Continue"
730
799
  }) })
@@ -739,7 +808,7 @@ const AddActionToReleaseModal = ({
739
808
  };
740
809
  const CMReleasesContainer = () => {
741
810
  const [isModalOpen, setIsModalOpen] = React.useState(false);
742
- const { formatMessage } = useIntl();
811
+ const { formatMessage, formatDate, formatTime } = useIntl();
743
812
  const {
744
813
  isCreatingEntry,
745
814
  hasDraftAndPublish,
@@ -795,7 +864,7 @@ const CMReleasesContainer = () => {
795
864
  alignItems: "start",
796
865
  borderWidth: "1px",
797
866
  borderStyle: "solid",
798
- borderColor: getReleaseColorVariant(release.action.type, "200"),
867
+ borderColor: getReleaseColorVariant(release.actions[0].type, "200"),
799
868
  overflow: "hidden",
800
869
  hasRadius: true,
801
870
  children: [
@@ -806,34 +875,59 @@ const CMReleasesContainer = () => {
806
875
  paddingBottom: 3,
807
876
  paddingLeft: 4,
808
877
  paddingRight: 4,
809
- background: getReleaseColorVariant(release.action.type, "100"),
878
+ background: getReleaseColorVariant(release.actions[0].type, "100"),
810
879
  width: "100%",
811
880
  children: /* @__PURE__ */ jsx(
812
881
  Typography,
813
882
  {
814
883
  fontSize: 1,
815
884
  variant: "pi",
816
- textColor: getReleaseColorVariant(release.action.type, "600"),
885
+ textColor: getReleaseColorVariant(release.actions[0].type, "600"),
817
886
  children: formatMessage(
818
887
  {
819
888
  id: "content-releases.content-manager-edit-view.list-releases.title",
820
889
  defaultMessage: "{isPublish, select, true {Will be published in} other {Will be unpublished in}}"
821
890
  },
822
- { isPublish: release.action.type === "publish" }
891
+ { isPublish: release.actions[0].type === "publish" }
823
892
  )
824
893
  }
825
894
  )
826
895
  }
827
896
  ),
828
- /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 3, width: "100%", alignItems: "flex-start", children: [
897
+ /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 2, width: "100%", alignItems: "flex-start", children: [
829
898
  /* @__PURE__ */ jsx(Typography, { fontSize: 2, fontWeight: "bold", variant: "omega", textColor: "neutral700", children: release.name }),
830
- /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsx(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: /* @__PURE__ */ jsx(
831
- ReleaseActionMenu.DeleteReleaseActionItem,
899
+ release.scheduledAt && release.timezone && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: formatMessage(
900
+ {
901
+ id: "content-releases.content-manager-edit-view.scheduled.date",
902
+ defaultMessage: "{date} at {time} ({offset})"
903
+ },
832
904
  {
833
- releaseId: release.id,
834
- actionId: release.action.id
905
+ date: formatDate(new Date(release.scheduledAt), {
906
+ day: "2-digit",
907
+ month: "2-digit",
908
+ year: "numeric",
909
+ timeZone: release.timezone
910
+ }),
911
+ time: formatTime(new Date(release.scheduledAt), {
912
+ hourCycle: "h23",
913
+ timeZone: release.timezone
914
+ }),
915
+ offset: getTimezoneOffset(
916
+ release.timezone,
917
+ new Date(release.scheduledAt)
918
+ )
835
919
  }
836
- ) }) })
920
+ ) }),
921
+ /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.deleteAction, children: /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { hasTriggerBorder: true, children: [
922
+ /* @__PURE__ */ jsx(ReleaseActionMenu.EditReleaseItem, { releaseId: release.id }),
923
+ /* @__PURE__ */ jsx(
924
+ ReleaseActionMenu.DeleteReleaseActionItem,
925
+ {
926
+ releaseId: release.id,
927
+ actionId: release.actions[0].id
928
+ }
929
+ )
930
+ ] }) })
837
931
  ] })
838
932
  ]
839
933
  },
@@ -841,7 +935,7 @@ const CMReleasesContainer = () => {
841
935
  );
842
936
  }),
843
937
  /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.createAction, children: /* @__PURE__ */ jsx(
844
- Button,
938
+ Button$1,
845
939
  {
846
940
  justifyContent: "center",
847
941
  paddingLeft: 4,
@@ -869,9 +963,272 @@ const CMReleasesContainer = () => {
869
963
  }
870
964
  ) });
871
965
  };
966
+ const getContentPermissions = (subject) => {
967
+ const permissions = {
968
+ publish: [
969
+ {
970
+ action: "plugin::content-manager.explorer.publish",
971
+ subject,
972
+ id: "",
973
+ actionParameters: {},
974
+ properties: {},
975
+ conditions: []
976
+ }
977
+ ]
978
+ };
979
+ return permissions;
980
+ };
981
+ const ReleaseAction = ({ ids, model }) => {
982
+ const { formatMessage } = useIntl();
983
+ const toggleNotification = useNotification();
984
+ const { formatAPIError } = useAPIErrorHandler();
985
+ const { modifiedData } = useCMEditViewDataManager();
986
+ const contentPermissions = getContentPermissions(model);
987
+ const {
988
+ allowedActions: { canPublish }
989
+ } = useRBAC(contentPermissions);
990
+ const {
991
+ allowedActions: { canCreate }
992
+ } = useRBAC(PERMISSIONS);
993
+ const response = useGetReleasesQuery();
994
+ const releases = response.data?.data;
995
+ const [createManyReleaseActions, { isLoading }] = useCreateManyReleaseActionsMutation();
996
+ const handleSubmit = async (values) => {
997
+ const locale = modifiedData.locale;
998
+ const releaseActionEntries = ids.map((id) => ({
999
+ type: values.type,
1000
+ entry: {
1001
+ contentType: model,
1002
+ id,
1003
+ locale
1004
+ }
1005
+ }));
1006
+ const response2 = await createManyReleaseActions({
1007
+ body: releaseActionEntries,
1008
+ params: { releaseId: values.releaseId }
1009
+ });
1010
+ if ("data" in response2) {
1011
+ const notificationMessage = formatMessage(
1012
+ {
1013
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.message",
1014
+ defaultMessage: "{entriesAlreadyInRelease} out of {totalEntries} entries were already in the release."
1015
+ },
1016
+ {
1017
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
1018
+ totalEntries: response2.data.meta.totalEntries
1019
+ }
1020
+ );
1021
+ const notification = {
1022
+ type: "success",
1023
+ title: formatMessage(
1024
+ {
1025
+ id: "content-releases.content-manager-list-view.add-to-release.notification.success.title",
1026
+ defaultMessage: "Successfully added to release."
1027
+ },
1028
+ {
1029
+ entriesAlreadyInRelease: response2.data.meta.entriesAlreadyInRelease,
1030
+ totalEntries: response2.data.meta.totalEntries
1031
+ }
1032
+ ),
1033
+ message: response2.data.meta.entriesAlreadyInRelease ? notificationMessage : ""
1034
+ };
1035
+ toggleNotification(notification);
1036
+ return true;
1037
+ }
1038
+ if ("error" in response2) {
1039
+ if (isAxiosError$1(response2.error)) {
1040
+ toggleNotification({
1041
+ type: "warning",
1042
+ message: formatAPIError(response2.error)
1043
+ });
1044
+ } else {
1045
+ toggleNotification({
1046
+ type: "warning",
1047
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1048
+ });
1049
+ }
1050
+ }
1051
+ };
1052
+ if (!canCreate || !canPublish)
1053
+ return null;
1054
+ return {
1055
+ actionType: "release",
1056
+ variant: "tertiary",
1057
+ label: formatMessage({
1058
+ id: "content-manager-list-view.add-to-release",
1059
+ defaultMessage: "Add to Release"
1060
+ }),
1061
+ dialog: {
1062
+ type: "modal",
1063
+ title: formatMessage({
1064
+ id: "content-manager-list-view.add-to-release",
1065
+ defaultMessage: "Add to Release"
1066
+ }),
1067
+ content: ({ onClose }) => {
1068
+ return /* @__PURE__ */ jsx(
1069
+ Formik,
1070
+ {
1071
+ onSubmit: async (values) => {
1072
+ const data = await handleSubmit(values);
1073
+ if (data) {
1074
+ return onClose();
1075
+ }
1076
+ },
1077
+ validationSchema: RELEASE_ACTION_FORM_SCHEMA,
1078
+ initialValues: INITIAL_VALUES,
1079
+ children: ({ values, setFieldValue }) => /* @__PURE__ */ jsxs(Form, { children: [
1080
+ releases?.length === 0 ? /* @__PURE__ */ jsx(NoReleases, {}) : /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
1081
+ /* @__PURE__ */ jsx(Box, { paddingBottom: 6, children: /* @__PURE__ */ jsx(
1082
+ SingleSelect,
1083
+ {
1084
+ required: true,
1085
+ label: formatMessage({
1086
+ id: "content-releases.content-manager-list-view.add-to-release.select-label",
1087
+ defaultMessage: "Select a release"
1088
+ }),
1089
+ placeholder: formatMessage({
1090
+ id: "content-releases.content-manager-list-view.add-to-release.select-placeholder",
1091
+ defaultMessage: "Select"
1092
+ }),
1093
+ onChange: (value) => setFieldValue("releaseId", value),
1094
+ value: values.releaseId,
1095
+ children: releases?.map((release) => /* @__PURE__ */ jsx(SingleSelectOption, { value: release.id, children: release.name }, release.id))
1096
+ }
1097
+ ) }),
1098
+ /* @__PURE__ */ jsx(FieldLabel, { children: formatMessage({
1099
+ id: "content-releases.content-manager-list-view.add-to-release.action-type-label",
1100
+ defaultMessage: "What do you want to do with these entries?"
1101
+ }) }),
1102
+ /* @__PURE__ */ jsx(
1103
+ ReleaseActionOptions,
1104
+ {
1105
+ selected: values.type,
1106
+ handleChange: (e) => setFieldValue("type", e.target.value),
1107
+ name: "type"
1108
+ }
1109
+ )
1110
+ ] }) }),
1111
+ /* @__PURE__ */ jsx(
1112
+ ModalFooter,
1113
+ {
1114
+ startActions: /* @__PURE__ */ jsx(Button$1, { onClick: onClose, variant: "tertiary", name: "cancel", children: formatMessage({
1115
+ id: "content-releases.content-manager-list-view.add-to-release.cancel-button",
1116
+ defaultMessage: "Cancel"
1117
+ }) }),
1118
+ endActions: (
1119
+ /**
1120
+ * TODO: Ideally we would use isValid from Formik to disable the button, however currently it always returns true
1121
+ * for yup.string().required(), even when the value is falsy (including empty string)
1122
+ */
1123
+ /* @__PURE__ */ jsx(Button$1, { type: "submit", disabled: !values.releaseId, loading: isLoading, children: formatMessage({
1124
+ id: "content-releases.content-manager-list-view.add-to-release.continue-button",
1125
+ defaultMessage: "Continue"
1126
+ }) })
1127
+ )
1128
+ }
1129
+ )
1130
+ ] })
1131
+ }
1132
+ );
1133
+ }
1134
+ }
1135
+ };
1136
+ };
1137
+ const Button = styled.button`
1138
+ svg {
1139
+ > g,
1140
+ path {
1141
+ fill: ${({ theme }) => theme.colors.neutral500};
1142
+ }
1143
+ }
1144
+ &:hover {
1145
+ svg {
1146
+ > g,
1147
+ path {
1148
+ fill: ${({ theme }) => theme.colors.neutral600};
1149
+ }
1150
+ }
1151
+ }
1152
+ &:active {
1153
+ svg {
1154
+ > g,
1155
+ path {
1156
+ fill: ${({ theme }) => theme.colors.neutral400};
1157
+ }
1158
+ }
1159
+ }
1160
+ `;
1161
+ const ActionWrapper = styled(Flex)`
1162
+ svg {
1163
+ height: ${4 / 16}rem;
1164
+ }
1165
+ `;
1166
+ const useReleasesList = (entryId) => {
1167
+ const { uid: contentTypeUid } = useTypedSelector(
1168
+ (state) => state["content-manager_listView"].contentType
1169
+ );
1170
+ const listViewData = useTypedSelector((state) => state["content-manager_listView"].data);
1171
+ const entriesIds = listViewData.map((entry) => entry.id);
1172
+ const response = useGetMappedEntriesInReleasesQuery(
1173
+ { contentTypeUid, entriesIds },
1174
+ { skip: !entriesIds || !contentTypeUid || entriesIds.length === 0 }
1175
+ );
1176
+ const mappedEntriesInReleases = response.data || {};
1177
+ return mappedEntriesInReleases?.[entryId] || [];
1178
+ };
1179
+ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1180
+ const { contentType } = layout;
1181
+ if (!contentType.options?.draftAndPublish) {
1182
+ return { displayedHeaders, layout };
1183
+ }
1184
+ return {
1185
+ displayedHeaders: [
1186
+ ...displayedHeaders,
1187
+ {
1188
+ key: "__release_key__",
1189
+ fieldSchema: { type: "string" },
1190
+ metadatas: { label: "To be released in", searchable: true, sortable: false },
1191
+ name: "releasedAt",
1192
+ cellFormatter: (props) => /* @__PURE__ */ jsx(ReleaseListCell, { ...props })
1193
+ }
1194
+ ],
1195
+ layout
1196
+ };
1197
+ };
1198
+ const ReleaseListCell = ({ id }) => {
1199
+ const releases = useReleasesList(id);
1200
+ const [visible, setVisible] = React.useState(false);
1201
+ const buttonRef = React.useRef(null);
1202
+ const { formatMessage } = useIntl();
1203
+ const handleTogglePopover = () => setVisible((prev) => !prev);
1204
+ return /* @__PURE__ */ jsx(Flex, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(Button, { type: "button", onClick: handleTogglePopover, ref: buttonRef, children: /* @__PURE__ */ jsxs(ActionWrapper, { height: "2rem", width: "2rem", children: [
1205
+ /* @__PURE__ */ jsx(Typography, { style: { maxWidth: "252px", cursor: "pointer" }, textColor: "neutral800", children: releases.length > 0 ? formatMessage(
1206
+ {
1207
+ id: "content-releases.content-manager.list-view.releases-number",
1208
+ defaultMessage: "{number} {number, plural, one {release} other {releases}}"
1209
+ },
1210
+ {
1211
+ number: releases.length
1212
+ }
1213
+ ) : "-" }),
1214
+ /* @__PURE__ */ jsxs(Flex, { children: [
1215
+ releases.length > 0 && /* @__PURE__ */ jsx(SortIcon, {}),
1216
+ visible && /* @__PURE__ */ jsx(
1217
+ Popover,
1218
+ {
1219
+ onDismiss: handleTogglePopover,
1220
+ source: buttonRef,
1221
+ spacing: 16,
1222
+ children: /* @__PURE__ */ jsx("ul", { children: releases.map(({ id: id2, name }) => /* @__PURE__ */ jsx(Box, { padding: 3, as: "li", children: /* @__PURE__ */ jsx(Link, { href: `/admin/plugins/content-releases/${id2}`, isExternal: false, children: name }) }, id2)) })
1223
+ }
1224
+ )
1225
+ ] })
1226
+ ] }) }) });
1227
+ };
872
1228
  const admin = {
873
1229
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
874
1230
  register(app) {
1231
+ app.createHook("ContentReleases/pages/ReleaseDetails/add-locale-in-releases");
875
1232
  if (window.strapi.features.isEnabled("cms-content-releases")) {
876
1233
  app.addMenuLink({
877
1234
  to: `/plugins/${pluginId}`,
@@ -881,7 +1238,7 @@ const admin = {
881
1238
  defaultMessage: "Releases"
882
1239
  },
883
1240
  async Component() {
884
- const { App } = await import("./App-U6GbyLIE.mjs");
1241
+ const { App } = await import("./App-jrh58sXY.mjs");
885
1242
  return App;
886
1243
  },
887
1244
  permissions: PERMISSIONS.main
@@ -894,6 +1251,12 @@ const admin = {
894
1251
  name: `${pluginId}-link`,
895
1252
  Component: CMReleasesContainer
896
1253
  });
1254
+ app.plugins["content-manager"].apis.addBulkAction((actions) => {
1255
+ const deleteActionIndex = actions.findIndex((action) => action.name === "DeleteAction");
1256
+ actions.splice(deleteActionIndex, 0, ReleaseAction);
1257
+ return actions;
1258
+ });
1259
+ app.registerHook("Admin/CM/pages/ListView/inject-column-in-table", addColumnToTableHook);
897
1260
  } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
898
1261
  app.addMenuLink({
899
1262
  to: `/plugins/purchase-content-releases`,
@@ -903,17 +1266,18 @@ const admin = {
903
1266
  defaultMessage: "Releases"
904
1267
  },
905
1268
  async Component() {
906
- const { PurchaseContentReleases } = await import("./PurchaseContentReleases-Clm0iACO.mjs");
1269
+ const { PurchaseContentReleases } = await import("./PurchaseContentReleases-3tRbmbY3.mjs");
907
1270
  return PurchaseContentReleases;
908
1271
  },
909
1272
  lockIcon: true
1273
+ // TODO: to replace with another name in v5
910
1274
  });
911
1275
  }
912
1276
  },
913
1277
  async registerTrads({ locales }) {
914
1278
  const importedTrads = await Promise.all(
915
1279
  locales.map((locale) => {
916
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-GqXgfmzl.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1280
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-ltT1TlKQ.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
917
1281
  return {
918
1282
  data: prefixPluginTranslations(data, "content-releases"),
919
1283
  locale
@@ -932,19 +1296,20 @@ const admin = {
932
1296
  export {
933
1297
  PERMISSIONS as P,
934
1298
  ReleaseActionOptions as R,
935
- useUpdateReleaseMutation as a,
936
- useDeleteReleaseMutation as b,
937
- usePublishReleaseMutation as c,
938
- useTypedDispatch as d,
939
- useGetReleaseActionsQuery as e,
940
- useUpdateReleaseActionMutation as f,
941
- ReleaseActionMenu as g,
942
- useGetReleasesQuery as h,
1299
+ useCreateReleaseMutation as a,
1300
+ useGetReleaseQuery as b,
1301
+ useUpdateReleaseMutation as c,
1302
+ useDeleteReleaseMutation as d,
1303
+ usePublishReleaseMutation as e,
1304
+ useTypedDispatch as f,
1305
+ getTimezoneOffset as g,
1306
+ useGetReleaseActionsQuery as h,
943
1307
  isAxiosError as i,
944
- useCreateReleaseMutation as j,
945
- admin as k,
1308
+ useUpdateReleaseActionMutation as j,
1309
+ ReleaseActionMenu as k,
1310
+ admin as l,
946
1311
  pluginId as p,
947
1312
  releaseApi as r,
948
- useGetReleaseQuery as u
1313
+ useGetReleasesQuery as u
949
1314
  };
950
- //# sourceMappingURL=index-gkExFBa0.mjs.map
1315
+ //# sourceMappingURL=index-PiOGBETy.mjs.map