@strapi/content-releases 0.0.0-experimental.d8a676a242377cee820b59b21a05d47290d9ac73 → 0.0.0-experimental.defd8568ae03ef8d52f86e1f3541979f953c3941

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 (110) hide show
  1. package/dist/_chunks/{App-p8aKBitd.js → App-C0DlH0im.js} +343 -323
  2. package/dist/_chunks/App-C0DlH0im.js.map +1 -0
  3. package/dist/_chunks/{App-bpzO2Ljh.mjs → App-O0ZO-S35.mjs} +328 -308
  4. package/dist/_chunks/App-O0ZO-S35.mjs.map +1 -0
  5. package/dist/_chunks/{PurchaseContentReleases-YhAPgpG9.js → PurchaseContentReleases-DAHdUpAA.js} +5 -5
  6. package/dist/_chunks/PurchaseContentReleases-DAHdUpAA.js.map +1 -0
  7. package/dist/_chunks/{PurchaseContentReleases-Clm0iACO.mjs → PurchaseContentReleases-Ex09YpKR.mjs} +6 -6
  8. package/dist/_chunks/PurchaseContentReleases-Ex09YpKR.mjs.map +1 -0
  9. package/dist/_chunks/{en-WuuhP6Bn.mjs → en-B9Ur3VsE.mjs} +11 -3
  10. package/dist/_chunks/en-B9Ur3VsE.mjs.map +1 -0
  11. package/dist/_chunks/{en-gcJJ5htG.js → en-DtFJ5ViE.js} +11 -3
  12. package/dist/_chunks/en-DtFJ5ViE.js.map +1 -0
  13. package/dist/_chunks/{index-AECgcaDa.mjs → index-DjDPK8kb.mjs} +337 -109
  14. package/dist/_chunks/index-DjDPK8kb.mjs.map +1 -0
  15. package/dist/_chunks/{index-fP3qoWZ4.js → index-DoZNNtsb.js} +340 -112
  16. package/dist/_chunks/index-DoZNNtsb.js.map +1 -0
  17. package/dist/admin/index.js +1 -15
  18. package/dist/admin/index.js.map +1 -1
  19. package/dist/admin/index.mjs +2 -16
  20. package/dist/admin/index.mjs.map +1 -1
  21. package/dist/admin/src/components/CMReleasesContainer.d.ts +22 -0
  22. package/dist/admin/src/components/RelativeTime.d.ts +28 -0
  23. package/dist/admin/src/components/ReleaseAction.d.ts +3 -0
  24. package/dist/admin/src/components/ReleaseActionMenu.d.ts +26 -0
  25. package/dist/admin/src/components/ReleaseActionOptions.d.ts +9 -0
  26. package/dist/admin/src/components/ReleaseListCell.d.ts +0 -0
  27. package/dist/admin/src/components/ReleaseModal.d.ts +16 -0
  28. package/dist/admin/src/constants.d.ts +58 -0
  29. package/dist/admin/src/index.d.ts +3 -0
  30. package/dist/admin/src/pages/App.d.ts +1 -0
  31. package/dist/admin/src/pages/PurchaseContentReleases.d.ts +2 -0
  32. package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +2 -0
  33. package/dist/admin/src/pages/ReleasesPage.d.ts +8 -0
  34. package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +181 -0
  35. package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +39 -0
  36. package/dist/admin/src/pluginId.d.ts +1 -0
  37. package/dist/admin/src/services/axios.d.ts +29 -0
  38. package/dist/admin/src/services/release.d.ts +429 -0
  39. package/dist/admin/src/store/hooks.d.ts +7 -0
  40. package/dist/admin/src/utils/prefixPluginTranslations.d.ts +3 -0
  41. package/dist/admin/src/utils/time.d.ts +1 -0
  42. package/dist/server/index.js +358 -237
  43. package/dist/server/index.js.map +1 -1
  44. package/dist/server/index.mjs +359 -237
  45. package/dist/server/index.mjs.map +1 -1
  46. package/dist/server/src/bootstrap.d.ts +5 -0
  47. package/dist/server/src/bootstrap.d.ts.map +1 -0
  48. package/dist/server/src/constants.d.ts +12 -0
  49. package/dist/server/src/constants.d.ts.map +1 -0
  50. package/dist/server/src/content-types/index.d.ts +99 -0
  51. package/dist/server/src/content-types/index.d.ts.map +1 -0
  52. package/dist/server/src/content-types/release/index.d.ts +48 -0
  53. package/dist/server/src/content-types/release/index.d.ts.map +1 -0
  54. package/dist/server/src/content-types/release/schema.d.ts +47 -0
  55. package/dist/server/src/content-types/release/schema.d.ts.map +1 -0
  56. package/dist/server/src/content-types/release-action/index.d.ts +50 -0
  57. package/dist/server/src/content-types/release-action/index.d.ts.map +1 -0
  58. package/dist/server/src/content-types/release-action/schema.d.ts +49 -0
  59. package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -0
  60. package/dist/server/src/controllers/index.d.ts +20 -0
  61. package/dist/server/src/controllers/index.d.ts.map +1 -0
  62. package/dist/server/src/controllers/release-action.d.ts +10 -0
  63. package/dist/server/src/controllers/release-action.d.ts.map +1 -0
  64. package/dist/server/src/controllers/release.d.ts +12 -0
  65. package/dist/server/src/controllers/release.d.ts.map +1 -0
  66. package/dist/server/src/controllers/validation/release-action.d.ts +8 -0
  67. package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -0
  68. package/dist/server/src/controllers/validation/release.d.ts +2 -0
  69. package/dist/server/src/controllers/validation/release.d.ts.map +1 -0
  70. package/dist/server/src/destroy.d.ts +5 -0
  71. package/dist/server/src/destroy.d.ts.map +1 -0
  72. package/dist/server/src/index.d.ts +2096 -0
  73. package/dist/server/src/index.d.ts.map +1 -0
  74. package/dist/server/src/migrations/index.d.ts +13 -0
  75. package/dist/server/src/migrations/index.d.ts.map +1 -0
  76. package/dist/server/src/register.d.ts +5 -0
  77. package/dist/server/src/register.d.ts.map +1 -0
  78. package/dist/server/src/routes/index.d.ts +35 -0
  79. package/dist/server/src/routes/index.d.ts.map +1 -0
  80. package/dist/server/src/routes/release-action.d.ts +18 -0
  81. package/dist/server/src/routes/release-action.d.ts.map +1 -0
  82. package/dist/server/src/routes/release.d.ts +18 -0
  83. package/dist/server/src/routes/release.d.ts.map +1 -0
  84. package/dist/server/src/services/index.d.ts +1826 -0
  85. package/dist/server/src/services/index.d.ts.map +1 -0
  86. package/dist/server/src/services/release.d.ts +66 -0
  87. package/dist/server/src/services/release.d.ts.map +1 -0
  88. package/dist/server/src/services/scheduling.d.ts +18 -0
  89. package/dist/server/src/services/scheduling.d.ts.map +1 -0
  90. package/dist/server/src/services/validation.d.ts +18 -0
  91. package/dist/server/src/services/validation.d.ts.map +1 -0
  92. package/dist/server/src/utils/index.d.ts +14 -0
  93. package/dist/server/src/utils/index.d.ts.map +1 -0
  94. package/dist/shared/contracts/release-actions.d.ts +131 -0
  95. package/dist/shared/contracts/release-actions.d.ts.map +1 -0
  96. package/dist/shared/contracts/releases.d.ts +182 -0
  97. package/dist/shared/contracts/releases.d.ts.map +1 -0
  98. package/dist/shared/types.d.ts +24 -0
  99. package/dist/shared/types.d.ts.map +1 -0
  100. package/dist/shared/validation-schemas.d.ts +2 -0
  101. package/dist/shared/validation-schemas.d.ts.map +1 -0
  102. package/package.json +26 -31
  103. package/dist/_chunks/App-bpzO2Ljh.mjs.map +0 -1
  104. package/dist/_chunks/App-p8aKBitd.js.map +0 -1
  105. package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +0 -1
  106. package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +0 -1
  107. package/dist/_chunks/en-WuuhP6Bn.mjs.map +0 -1
  108. package/dist/_chunks/en-gcJJ5htG.js.map +0 -1
  109. package/dist/_chunks/index-AECgcaDa.mjs.map +0 -1
  110. package/dist/_chunks/index-fP3qoWZ4.js.map +0 -1
