@strapi/content-releases 0.0.0-next.aa7c7ec6724534e157d8a23fe85ee8318dabbf37 → 0.0.0-next.af9f5eed766381838931b23118affc1c765c5d88

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 (30) hide show
  1. package/LICENSE +17 -1
  2. package/dist/_chunks/{App-pspKUC-W.js → App-dLXY5ei3.js} +639 -380
  3. package/dist/_chunks/App-dLXY5ei3.js.map +1 -0
  4. package/dist/_chunks/{App-8FCxPK8-.mjs → App-jrh58sXY.mjs} +650 -392
  5. package/dist/_chunks/App-jrh58sXY.mjs.map +1 -0
  6. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs +51 -0
  7. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
  8. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js +51 -0
  9. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
  10. package/dist/_chunks/{en-r9YocBH0.js → en-HrREghh3.js} +24 -5
  11. package/dist/_chunks/en-HrREghh3.js.map +1 -0
  12. package/dist/_chunks/{en-m9eTk4UF.mjs → en-ltT1TlKQ.mjs} +24 -5
  13. package/dist/_chunks/en-ltT1TlKQ.mjs.map +1 -0
  14. package/dist/_chunks/{index-nGaPcY9m.js → index-CVO0Rqdm.js} +398 -19
  15. package/dist/_chunks/index-CVO0Rqdm.js.map +1 -0
  16. package/dist/_chunks/{index-8aK7GzI5.mjs → index-PiOGBETy.mjs} +414 -35
  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 +953 -443
  21. package/dist/server/index.js.map +1 -1
  22. package/dist/server/index.mjs +952 -443
  23. package/dist/server/index.mjs.map +1 -1
  24. package/package.json +14 -12
  25. package/dist/_chunks/App-8FCxPK8-.mjs.map +0 -1
  26. package/dist/_chunks/App-pspKUC-W.js.map +0 -1
  27. package/dist/_chunks/en-m9eTk4UF.mjs.map +0 -1
  28. package/dist/_chunks/en-r9YocBH0.js.map +0 -1
  29. package/dist/_chunks/index-8aK7GzI5.mjs.map +0 -1
  30. package/dist/_chunks/index-nGaPcY9m.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-8FCxPK8-.mjs");
1241
+ const { App } = await import("./App-jrh58sXY.mjs");
885
1242
  return App;
886
1243
  },
887
1244
  permissions: PERMISSIONS.main
@@ -894,12 +1251,33 @@ 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);
1260
+ } else if (!window.strapi.features.isEnabled("cms-content-releases") && window.strapi?.flags?.promoteEE) {
1261
+ app.addMenuLink({
1262
+ to: `/plugins/purchase-content-releases`,
1263
+ icon: PaperPlane,
1264
+ intlLabel: {
1265
+ id: `${pluginId}.plugin.name`,
1266
+ defaultMessage: "Releases"
1267
+ },
1268
+ async Component() {
1269
+ const { PurchaseContentReleases } = await import("./PurchaseContentReleases-3tRbmbY3.mjs");
1270
+ return PurchaseContentReleases;
1271
+ },
1272
+ lockIcon: true
1273
+ // TODO: to replace with another name in v5
1274
+ });
897
1275
  }
898
1276
  },
899
1277
  async registerTrads({ locales }) {
900
1278
  const importedTrads = await Promise.all(
901
1279
  locales.map((locale) => {
902
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-m9eTk4UF.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 }) => {
903
1281
  return {
904
1282
  data: prefixPluginTranslations(data, "content-releases"),
905
1283
  locale
@@ -918,19 +1296,20 @@ const admin = {
918
1296
  export {
919
1297
  PERMISSIONS as P,
920
1298
  ReleaseActionOptions as R,
921
- useUpdateReleaseMutation as a,
922
- useDeleteReleaseMutation as b,
923
- usePublishReleaseMutation as c,
924
- useTypedDispatch as d,
925
- useGetReleaseActionsQuery as e,
926
- useUpdateReleaseActionMutation as f,
927
- ReleaseActionMenu as g,
928
- 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,
929
1307
  isAxiosError as i,
930
- useCreateReleaseMutation as j,
931
- admin as k,
1308
+ useUpdateReleaseActionMutation as j,
1309
+ ReleaseActionMenu as k,
1310
+ admin as l,
932
1311
  pluginId as p,
933
1312
  releaseApi as r,
934
- useGetReleaseQuery as u
1313
+ useGetReleasesQuery as u
935
1314
  };
936
- //# sourceMappingURL=index-8aK7GzI5.mjs.map
1315
+ //# sourceMappingURL=index-PiOGBETy.mjs.map