@@ -1,23 +1,51 @@
1
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { RelativeTime, useNotification, useAPIErrorHandler, useQueryParams, useTracking, LoadingIndicatorPage, CheckPermissions, PageSizeURLQuery, PaginationURLQuery, AnErrorOccurred, ConfirmDialog, useRBAC, NoContent, Table, CheckPagePermissions } from "@strapi/helper-plugin";
3
- import { useLocation, useHistory, useParams, Redirect, Link as Link$2, Switch, Route } from "react-router-dom";
4
- import { g as getTimezoneOffset, p as pluginId, u as useGetReleasesQuery, a as useCreateReleaseMutation, P as PERMISSIONS, i as isAxiosError, b as useGetReleaseQuery, c as useUpdateReleaseMutation, d as useDeleteReleaseMutation, e as usePublishReleaseMutation, f as useTypedDispatch, h as useGetReleaseActionsQuery, j as useUpdateReleaseActionMutation, R as ReleaseActionOptions, k as ReleaseActionMenu, r as releaseApi } from "./index-AECgcaDa.mjs";
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { useNotification, useAPIErrorHandler, useQueryParams, useTracking, useRBAC, Page, Pagination, ConfirmDialog, BackButton, useStrapiApp, Table } from "@strapi/admin/strapi-admin";
3
+ import { useLocation, useNavigate, useParams, Navigate, Link as Link$1, Routes, Route } from "react-router-dom";
4
+ import { g as getTimezoneOffset, p as pluginId, u as useGetReleasesQuery, a as useCreateReleaseMutation, P as PERMISSIONS, i as isAxiosError, b as useGetReleaseQuery, c as useUpdateReleaseMutation, d as useDeleteReleaseMutation, e as usePublishReleaseMutation, f as useGetReleaseActionsQuery, h as useUpdateReleaseActionMutation, R as ReleaseActionOptions, j as ReleaseActionMenu, r as releaseApi } from "./index-DjDPK8kb.mjs";
5
5
  import * as React from "react";
6
- import { useLicenseLimits, unstable_useDocument } from "@strapi/admin/strapi-admin";
7
- import { ModalLayout, ModalHeader, Typography, ModalBody, Flex, TextInput, Box, Checkbox, DatePicker, TimePicker, ModalFooter, Button, Combobox, ComboboxOption, Alert, Main, HeaderLayout, ContentLayout, TabGroup, Tabs, Tab, Divider, TabPanels, TabPanel, EmptyStateLayout, Grid, GridItem, Badge, Link as Link$1, IconButton, SingleSelect, SingleSelectOption, Tr, Td, Icon, Tooltip } from "@strapi/design-system";
8
- import { Link, Menu, LinkButton } from "@strapi/design-system/v2";
9
- import { Plus, EmptyDocuments, Pencil, Trash, ArrowLeft, More, CrossCircle, CheckCircle } from "@strapi/icons";
6
+ import { ModalLayout, ModalHeader, Typography, ModalBody, Flex, TextInput, Box, Checkbox, DatePicker, TimePicker, ModalFooter, Button, Combobox, ComboboxOption, Link, Alert, Main, HeaderLayout, ContentLayout, TabGroup, Tabs, Tab, Divider, TabPanels, TabPanel, EmptyStateLayout, Grid, GridItem, Badge, Menu, IconButton, LinkButton, SingleSelect, SingleSelectOption, Tr, Td, Tooltip } from "@strapi/design-system";
7
+ import { Plus, Pencil, Trash, More, CrossCircle, CheckCircle } from "@strapi/icons";
8
+ import { EmptyDocuments } from "@strapi/icons/symbols";
9
+ import { unstable_useDocument } from "@strapi/plugin-content-manager/strapi-admin";
10
10
  import format from "date-fns/format";
11
11
  import { utcToZonedTime, zonedTimeToUtc } from "date-fns-tz";
12
12
  import { useIntl } from "react-intl";
13
13
  import styled from "styled-components";
14
- import { formatISO, parse } from "date-fns";
14
+ import { intervalToDuration, isPast, formatISO } from "date-fns";
15
15
  import { Formik, Form, useFormikContext } from "formik";
16
16
  import * as yup from "yup";
17
- import "@reduxjs/toolkit/query";
18
- import "axios";
19
- import "@reduxjs/toolkit/query/react";
20
- import "react-redux";
17
+ import { useDispatch } from "react-redux";
18
+ import { useLicenseLimits } from "@strapi/admin/strapi-admin/ee";
19
+ const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
20
+ const RelativeTime$1 = React.forwardRef(
21
+ ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
22
+ const { formatRelativeTime, formatDate, formatTime } = useIntl();
23
+ const interval = intervalToDuration({
24
+ start: timestamp,
25
+ end: Date.now()
26
+ // see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
27
+ });
28
+ const unit = intervals.find((intervalUnit) => {
29
+ return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
30
+ });
31
+ const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
32
+ const customInterval = customIntervals.find(
33
+ (custom) => interval[custom.unit] < custom.threshold
34
+ );
35
+ const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
36
+ return /* @__PURE__ */ jsx(
37
+ "time",
38
+ {
39
+ ref: forwardedRef,
40
+ dateTime: timestamp.toISOString(),
41
+ role: "time",
42
+ title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
43
+ ...restProps,
44
+ children: displayText
45
+ }
46
+ );
47
+ }
48
+ );
21
49
  const RELEASE_SCHEMA = yup.object().shape({
22
50
  name: yup.string().trim().required(),
23
51
  scheduledAt: yup.string().nullable(),
@@ -47,7 +75,6 @@ const ReleaseModal = ({
47
75
  const { formatMessage } = useIntl();
48
76
  const { pathname } = useLocation();
49
77
  const isCreatingRelease = pathname === `/plugins/${pluginId}`;
50
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
51
78
  const { timezoneList, systemTimezone = { value: "UTC+00:00-Africa/Abidjan " } } = getTimezones(
52
79
  initialValues.scheduledAt ? new Date(initialValues.scheduledAt) : /* @__PURE__ */ new Date()
53
80
  );
@@ -55,9 +82,8 @@ const ReleaseModal = ({
55
82
  const { date, time, timezone } = values;
56
83
  if (!date || !time || !timezone)
57
84
  return null;
58
- const formattedDate = parse(time, "HH:mm", new Date(date));
59
85
  const timezoneWithoutOffset = timezone.split("&")[1];
60
- return zonedTimeToUtc(formattedDate, timezoneWithoutOffset);
86
+ return zonedTimeToUtc(`${date} ${time}`, timezoneWithoutOffset);
61
87
  };
62
88
  const getTimezoneWithOffset = () => {
63
89
  const currentTimezone = timezoneList.find(
@@ -105,93 +131,88 @@ const ReleaseModal = ({
105
131
  required: true
106
132
  }
107
133
  ),
108
- IsSchedulingEnabled && /* @__PURE__ */ jsxs(Fragment, { children: [
109
- /* @__PURE__ */ jsx(Box, { width: "max-content", children: /* @__PURE__ */ jsx(
110
- Checkbox,
111
- {
112
- name: "isScheduled",
113
- value: values.isScheduled,
114
- onChange: (event) => {
115
- setFieldValue("isScheduled", event.target.checked);
116
- if (!event.target.checked) {
134
+ /* @__PURE__ */ jsx(Box, { width: "max-content", children: /* @__PURE__ */ jsx(
135
+ Checkbox,
136
+ {
137
+ name: "isScheduled",
138
+ value: values.isScheduled,
139
+ onChange: (event) => {
140
+ setFieldValue("isScheduled", event.target.checked);
141
+ if (!event.target.checked) {
142
+ setFieldValue("date", null);
143
+ setFieldValue("time", "");
144
+ setFieldValue("timezone", null);
145
+ } else {
146
+ setFieldValue("date", initialValues.date);
147
+ setFieldValue("time", initialValues.time);
148
+ setFieldValue("timezone", initialValues.timezone ?? systemTimezone?.value);
149
+ }
150
+ },
151
+ children: /* @__PURE__ */ jsx(
152
+ Typography,
153
+ {
154
+ textColor: values.isScheduled ? "primary600" : "neutral800",
155
+ fontWeight: values.isScheduled ? "semiBold" : "regular",
156
+ children: formatMessage({
157
+ id: "modal.form.input.label.schedule-release",
158
+ defaultMessage: "Schedule release"
159
+ })
160
+ }
161
+ )
162
+ }
163
+ ) }),
164
+ values.isScheduled && /* @__PURE__ */ jsxs(Fragment, { children: [
165
+ /* @__PURE__ */ jsxs(Flex, { gap: 4, alignItems: "start", children: [
166
+ /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
167
+ DatePicker,
168
+ {
169
+ label: formatMessage({
170
+ id: "content-releases.modal.form.input.label.date",
171
+ defaultMessage: "Date"
172
+ }),
173
+ name: "date",
174
+ error: errors.date,
175
+ onChange: (date) => {
176
+ const isoFormatDate = date ? formatISO(date, { representation: "date" }) : null;
177
+ setFieldValue("date", isoFormatDate);
178
+ },
179
+ clearLabel: formatMessage({
180
+ id: "content-releases.modal.form.input.clearLabel",
181
+ defaultMessage: "Clear"
182
+ }),
183
+ onClear: () => {
117
184
  setFieldValue("date", null);
185
+ },
186
+ selectedDate: values.date || void 0,
187
+ required: true,
188
+ minDate: utcToZonedTime(/* @__PURE__ */ new Date(), values.timezone.split("&")[1])
189
+ }
190
+ ) }),
191
+ /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
192
+ TimePicker,
193
+ {
194
+ label: formatMessage({
195
+ id: "content-releases.modal.form.input.label.time",
196
+ defaultMessage: "Time"
197
+ }),
198
+ name: "time",
199
+ error: errors.time,
200
+ onChange: (time) => {
201
+ setFieldValue("time", time);
202
+ },
203
+ clearLabel: formatMessage({
204
+ id: "content-releases.modal.form.input.clearLabel",
205
+ defaultMessage: "Clear"
206
+ }),
207
+ onClear: () => {
118
208
  setFieldValue("time", "");
119
- setFieldValue("timezone", null);
120
- } else {
121
- setFieldValue("date", initialValues.date);
122
- setFieldValue("time", initialValues.time);
123
- setFieldValue(
124
- "timezone",
125
- initialValues.timezone ?? systemTimezone?.value
126
- );
127
- }
128
- },
129
- children: /* @__PURE__ */ jsx(
130
- Typography,
131
- {
132
- textColor: values.isScheduled ? "primary600" : "neutral800",
133
- fontWeight: values.isScheduled ? "semiBold" : "regular",
134
- children: formatMessage({
135
- id: "modal.form.input.label.schedule-release",
136
- defaultMessage: "Schedule release"
137
- })
138
- }
139
- )
140
- }
141
- ) }),
142
- values.isScheduled && /* @__PURE__ */ jsxs(Fragment, { children: [
143
- /* @__PURE__ */ jsxs(Flex, { gap: 4, alignItems: "start", children: [
144
- /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
145
- DatePicker,
146
- {
147
- label: formatMessage({
148
- id: "content-releases.modal.form.input.label.date",
149
- defaultMessage: "Date"
150
- }),
151
- name: "date",
152
- error: errors.date,
153
- onChange: (date) => {
154
- const isoFormatDate = date ? formatISO(date, { representation: "date" }) : null;
155
- setFieldValue("date", isoFormatDate);
156
- },
157
- clearLabel: formatMessage({
158
- id: "content-releases.modal.form.input.clearLabel",
159
- defaultMessage: "Clear"
160
- }),
161
- onClear: () => {
162
- setFieldValue("date", null);
163
- },
164
- selectedDate: values.date || void 0,
165
- required: true,
166
- minDate: utcToZonedTime(/* @__PURE__ */ new Date(), values.timezone.split("&")[1])
167
- }
168
- ) }),
169
- /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
170
- TimePicker,
171
- {
172
- label: formatMessage({
173
- id: "content-releases.modal.form.input.label.time",
174
- defaultMessage: "Time"
175
- }),
176
- name: "time",
177
- error: errors.time,
178
- onChange: (time) => {
179
- setFieldValue("time", time);
180
- },
181
- clearLabel: formatMessage({
182
- id: "content-releases.modal.form.input.clearLabel",
183
- defaultMessage: "Clear"
184
- }),
185
- onClear: () => {
186
- setFieldValue("time", "");
187
- },
188
- value: values.time || void 0,
189
- required: true
190
- }
191
- ) })
192
- ] }),
193
- /* @__PURE__ */ jsx(TimezoneComponent, { timezoneOptions: timezoneList })
194
- ] })
209
+ },
210
+ value: values.time || void 0,
211
+ required: true
212
+ }
213
+ ) })
214
+ ] }),
215
+ /* @__PURE__ */ jsx(TimezoneComponent, { timezoneOptions: timezoneList })
195
216
  ] })
196
217
  ] }) }),
197
218
  /* @__PURE__ */ jsx(
@@ -262,11 +283,15 @@ const TimezoneComponent = ({ timezoneOptions }) => {
262
283
  }
263
284
  );
264
285
  };
286
+ const useTypedDispatch = useDispatch;
265
287
  const LinkCard = styled(Link)`
266
288
  display: block;
267
289
  `;
268
- const CapitalizeRelativeTime = styled(RelativeTime)`
269
- text-transform: capitalize;
290
+ const RelativeTime = styled(RelativeTime$1)`
291
+ display: inline-block;
292
+ &::first-letter {
293
+ text-transform: uppercase;
294
+ }
270
295
  `;
271
296
  const getBadgeProps = (status) => {
272
297
  let color;
@@ -295,9 +320,8 @@ const getBadgeProps = (status) => {
295
320
  };
296
321
  const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
297
322
  const { formatMessage } = useIntl();
298
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
299
323
  if (isError) {
300
- return /* @__PURE__ */ jsx(AnErrorOccurred, {});
324
+ return /* @__PURE__ */ jsx(Page.Error, {});
301
325
  }
302
326
  if (releases?.length === 0) {
303
327
  return /* @__PURE__ */ jsx(
@@ -312,11 +336,11 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
312
336
  target: sectionTitle
313
337
  }
314
338
  ),
315
- icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem" })
339
+ icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "16rem" })
316
340
  }
317
341
  );
318
342
  }
319
- return /* @__PURE__ */ jsx(Grid, { gap: 4, children: releases.map(({ id, name, actions, scheduledAt, status }) => /* @__PURE__ */ jsx(GridItem, { col: 3, s: 6, xs: 12, children: /* @__PURE__ */ jsx(LinkCard, { href: `content-releases/${id}`, isExternal: false, children: /* @__PURE__ */ jsxs(
343
+ return /* @__PURE__ */ jsx(Grid, { gap: 4, children: releases.map(({ id, name, scheduledAt, status }) => /* @__PURE__ */ jsx(GridItem, { col: 3, s: 6, xs: 12, children: /* @__PURE__ */ jsx(LinkCard, { href: `content-releases/${id}`, isExternal: false, children: /* @__PURE__ */ jsxs(
320
344
  Flex,
321
345
  {
322
346
  direction: "column",
@@ -332,16 +356,10 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
332
356
  children: [
333
357
  /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "start", gap: 1, children: [
334
358
  /* @__PURE__ */ jsx(Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
335
- /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: IsSchedulingEnabled ? scheduledAt ? /* @__PURE__ */ jsx(CapitalizeRelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
359
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: scheduledAt ? /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
336
360
  id: "content-releases.pages.Releases.not-scheduled",
337
361
  defaultMessage: "Not scheduled"
338
- }) : formatMessage(
339
- {
340
- id: "content-releases.page.Releases.release-item.entries",
341
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
342
- },
343
- { number: actions.meta.count }
344
- ) })
362
+ }) })
345
363
  ] }),
346
364
  /* @__PURE__ */ jsx(Badge, { ...getBadgeProps(status), children: status })
347
365
  ]
@@ -360,8 +378,7 @@ const INITIAL_FORM_VALUES = {
360
378
  name: "",
361
379
  date: null,
362
380
  time: "",
363
- // Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
364
- isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
381
+ isScheduled: true,
365
382
  scheduledAt: null,
366
383
  timezone: null
367
384
  };
@@ -369,9 +386,9 @@ const ReleasesPage = () => {
369
386
  const tabRef = React.useRef(null);
370
387
  const location = useLocation();
371
388
  const [releaseModalShown, setReleaseModalShown] = React.useState(false);
372
- const toggleNotification = useNotification();
389
+ const { toggleNotification } = useNotification();
373
390
  const { formatMessage } = useIntl();
374
- const { push, replace } = useHistory();
391
+ const navigate = useNavigate();
375
392
  const { formatAPIError } = useAPIErrorHandler();
376
393
  const [{ query }, setQuery] = useQueryParams();
377
394
  const response = useGetReleasesQuery(query);
@@ -379,13 +396,16 @@ const ReleasesPage = () => {
379
396
  const { getFeature } = useLicenseLimits();
380
397
  const { maximumReleases = 3 } = getFeature("cms-content-releases");
381
398
  const { trackUsage } = useTracking();
399
+ const {
400
+ allowedActions: { canCreate }
401
+ } = useRBAC(PERMISSIONS);
382
402
  const { isLoading, isSuccess, isError } = response;
383
403
  const activeTab = response?.currentData?.meta?.activeTab || "pending";
384
404
  const activeTabIndex = ["pending", "done"].indexOf(activeTab);
385
405
  React.useEffect(() => {
386
406
  if (location?.state?.errors) {
387
407
  toggleNotification({
388
- type: "warning",
408
+ type: "danger",
389
409
  title: formatMessage({
390
410
  id: "content-releases.pages.Releases.notification.error.title",
391
411
  defaultMessage: "Your request could not be processed."
@@ -395,9 +415,9 @@ const ReleasesPage = () => {
395
415
  defaultMessage: "Please try again or open another release."
396
416
  })
397
417
  });
398
- replace({ state: null });
418
+ navigate("", { replace: true, state: null });
399
419
  }
400
- }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
420
+ }, [formatMessage, location?.state?.errors, navigate, toggleNotification]);
401
421
  React.useEffect(() => {
402
422
  if (tabRef.current) {
403
423
  tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
@@ -407,7 +427,7 @@ const ReleasesPage = () => {
407
427
  setReleaseModalShown((prev) => !prev);
408
428
  };
409
429
  if (isLoading) {
410
- return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
430
+ return /* @__PURE__ */ jsx(Page.Loading, {});
411
431
  }
412
432
  const totalPendingReleases = isSuccess && response.currentData?.meta?.pendingReleasesCount || 0;
413
433
  const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
@@ -438,15 +458,15 @@ const ReleasesPage = () => {
438
458
  })
439
459
  });
440
460
  trackUsage("didCreateRelease");
441
- push(`/plugins/content-releases/${response2.data.data.id}`);
461
+ navigate(response2.data.data.id.toString());
442
462
  } else if (isAxiosError(response2.error)) {
443
463
  toggleNotification({
444
- type: "warning",
464
+ type: "danger",
445
465
  message: formatAPIError(response2.error)
446
466
  });
447
467
  } else {
448
468
  toggleNotification({
449
- type: "warning",
469
+ type: "danger",
450
470
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
451
471
  });
452
472
  }
@@ -463,7 +483,7 @@ const ReleasesPage = () => {
463
483
  id: "content-releases.pages.Releases.header-subtitle",
464
484
  defaultMessage: "Create and manage content updates"
465
485
  }),
466
- primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(
486
+ primaryAction: canCreate ? /* @__PURE__ */ jsx(
467
487
  Button,
468
488
  {
469
489
  startIcon: /* @__PURE__ */ jsx(Plus, {}),
@@ -474,7 +494,7 @@ const ReleasesPage = () => {
474
494
  defaultMessage: "New release"
475
495
  })
476
496
  }
477
- ) })
497
+ ) : null
478
498
  }
479
499
  ),
480
500
  /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -553,23 +573,17 @@ const ReleasesPage = () => {
553
573
  ]
554
574
  }
555
575
  ),
556
- response.currentData?.meta?.pagination?.total ? /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
557
- /* @__PURE__ */ jsx(
558
- PageSizeURLQuery,
559
- {
560
- options: ["8", "16", "32", "64"],
561
- defaultValue: response?.currentData?.meta?.pagination?.pageSize.toString()
562
- }
563
- ),
564
- /* @__PURE__ */ jsx(
565
- PaginationURLQuery,
566
- {
567
- pagination: {
568
- pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
569
- }
570
- }
571
- )
572
- ] }) : null
576
+ /* @__PURE__ */ jsxs(
577
+ Pagination.Root,
578
+ {
579
+ ...response?.currentData?.meta?.pagination,
580
+ defaultPageSize: response?.currentData?.meta?.pagination?.pageSize,
581
+ children: [
582
+ /* @__PURE__ */ jsx(Pagination.PageSize, { options: ["8", "16", "32", "64"] }),
583
+ /* @__PURE__ */ jsx(Pagination.Links, {})
584
+ ]
585
+ }
586
+ )
573
587
  ] }) }),
574
588
  releaseModalShown && /* @__PURE__ */ jsx(
575
589
  ReleaseModal,
@@ -617,14 +631,18 @@ const TrashIcon = styled(Trash)`
617
631
  const TypographyMaxWidth = styled(Typography)`
618
632
  max-width: 300px;
619
633
  `;
620
- const EntryValidationText = ({ action, schema, components, entry }) => {
634
+ const EntryValidationText = ({ action, schema, entry }) => {
621
635
  const { formatMessage } = useIntl();
622
- const { validate } = unstable_useDocument();
623
- const { errors } = validate(entry, {
624
- contentType: schema,
625
- components,
626
- isCreatingEntry: false
627
- });
636
+ const { validate } = unstable_useDocument(
637
+ {
638
+ collectionType: schema?.kind ?? "",
639
+ model: schema?.uid ?? ""
640
+ },
641
+ {
642
+ skip: !schema
643
+ }
644
+ );
645
+ const errors = validate(entry) ?? {};
628
646
  if (Object.keys(errors).length > 0) {
629
647
  const validationErrorsMessages = Object.entries(errors).map(
630
648
  ([key, value]) => formatMessage(
@@ -633,13 +651,13 @@ const EntryValidationText = ({ action, schema, components, entry }) => {
633
651
  )
634
652
  ).join(" ");
635
653
  return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
636
- /* @__PURE__ */ jsx(Icon, { color: "danger600", as: CrossCircle }),
654
+ /* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
637
655
  /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
638
656
  ] });
639
657
  }
640
658
  if (action == "publish") {
641
659
  return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
642
- /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
660
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
643
661
  entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
644
662
  id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
645
663
  defaultMessage: "Already published"
@@ -650,7 +668,7 @@ const EntryValidationText = ({ action, schema, components, entry }) => {
650
668
  ] });
651
669
  }
652
670
  return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
653
- /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
671
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
654
672
  !entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
655
673
  id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
656
674
  defaultMessage: "Already unpublished"
@@ -672,18 +690,22 @@ const ReleaseDetailsLayout = ({
672
690
  isLoading: isLoadingDetails,
673
691
  isError,
674
692
  error
675
- } = useGetReleaseQuery({ id: releaseId });
693
+ } = useGetReleaseQuery(
694
+ { id: releaseId },
695
+ {
696
+ skip: !releaseId
697
+ }
698
+ );
676
699
  const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();
677
- const toggleNotification = useNotification();
700
+ const { toggleNotification } = useNotification();
678
701
  const { formatAPIError } = useAPIErrorHandler();
679
- const {
680
- allowedActions: { canUpdate, canDelete }
681
- } = useRBAC(PERMISSIONS);
702
+ const { allowedActions } = useRBAC(PERMISSIONS);
703
+ const { canUpdate, canDelete, canPublish } = allowedActions;
682
704
  const dispatch = useTypedDispatch();
683
705
  const { trackUsage } = useTracking();
684
706
  const release = data?.data;
685
- const handlePublishRelease = async () => {
686
- const response = await publishRelease({ id: releaseId });
707
+ const handlePublishRelease = (id) => async () => {
708
+ const response = await publishRelease({ id });
687
709
  if ("data" in response) {
688
710
  toggleNotification({
689
711
  type: "success",
@@ -700,18 +722,23 @@ const ReleaseDetailsLayout = ({
700
722
  });
701
723
  } else if (isAxiosError(response.error)) {
702
724
  toggleNotification({
703
- type: "warning",
725
+ type: "danger",
704
726
  message: formatAPIError(response.error)
705
727
  });
706
728
  } else {
707
729
  toggleNotification({
708
- type: "warning",
730
+ type: "danger",
709
731
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
710
732
  });
711
733
  }
712
734
  };
713
735
  const handleRefresh = () => {
714
- dispatch(releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
736
+ dispatch(
737
+ releaseApi.util.invalidateTags([
738
+ { type: "ReleaseAction", id: "LIST" },
739
+ { type: "Release", id: releaseId }
740
+ ])
741
+ );
715
742
  };
716
743
  const getCreatedByUser = () => {
717
744
  if (!release?.createdBy) {
@@ -726,28 +753,25 @@ const ReleaseDetailsLayout = ({
726
753
  return release.createdBy.email;
727
754
  };
728
755
  if (isLoadingDetails) {
729
- return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
756
+ return /* @__PURE__ */ jsx(Page.Loading, {});
730
757
  }
731
758
  if (isError || !release) {
732
759
  return /* @__PURE__ */ jsx(
733
- Redirect,
760
+ Navigate,
734
761
  {
735
- to: {
736
- pathname: "/plugins/content-releases",
737
- state: {
738
- errors: [
739
- {
740
- code: error?.code
741
- }
742
- ]
743
- }
762
+ to: "..",
763
+ state: {
764
+ errors: [
765
+ {
766
+ code: error?.code
767
+ }
768
+ ]
744
769
  }
745
770
  }
746
771
  );
747
772
  }
748
773
  const totalEntries = release.actions.meta.count || 0;
749
774
  const hasCreatedByUser = Boolean(getCreatedByUser());
750
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
751
775
  const isScheduled = release.scheduledAt && release.timezone;
752
776
  const numberOfEntriesText = formatMessage(
753
777
  {
@@ -782,13 +806,10 @@ const ReleaseDetailsLayout = ({
782
806
  {
783
807
  title: release.name,
784
808
  subtitle: /* @__PURE__ */ jsxs(Flex, { gap: 2, lineHeight: 6, children: [
785
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", variant: "epsilon", children: numberOfEntriesText + (IsSchedulingEnabled && isScheduled ? ` - ${scheduledText}` : "") }),
809
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", variant: "epsilon", children: numberOfEntriesText + (isScheduled ? ` - ${scheduledText}` : "") }),
786
810
  /* @__PURE__ */ jsx(Badge, { ...getBadgeProps(release.status), children: release.status })
787
811
  ] }),
788
- navigationAction: /* @__PURE__ */ jsx(Link$1, { startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
789
- id: "global.back",
790
- defaultMessage: "Back"
791
- }) }),
812
+ navigationAction: /* @__PURE__ */ jsx(BackButton, {}),
792
813
  primaryAction: !release.releasedAt && /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
793
814
  /* @__PURE__ */ jsxs(Menu.Root, { children: [
794
815
  /* @__PURE__ */ jsx(
@@ -805,7 +826,7 @@ const ReleaseDetailsLayout = ({
805
826
  variant: "tertiary"
806
827
  }
807
828
  ),
808
- /* @__PURE__ */ jsxs(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: [
829
+ /* @__PURE__ */ jsxs(Menu.Content, { top: 1, popoverPlacement: "bottom-end", maxHeight: void 0, children: [
809
830
  /* @__PURE__ */ jsxs(
810
831
  Flex,
811
832
  {
@@ -854,7 +875,7 @@ const ReleaseDetailsLayout = ({
854
875
  defaultMessage: "Created"
855
876
  }) }),
856
877
  /* @__PURE__ */ jsxs(Typography, { variant: "pi", color: "neutral300", children: [
857
- /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(release.createdAt) }),
878
+ /* @__PURE__ */ jsx(RelativeTime$1, { timestamp: new Date(release.createdAt) }),
858
879
  formatMessage(
859
880
  {
860
881
  id: "content-releases.header.actions.created.description",
@@ -872,12 +893,12 @@ const ReleaseDetailsLayout = ({
872
893
  id: "content-releases.header.actions.refresh",
873
894
  defaultMessage: "Refresh"
874
895
  }) }),
875
- /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.publish, children: /* @__PURE__ */ jsx(
896
+ canPublish ? /* @__PURE__ */ jsx(
876
897
  Button,
877
898
  {
878
899
  size: "S",
879
900
  variant: "default",
880
- onClick: handlePublishRelease,
901
+ onClick: handlePublishRelease(release.id.toString()),
881
902
  loading: isPublishing,
882
903
  disabled: release.actions.meta.count === 0,
883
904
  children: formatMessage({
@@ -885,7 +906,7 @@ const ReleaseDetailsLayout = ({
885
906
  defaultMessage: "Publish"
886
907
  })
887
908
  }
888
- ) })
909
+ ) : null
889
910
  ] })
890
911
  }
891
912
  ),
@@ -893,6 +914,7 @@ const ReleaseDetailsLayout = ({
893
914
  ] });
894
915
  };
895
916
  const GROUP_BY_OPTIONS = ["contentType", "locale", "action"];
917
+ const GROUP_BY_OPTIONS_NO_LOCALE = ["contentType", "action"];
896
918
  const getGroupByOptionLabel = (value) => {
897
919
  if (value === "locale") {
898
920
  return {
@@ -911,11 +933,10 @@ const getGroupByOptionLabel = (value) => {
911
933
  defaultMessage: "Content-Types"
912
934
  };
913
935
  };
914
- const ReleaseDetailsBody = () => {
936
+ const ReleaseDetailsBody = ({ releaseId }) => {
915
937
  const { formatMessage } = useIntl();
916
- const { releaseId } = useParams();
917
938
  const [{ query }, setQuery] = useQueryParams();
918
- const toggleNotification = useNotification();
939
+ const { toggleNotification } = useNotification();
919
940
  const { formatAPIError } = useAPIErrorHandler();
920
941
  const {
921
942
  data: releaseData,
@@ -926,6 +947,20 @@ const ReleaseDetailsBody = () => {
926
947
  const {
927
948
  allowedActions: { canUpdate }
928
949
  } = useRBAC(PERMISSIONS);
950
+ const runHookWaterfall = useStrapiApp("ReleaseDetailsPage", (state) => state.runHookWaterfall);
951
+ const { hasI18nEnabled } = runHookWaterfall(
952
+ "ContentReleases/pages/ReleaseDetails/add-locale-in-releases",
953
+ {
954
+ displayedHeaders: {
955
+ label: formatMessage({
956
+ id: "content-releases.page.ReleaseDetails.table.header.label.locale",
957
+ defaultMessage: "locale"
958
+ }),
959
+ name: "locale"
960
+ },
961
+ hasI18nEnabled: false
962
+ }
963
+ );
929
964
  const release = releaseData?.data;
930
965
  const selectedGroupBy = query?.groupBy || "contentType";
931
966
  const {
@@ -956,19 +991,19 @@ const ReleaseDetailsBody = () => {
956
991
  if ("error" in response) {
957
992
  if (isAxiosError(response.error)) {
958
993
  toggleNotification({
959
- type: "warning",
994
+ type: "danger",
960
995
  message: formatAPIError(response.error)
961
996
  });
962
997
  } else {
963
998
  toggleNotification({
964
- type: "warning",
999
+ type: "danger",
965
1000
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
966
1001
  });
967
1002
  }
968
1003
  }
969
1004
  };
970
1005
  if (isLoading || isReleaseLoading) {
971
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
1006
+ return /* @__PURE__ */ jsx(Page.Loading, {});
972
1007
  }
973
1008
  const releaseActions = data?.data;
974
1009
  const releaseMeta = data?.meta;
@@ -987,32 +1022,26 @@ const ReleaseDetailsBody = () => {
987
1022
  });
988
1023
  }
989
1024
  return /* @__PURE__ */ jsx(
990
- Redirect,
1025
+ Navigate,
991
1026
  {
992
- to: {
993
- pathname: "/plugins/content-releases",
994
- state: {
995
- errors: errorsArray
996
- }
1027
+ to: "..",
1028
+ state: {
1029
+ errors: errorsArray
997
1030
  }
998
1031
  }
999
1032
  );
1000
1033
  }
1001
1034
  if (isError || !releaseActions) {
1002
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(AnErrorOccurred, {}) });
1035
+ return /* @__PURE__ */ jsx(Page.Error, {});
1003
1036
  }
1004
1037
  if (Object.keys(releaseActions).length === 0) {
1005
1038
  return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(
1006
- NoContent,
1039
+ EmptyStateLayout,
1007
1040
  {
1008
- content: {
1009
- id: "content-releases.pages.Details.tab.emptyEntries",
1010
- defaultMessage: "This release is empty. Open the Content Manager, select an entry and add it to the release."
1011
- },
1012
1041
  action: /* @__PURE__ */ jsx(
1013
1042
  LinkButton,
1014
1043
  {
1015
- as: Link$2,
1044
+ as: Link$1,
1016
1045
  to: {
1017
1046
  pathname: "/content-manager"
1018
1047
  },
@@ -1023,18 +1052,59 @@ const ReleaseDetailsBody = () => {
1023
1052
  defaultMessage: "Open the Content Manager"
1024
1053
  })
1025
1054
  }
1026
- )
1055
+ ),
1056
+ icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "16rem" }),
1057
+ content: formatMessage({
1058
+ id: "content-releases.pages.Details.tab.emptyEntries",
1059
+ defaultMessage: "This release is empty. Open the Content Manager, select an entry and add it to the release."
1060
+ })
1027
1061
  }
1028
1062
  ) });
1029
1063
  }
1064
+ const groupByLabel = formatMessage({
1065
+ id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
1066
+ defaultMessage: "Group by"
1067
+ });
1068
+ const headers = [
1069
+ // ...displayedHeaders,
1070
+ {
1071
+ label: formatMessage({
1072
+ id: "content-releases.page.ReleaseDetails.table.header.label.name",
1073
+ defaultMessage: "name"
1074
+ }),
1075
+ name: "name"
1076
+ },
1077
+ {
1078
+ label: formatMessage({
1079
+ id: "content-releases.page.ReleaseDetails.table.header.label.content-type",
1080
+ defaultMessage: "content-type"
1081
+ }),
1082
+ name: "content-type"
1083
+ },
1084
+ {
1085
+ label: formatMessage({
1086
+ id: "content-releases.page.ReleaseDetails.table.header.label.action",
1087
+ defaultMessage: "action"
1088
+ }),
1089
+ name: "action"
1090
+ },
1091
+ ...!release.releasedAt ? [
1092
+ {
1093
+ label: formatMessage({
1094
+ id: "content-releases.page.ReleaseDetails.table.header.label.status",
1095
+ defaultMessage: "status"
1096
+ }),
1097
+ name: "status"
1098
+ }
1099
+ ] : []
1100
+ ];
1101
+ const options = hasI18nEnabled ? GROUP_BY_OPTIONS : GROUP_BY_OPTIONS_NO_LOCALE;
1030
1102
  return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
1031
1103
  /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
1032
1104
  SingleSelect,
1033
1105
  {
1034
- "aria-label": formatMessage({
1035
- id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
1036
- defaultMessage: "Group by"
1037
- }),
1106
+ placeholder: groupByLabel,
1107
+ "aria-label": groupByLabel,
1038
1108
  customizeContent: (value) => formatMessage(
1039
1109
  {
1040
1110
  id: `content-releases.pages.ReleaseDetails.groupBy.label`,
@@ -1046,7 +1116,7 @@ const ReleaseDetailsBody = () => {
1046
1116
  ),
1047
1117
  value: formatMessage(getGroupByOptionLabel(selectedGroupBy)),
1048
1118
  onChange: (value) => setQuery({ groupBy: value }),
1049
- children: GROUP_BY_OPTIONS.map((option) => /* @__PURE__ */ jsx(SingleSelectOption, { value: option, children: formatMessage(getGroupByOptionLabel(option)) }, option))
1119
+ children: options.map((option) => /* @__PURE__ */ jsx(SingleSelectOption, { value: option, children: formatMessage(getGroupByOptionLabel(option)) }, option))
1050
1120
  }
1051
1121
  ) }),
1052
1122
  Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
@@ -1058,72 +1128,15 @@ const ReleaseDetailsBody = () => {
1058
1128
  ...item,
1059
1129
  id: Number(item.entry.id)
1060
1130
  })),
1061
- colCount: releaseActions[key].length,
1062
- isLoading,
1063
- isFetching,
1131
+ headers,
1132
+ isLoading: isLoading || isFetching,
1064
1133
  children: /* @__PURE__ */ jsxs(Table.Content, { children: [
1065
- /* @__PURE__ */ jsxs(Table.Head, { children: [
1066
- /* @__PURE__ */ jsx(
1067
- Table.HeaderCell,
1068
- {
1069
- fieldSchemaType: "string",
1070
- label: formatMessage({
1071
- id: "content-releases.page.ReleaseDetails.table.header.label.name",
1072
- defaultMessage: "name"
1073
- }),
1074
- name: "name"
1075
- }
1076
- ),
1077
- /* @__PURE__ */ jsx(
1078
- Table.HeaderCell,
1079
- {
1080
- fieldSchemaType: "string",
1081
- label: formatMessage({
1082
- id: "content-releases.page.ReleaseDetails.table.header.label.locale",
1083
- defaultMessage: "locale"
1084
- }),
1085
- name: "locale"
1086
- }
1087
- ),
1088
- /* @__PURE__ */ jsx(
1089
- Table.HeaderCell,
1090
- {
1091
- fieldSchemaType: "string",
1092
- label: formatMessage({
1093
- id: "content-releases.page.ReleaseDetails.table.header.label.content-type",
1094
- defaultMessage: "content-type"
1095
- }),
1096
- name: "content-type"
1097
- }
1098
- ),
1099
- /* @__PURE__ */ jsx(
1100
- Table.HeaderCell,
1101
- {
1102
- fieldSchemaType: "string",
1103
- label: formatMessage({
1104
- id: "content-releases.page.ReleaseDetails.table.header.label.action",
1105
- defaultMessage: "action"
1106
- }),
1107
- name: "action"
1108
- }
1109
- ),
1110
- !release.releasedAt && /* @__PURE__ */ jsx(
1111
- Table.HeaderCell,
1112
- {
1113
- fieldSchemaType: "string",
1114
- label: formatMessage({
1115
- id: "content-releases.page.ReleaseDetails.table.header.label.status",
1116
- defaultMessage: "status"
1117
- }),
1118
- name: "status"
1119
- }
1120
- )
1121
- ] }),
1122
- /* @__PURE__ */ jsx(Table.LoadingBody, {}),
1134
+ /* @__PURE__ */ jsx(Table.Head, { children: headers.map((header) => /* @__PURE__ */ jsx(Table.HeaderCell, { ...header }, header.name)) }),
1135
+ /* @__PURE__ */ jsx(Table.Loading, {}),
1123
1136
  /* @__PURE__ */ jsx(Table.Body, { children: releaseActions[key].map(
1124
1137
  ({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxs(Tr, { children: [
1125
1138
  /* @__PURE__ */ jsx(Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
1126
- /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
1139
+ hasI18nEnabled && /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
1127
1140
  /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: contentType.displayName || "" }) }),
1128
1141
  /* @__PURE__ */ jsx(Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsx(Typography, { children: formatMessage(
1129
1142
  {
@@ -1177,34 +1190,39 @@ const ReleaseDetailsBody = () => {
1177
1190
  }
1178
1191
  )
1179
1192
  ] }, `releases-group-${key}`)),
1180
- /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
1181
- /* @__PURE__ */ jsx(PageSizeURLQuery, { defaultValue: releaseMeta?.pagination?.pageSize.toString() }),
1182
- /* @__PURE__ */ jsx(
1183
- PaginationURLQuery,
1184
- {
1185
- pagination: {
1186
- pageCount: releaseMeta?.pagination?.pageCount || 0
1187
- }
1188
- }
1189
- )
1190
- ] })
1193
+ /* @__PURE__ */ jsxs(
1194
+ Pagination.Root,
1195
+ {
1196
+ ...releaseMeta?.pagination,
1197
+ defaultPageSize: releaseMeta?.pagination?.pageSize,
1198
+ children: [
1199
+ /* @__PURE__ */ jsx(Pagination.PageSize, {}),
1200
+ /* @__PURE__ */ jsx(Pagination.Links, {})
1201
+ ]
1202
+ }
1203
+ )
1191
1204
  ] }) });
1192
1205
  };
1193
1206
  const ReleaseDetailsPage = () => {
1194
1207
  const { formatMessage } = useIntl();
1195
1208
  const { releaseId } = useParams();
1196
- const toggleNotification = useNotification();
1209
+ const { toggleNotification } = useNotification();
1197
1210
  const { formatAPIError } = useAPIErrorHandler();
1198
- const { replace } = useHistory();
1211
+ const navigate = useNavigate();
1199
1212
  const [releaseModalShown, setReleaseModalShown] = React.useState(false);
1200
1213
  const [showWarningSubmit, setWarningSubmit] = React.useState(false);
1201
1214
  const {
1202
1215
  isLoading: isLoadingDetails,
1203
1216
  data,
1204
1217
  isSuccess: isSuccessDetails
1205
- } = useGetReleaseQuery({ id: releaseId });
1218
+ } = useGetReleaseQuery(
1219
+ { id: releaseId },
1220
+ {
1221
+ skip: !releaseId
1222
+ }
1223
+ );
1206
1224
  const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();
1207
- const [deleteRelease, { isLoading: isDeletingRelease }] = useDeleteReleaseMutation();
1225
+ const [deleteRelease] = useDeleteReleaseMutation();
1208
1226
  const toggleEditReleaseModal = () => {
1209
1227
  setReleaseModalShown((prev) => !prev);
1210
1228
  };
@@ -1215,15 +1233,18 @@ const ReleaseDetailsPage = () => {
1215
1233
  {
1216
1234
  toggleEditReleaseModal,
1217
1235
  toggleWarningSubmit,
1218
- children: /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) })
1236
+ children: /* @__PURE__ */ jsx(Page.Loading, {})
1219
1237
  }
1220
1238
  );
1221
1239
  }
1240
+ if (!releaseId) {
1241
+ return /* @__PURE__ */ jsx(Navigate, { to: ".." });
1242
+ }
1222
1243
  const releaseData = isSuccessDetails && data?.data || null;
1223
1244
  const title = releaseData?.name || "";
1224
1245
  const timezone = releaseData?.timezone ?? null;
1225
1246
  const scheduledAt = releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;
1226
- const date = scheduledAt ? new Date(format(scheduledAt, "yyyy-MM-dd")) : null;
1247
+ const date = scheduledAt ? format(scheduledAt, "yyyy-MM-dd") : null;
1227
1248
  const time = scheduledAt ? format(scheduledAt, "HH:mm") : "";
1228
1249
  const handleEditRelease = async (values) => {
1229
1250
  const response = await updateRelease({
@@ -1240,33 +1261,33 @@ const ReleaseDetailsPage = () => {
1240
1261
  defaultMessage: "Release updated."
1241
1262
  })
1242
1263
  });
1264
+ toggleEditReleaseModal();
1243
1265
  } else if (isAxiosError(response.error)) {
1244
1266
  toggleNotification({
1245
- type: "warning",
1267
+ type: "danger",
1246
1268
  message: formatAPIError(response.error)
1247
1269
  });
1248
1270
  } else {
1249
1271
  toggleNotification({
1250
- type: "warning",
1272
+ type: "danger",
1251
1273
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1252
1274
  });
1253
1275
  }
1254
- toggleEditReleaseModal();
1255
1276
  };
1256
1277
  const handleDeleteRelease = async () => {
1257
1278
  const response = await deleteRelease({
1258
1279
  id: releaseId
1259
1280
  });
1260
1281
  if ("data" in response) {
1261
- replace("/plugins/content-releases");
1282
+ navigate("..");
1262
1283
  } else if (isAxiosError(response.error)) {
1263
1284
  toggleNotification({
1264
- type: "warning",
1285
+ type: "danger",
1265
1286
  message: formatAPIError(response.error)
1266
1287
  });
1267
1288
  } else {
1268
1289
  toggleNotification({
1269
- type: "warning",
1290
+ type: "danger",
1270
1291
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1271
1292
  });
1272
1293
  }
@@ -1277,7 +1298,7 @@ const ReleaseDetailsPage = () => {
1277
1298
  toggleEditReleaseModal,
1278
1299
  toggleWarningSubmit,
1279
1300
  children: [
1280
- /* @__PURE__ */ jsx(ReleaseDetailsBody, {}),
1301
+ /* @__PURE__ */ jsx(ReleaseDetailsBody, { releaseId }),
1281
1302
  releaseModalShown && /* @__PURE__ */ jsx(
1282
1303
  ReleaseModal,
1283
1304
  {
@@ -1297,14 +1318,13 @@ const ReleaseDetailsPage = () => {
1297
1318
  /* @__PURE__ */ jsx(
1298
1319
  ConfirmDialog,
1299
1320
  {
1300
- bodyText: {
1321
+ isOpen: showWarningSubmit,
1322
+ onClose: toggleWarningSubmit,
1323
+ onConfirm: handleDeleteRelease,
1324
+ children: formatMessage({
1301
1325
  id: "content-releases.dialog.confirmation-message",
1302
1326
  defaultMessage: "Are you sure you want to delete this release?"
1303
- },
1304
- isOpen: showWarningSubmit,
1305
- isConfirmButtonLoading: isDeletingRelease,
1306
- onToggleDialog: toggleWarningSubmit,
1307
- onConfirm: handleDeleteRelease
1327
+ })
1308
1328
  }
1309
1329
  )
1310
1330
  ]
@@ -1312,12 +1332,12 @@ const ReleaseDetailsPage = () => {
1312
1332
  );
1313
1333
  };
1314
1334
  const App = () => {
1315
- return /* @__PURE__ */ jsx(CheckPagePermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(Switch, { children: [
1316
- /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}`, component: ReleasesPage }),
1317
- /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}/:releaseId`, component: ReleaseDetailsPage })
1335
+ return /* @__PURE__ */ jsx(Page.Protect, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(Routes, { children: [
1336
+ /* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(ReleasesPage, {}) }),
1337
+ /* @__PURE__ */ jsx(Route, { path: ":releaseId", element: /* @__PURE__ */ jsx(ReleaseDetailsPage, {}) })
1318
1338
  ] }) });
1319
1339
  };
1320
1340
  export {
1321
1341
  App
1322
1342
  };
1323
- //# sourceMappingURL=App-bpzO2Ljh.mjs.map
1343
+ //# sourceMappingURL=App-O0ZO-S35.mjs.map