@strapi/content-releases 0.0.0-next.f8af92b375dc730ba47ed2117f25df893aae696c → 0.0.0-next.fd9757603c653ca239c45d6e28ab536d2dae0b39

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-OK4Xac-O.js → App-dLXY5ei3.js} +677 -639
  3. package/dist/_chunks/App-dLXY5ei3.js.map +1 -0
  4. package/dist/_chunks/{App-xAkiD42p.mjs → App-jrh58sXY.mjs} +690 -652
  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-r0otWaln.js → en-HrREghh3.js} +14 -5
  11. package/dist/_chunks/en-HrREghh3.js.map +1 -0
  12. package/dist/_chunks/{en-veqvqeEr.mjs → en-ltT1TlKQ.mjs} +14 -5
  13. package/dist/_chunks/en-ltT1TlKQ.mjs.map +1 -0
  14. package/dist/_chunks/{index-JvA2_26n.js → index-CVO0Rqdm.js} +343 -22
  15. package/dist/_chunks/index-CVO0Rqdm.js.map +1 -0
  16. package/dist/_chunks/{index-exoiSU3V.mjs → index-PiOGBETy.mjs} +358 -37
  17. package/dist/_chunks/index-PiOGBETy.mjs.map +1 -0
  18. package/dist/admin/index.js +1 -1
  19. package/dist/admin/index.mjs +1 -1
  20. package/dist/server/index.js +629 -176
  21. package/dist/server/index.js.map +1 -1
  22. package/dist/server/index.mjs +628 -176
  23. package/dist/server/index.mjs.map +1 -1
  24. package/package.json +15 -14
  25. package/dist/_chunks/App-OK4Xac-O.js.map +0 -1
  26. package/dist/_chunks/App-xAkiD42p.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-r0otWaln.js.map +0 -1
  30. package/dist/_chunks/en-veqvqeEr.mjs.map +0 -1
  31. package/dist/_chunks/index-JvA2_26n.js.map +0 -1
  32. package/dist/_chunks/index-exoiSU3V.mjs.map +0 -1
@@ -1,17 +1,17 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { useNotification, useAPIErrorHandler, LoadingIndicatorPage, ConfirmDialog, useRBAC, useTracking, RelativeTime, CheckPermissions, useQueryParams, AnErrorOccurred, NoContent, Table, PageSizeURLQuery, PaginationURLQuery, CheckPagePermissions } from "@strapi/helper-plugin";
3
- import { useLocation, useParams, useHistory, Redirect, Link as Link$1, Switch, Route } from "react-router-dom";
4
- import { g as getTimezoneOffset, p as pluginId, u as useGetReleaseQuery, a as useUpdateReleaseMutation, b as useDeleteReleaseMutation, c as usePublishReleaseMutation, P as PERMISSIONS, d as useTypedDispatch, e as useGetReleaseActionsQuery, f as useUpdateReleaseActionMutation, R as ReleaseActionOptions, h as ReleaseActionMenu, i as isAxiosError, r as releaseApi, j as useGetReleasesQuery, k as useCreateReleaseMutation } from "./index-exoiSU3V.mjs";
2
+ import { RelativeTime as RelativeTime$1, useNotification, useAPIErrorHandler, useQueryParams, useTracking, LoadingIndicatorPage, CheckPermissions, PageSizeURLQuery, PaginationURLQuery, AnErrorOccurred, ConfirmDialog, useRBAC, useStrapiApp, 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-PiOGBETy.mjs";
5
5
  import * as React from "react";
6
- import { unstable_useDocument, useLicenseLimits } from "@strapi/admin/strapi-admin";
7
- import { ModalLayout, ModalHeader, Typography, ModalBody, Flex, TextInput, Box, Checkbox, DatePicker, TimePicker, ModalFooter, Button, Combobox, ComboboxOption, ContentLayout, Main, HeaderLayout, Link, IconButton, SingleSelect, SingleSelectOption, Badge, Tr, Td, Icon, Tooltip, Alert, TabGroup, Tabs, Tab, Divider, TabPanels, TabPanel, EmptyStateLayout, Grid, GridItem } from "@strapi/design-system";
8
- import { Menu, LinkButton, Link as Link$2 } from "@strapi/design-system/v2";
9
- import { Pencil, Trash, ArrowLeft, More, CrossCircle, CheckCircle, Plus, EmptyDocuments } from "@strapi/icons";
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";
10
10
  import format from "date-fns/format";
11
- import { zonedTimeToUtc, utcToZonedTime } from "date-fns-tz";
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 { formatISO } from "date-fns";
15
15
  import { Formik, Form, useFormikContext } from "formik";
16
16
  import * as yup from "yup";
17
17
  import "@reduxjs/toolkit/query";
@@ -47,7 +47,6 @@ const ReleaseModal = ({
47
47
  const { formatMessage } = useIntl();
48
48
  const { pathname } = useLocation();
49
49
  const isCreatingRelease = pathname === `/plugins/${pluginId}`;
50
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
51
50
  const { timezoneList, systemTimezone = { value: "UTC+00:00-Africa/Abidjan " } } = getTimezones(
52
51
  initialValues.scheduledAt ? new Date(initialValues.scheduledAt) : /* @__PURE__ */ new Date()
53
52
  );
@@ -55,13 +54,12 @@ const ReleaseModal = ({
55
54
  const { date, time, timezone } = values;
56
55
  if (!date || !time || !timezone)
57
56
  return null;
58
- const formattedDate = parse(time, "HH:mm", new Date(date));
59
- const timezoneWithoutOffset = timezone.split("_")[1];
60
- return zonedTimeToUtc(formattedDate, timezoneWithoutOffset);
57
+ const timezoneWithoutOffset = timezone.split("&")[1];
58
+ return zonedTimeToUtc(`${date} ${time}`, timezoneWithoutOffset);
61
59
  };
62
60
  const getTimezoneWithOffset = () => {
63
61
  const currentTimezone = timezoneList.find(
64
- (timezone) => timezone.value.split("_")[1] === initialValues.timezone
62
+ (timezone) => timezone.value.split("&")[1] === initialValues.timezone
65
63
  );
66
64
  return currentTimezone?.value || systemTimezone.value;
67
65
  };
@@ -79,7 +77,7 @@ const ReleaseModal = ({
79
77
  onSubmit: (values) => {
80
78
  handleSubmit({
81
79
  ...values,
82
- timezone: values.timezone ? values.timezone.split("_")[1] : null,
80
+ timezone: values.timezone ? values.timezone.split("&")[1] : null,
83
81
  scheduledAt: values.isScheduled ? getScheduledTimestamp(values) : null
84
82
  });
85
83
  },
@@ -105,92 +103,88 @@ const ReleaseModal = ({
105
103
  required: true
106
104
  }
107
105
  ),
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) {
106
+ /* @__PURE__ */ jsx(Box, { width: "max-content", children: /* @__PURE__ */ jsx(
107
+ Checkbox,
108
+ {
109
+ name: "isScheduled",
110
+ value: values.isScheduled,
111
+ onChange: (event) => {
112
+ setFieldValue("isScheduled", event.target.checked);
113
+ if (!event.target.checked) {
114
+ setFieldValue("date", null);
115
+ setFieldValue("time", "");
116
+ setFieldValue("timezone", null);
117
+ } else {
118
+ setFieldValue("date", initialValues.date);
119
+ setFieldValue("time", initialValues.time);
120
+ setFieldValue("timezone", initialValues.timezone ?? systemTimezone?.value);
121
+ }
122
+ },
123
+ children: /* @__PURE__ */ jsx(
124
+ Typography,
125
+ {
126
+ textColor: values.isScheduled ? "primary600" : "neutral800",
127
+ fontWeight: values.isScheduled ? "semiBold" : "regular",
128
+ children: formatMessage({
129
+ id: "modal.form.input.label.schedule-release",
130
+ defaultMessage: "Schedule release"
131
+ })
132
+ }
133
+ )
134
+ }
135
+ ) }),
136
+ values.isScheduled && /* @__PURE__ */ jsxs(Fragment, { children: [
137
+ /* @__PURE__ */ jsxs(Flex, { gap: 4, alignItems: "start", children: [
138
+ /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
139
+ DatePicker,
140
+ {
141
+ label: formatMessage({
142
+ id: "content-releases.modal.form.input.label.date",
143
+ defaultMessage: "Date"
144
+ }),
145
+ name: "date",
146
+ error: errors.date,
147
+ onChange: (date) => {
148
+ const isoFormatDate = date ? formatISO(date, { representation: "date" }) : null;
149
+ setFieldValue("date", isoFormatDate);
150
+ },
151
+ clearLabel: formatMessage({
152
+ id: "content-releases.modal.form.input.clearLabel",
153
+ defaultMessage: "Clear"
154
+ }),
155
+ onClear: () => {
117
156
  setFieldValue("date", null);
157
+ },
158
+ selectedDate: values.date || void 0,
159
+ required: true,
160
+ minDate: utcToZonedTime(/* @__PURE__ */ new Date(), values.timezone.split("&")[1])
161
+ }
162
+ ) }),
163
+ /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
164
+ TimePicker,
165
+ {
166
+ label: formatMessage({
167
+ id: "content-releases.modal.form.input.label.time",
168
+ defaultMessage: "Time"
169
+ }),
170
+ name: "time",
171
+ error: errors.time,
172
+ onChange: (time) => {
173
+ setFieldValue("time", time);
174
+ },
175
+ clearLabel: formatMessage({
176
+ id: "content-releases.modal.form.input.clearLabel",
177
+ defaultMessage: "Clear"
178
+ }),
179
+ onClear: () => {
118
180
  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
- }
167
- ) }),
168
- /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
169
- TimePicker,
170
- {
171
- label: formatMessage({
172
- id: "content-releases.modal.form.input.label.time",
173
- defaultMessage: "Time"
174
- }),
175
- name: "time",
176
- error: errors.time,
177
- onChange: (time) => {
178
- setFieldValue("time", time);
179
- },
180
- clearLabel: formatMessage({
181
- id: "content-releases.modal.form.input.clearLabel",
182
- defaultMessage: "Clear"
183
- }),
184
- onClear: () => {
185
- setFieldValue("time", "");
186
- },
187
- value: values.time || void 0,
188
- required: true
189
- }
190
- ) })
191
- ] }),
192
- /* @__PURE__ */ jsx(TimezoneComponent, { timezoneOptions: timezoneList })
193
- ] })
181
+ },
182
+ value: values.time || void 0,
183
+ required: true
184
+ }
185
+ ) })
186
+ ] }),
187
+ /* @__PURE__ */ jsx(TimezoneComponent, { timezoneOptions: timezoneList })
194
188
  ] })
195
189
  ] }) }),
196
190
  /* @__PURE__ */ jsx(
@@ -214,10 +208,10 @@ const ReleaseModal = ({
214
208
  const getTimezones = (selectedDate) => {
215
209
  const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
216
210
  const utcOffset = getTimezoneOffset(timezone, selectedDate);
217
- return { offset: utcOffset, value: `${utcOffset}_${timezone}` };
211
+ return { offset: utcOffset, value: `${utcOffset}&${timezone}` };
218
212
  });
219
213
  const systemTimezone = timezoneList.find(
220
- (timezone) => timezone.value.split("_")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
214
+ (timezone) => timezone.value.split("&")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
221
215
  );
222
216
  return { timezoneList, systemTimezone };
223
217
  };
@@ -229,7 +223,7 @@ const TimezoneComponent = ({ timezoneOptions }) => {
229
223
  if (values.date) {
230
224
  const { timezoneList: timezoneList2 } = getTimezones(new Date(values.date));
231
225
  setTimezoneList(timezoneList2);
232
- const updatedTimezone = values.timezone && timezoneList2.find((tz) => tz.value.split("_")[1] === values.timezone.split("_")[1]);
226
+ const updatedTimezone = values.timezone && timezoneList2.find((tz) => tz.value.split("&")[1] === values.timezone.split("&")[1]);
233
227
  if (updatedTimezone) {
234
228
  setFieldValue("timezone", updatedTimezone.value);
235
229
  }
@@ -242,137 +236,201 @@ const TimezoneComponent = ({ timezoneOptions }) => {
242
236
  id: "content-releases.modal.form.input.label.timezone",
243
237
  defaultMessage: "Timezone"
244
238
  }),
239
+ autocomplete: { type: "list", filter: "contains" },
245
240
  name: "timezone",
246
241
  value: values.timezone || void 0,
247
- textValue: values.timezone ? values.timezone.replace("_", " ") : void 0,
242
+ textValue: values.timezone ? values.timezone.replace(/&/, " ") : void 0,
248
243
  onChange: (timezone) => {
249
244
  setFieldValue("timezone", timezone);
250
245
  },
246
+ onTextValueChange: (timezone) => {
247
+ setFieldValue("timezone", timezone);
248
+ },
251
249
  onClear: () => {
252
250
  setFieldValue("timezone", "");
253
251
  },
254
252
  error: errors.timezone,
255
253
  required: true,
256
- children: timezoneList.map((timezone) => /* @__PURE__ */ jsx(ComboboxOption, { value: timezone.value, children: timezone.value.replace("_", " ") }, timezone.value))
254
+ children: timezoneList.map((timezone) => /* @__PURE__ */ jsx(ComboboxOption, { value: timezone.value, children: timezone.value.replace(/&/, " ") }, timezone.value))
257
255
  }
258
256
  );
259
257
  };
260
- const ReleaseInfoWrapper = styled(Flex)`
261
- align-self: stretch;
262
- border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
263
- border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
264
- border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
265
- `;
266
- const StyledMenuItem = styled(Menu.Item)`
267
- svg path {
268
- fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
269
- }
270
- span {
271
- color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
272
- }
258
+ const LinkCard = styled(Link)`
259
+ display: block;
273
260
  `;
274
- const PencilIcon = styled(Pencil)`
275
- width: ${({ theme }) => theme.spaces[3]};
276
- height: ${({ theme }) => theme.spaces[3]};
277
- path {
278
- fill: ${({ theme }) => theme.colors.neutral600};
261
+ const RelativeTime = styled(RelativeTime$1)`
262
+ display: inline-block;
263
+ &::first-letter {
264
+ text-transform: uppercase;
279
265
  }
280
266
  `;
281
- const TrashIcon = styled(Trash)`
282
- width: ${({ theme }) => theme.spaces[3]};
283
- height: ${({ theme }) => theme.spaces[3]};
284
- path {
285
- fill: ${({ theme }) => theme.colors.danger600};
267
+ const getBadgeProps = (status) => {
268
+ let color;
269
+ switch (status) {
270
+ case "ready":
271
+ color = "success";
272
+ break;
273
+ case "blocked":
274
+ color = "warning";
275
+ break;
276
+ case "failed":
277
+ color = "danger";
278
+ break;
279
+ case "done":
280
+ color = "primary";
281
+ break;
282
+ case "empty":
283
+ default:
284
+ color = "neutral";
286
285
  }
287
- `;
288
- const TypographyMaxWidth = styled(Typography)`
289
- max-width: 300px;
290
- `;
291
- const EntryValidationText = ({ action, schema, components, entry }) => {
286
+ return {
287
+ textColor: `${color}600`,
288
+ backgroundColor: `${color}100`,
289
+ borderColor: `${color}200`
290
+ };
291
+ };
292
+ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
292
293
  const { formatMessage } = useIntl();
293
- const { validate } = unstable_useDocument();
294
- const { errors } = validate(entry, {
295
- contentType: schema,
296
- components,
297
- isCreatingEntry: false
298
- });
299
- if (Object.keys(errors).length > 0) {
300
- const validationErrorsMessages = Object.entries(errors).map(
301
- ([key, value]) => formatMessage(
302
- { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
303
- { field: key }
304
- )
305
- ).join(" ");
306
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
307
- /* @__PURE__ */ jsx(Icon, { color: "danger600", as: CrossCircle }),
308
- /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
309
- ] });
294
+ if (isError) {
295
+ return /* @__PURE__ */ jsx(AnErrorOccurred, {});
310
296
  }
311
- if (action == "publish") {
312
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
313
- /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
314
- entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
315
- id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
316
- defaultMessage: "Already published"
317
- }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
318
- id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
319
- defaultMessage: "Ready to publish"
320
- }) })
321
- ] });
297
+ if (releases?.length === 0) {
298
+ return /* @__PURE__ */ jsx(
299
+ EmptyStateLayout,
300
+ {
301
+ content: formatMessage(
302
+ {
303
+ id: "content-releases.page.Releases.tab.emptyEntries",
304
+ defaultMessage: "No releases"
305
+ },
306
+ {
307
+ target: sectionTitle
308
+ }
309
+ ),
310
+ icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem" })
311
+ }
312
+ );
322
313
  }
323
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
324
- /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
325
- !entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
326
- id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
327
- defaultMessage: "Already unpublished"
328
- }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
329
- id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish",
330
- defaultMessage: "Ready to unpublish"
331
- }) })
332
- ] });
314
+ 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(
315
+ Flex,
316
+ {
317
+ direction: "column",
318
+ justifyContent: "space-between",
319
+ padding: 4,
320
+ hasRadius: true,
321
+ background: "neutral0",
322
+ shadow: "tableShadow",
323
+ height: "100%",
324
+ width: "100%",
325
+ alignItems: "start",
326
+ gap: 4,
327
+ children: [
328
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "start", gap: 1, children: [
329
+ /* @__PURE__ */ jsx(Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
330
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: scheduledAt ? /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
331
+ id: "content-releases.pages.Releases.not-scheduled",
332
+ defaultMessage: "Not scheduled"
333
+ }) })
334
+ ] }),
335
+ /* @__PURE__ */ jsx(Badge, { ...getBadgeProps(status), children: status })
336
+ ]
337
+ }
338
+ ) }) }, id)) });
333
339
  };
334
- const ReleaseDetailsLayout = ({
335
- toggleEditReleaseModal,
336
- toggleWarningSubmit,
337
- children
338
- }) => {
339
- const { formatMessage, formatDate, formatTime } = useIntl();
340
- const { releaseId } = useParams();
341
- const {
342
- data,
343
- isLoading: isLoadingDetails,
344
- isError,
345
- error
346
- } = useGetReleaseQuery({ id: releaseId });
347
- const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();
340
+ const StyledAlert = styled(Alert)`
341
+ button {
342
+ display: none;
343
+ }
344
+ p + div {
345
+ margin-left: auto;
346
+ }
347
+ `;
348
+ const INITIAL_FORM_VALUES = {
349
+ name: "",
350
+ date: null,
351
+ time: "",
352
+ isScheduled: true,
353
+ scheduledAt: null,
354
+ timezone: null
355
+ };
356
+ const ReleasesPage = () => {
357
+ const tabRef = React.useRef(null);
358
+ const location = useLocation();
359
+ const [releaseModalShown, setReleaseModalShown] = React.useState(false);
348
360
  const toggleNotification = useNotification();
361
+ const { formatMessage } = useIntl();
362
+ const { push, replace } = useHistory();
349
363
  const { formatAPIError } = useAPIErrorHandler();
350
- const {
351
- allowedActions: { canUpdate, canDelete }
352
- } = useRBAC(PERMISSIONS);
353
- const dispatch = useTypedDispatch();
364
+ const [{ query }, setQuery] = useQueryParams();
365
+ const response = useGetReleasesQuery(query);
366
+ const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();
367
+ const { getFeature } = useLicenseLimits();
368
+ const { maximumReleases = 3 } = getFeature("cms-content-releases");
354
369
  const { trackUsage } = useTracking();
355
- const release = data?.data;
356
- const handlePublishRelease = async () => {
357
- const response = await publishRelease({ id: releaseId });
358
- if ("data" in response) {
370
+ const { isLoading, isSuccess, isError } = response;
371
+ const activeTab = response?.currentData?.meta?.activeTab || "pending";
372
+ const activeTabIndex = ["pending", "done"].indexOf(activeTab);
373
+ React.useEffect(() => {
374
+ if (location?.state?.errors) {
359
375
  toggleNotification({
360
- type: "success",
376
+ type: "warning",
377
+ title: formatMessage({
378
+ id: "content-releases.pages.Releases.notification.error.title",
379
+ defaultMessage: "Your request could not be processed."
380
+ }),
361
381
  message: formatMessage({
362
- id: "content-releases.pages.ReleaseDetails.publish-notification-success",
363
- defaultMessage: "Release was published successfully."
382
+ id: "content-releases.pages.Releases.notification.error.message",
383
+ defaultMessage: "Please try again or open another release."
364
384
  })
365
385
  });
366
- const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
367
- trackUsage("didPublishRelease", {
368
- totalEntries: totalEntries2,
369
- totalPublishedEntries,
370
- totalUnpublishedEntries
386
+ replace({ state: null });
387
+ }
388
+ }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
389
+ React.useEffect(() => {
390
+ if (tabRef.current) {
391
+ tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
392
+ }
393
+ }, [activeTabIndex]);
394
+ const toggleAddReleaseModal = () => {
395
+ setReleaseModalShown((prev) => !prev);
396
+ };
397
+ if (isLoading) {
398
+ return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
399
+ }
400
+ const totalPendingReleases = isSuccess && response.currentData?.meta?.pendingReleasesCount || 0;
401
+ const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
402
+ const handleTabChange = (index) => {
403
+ setQuery({
404
+ ...query,
405
+ page: 1,
406
+ pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
407
+ filters: {
408
+ releasedAt: {
409
+ $notNull: index === 0 ? false : true
410
+ }
411
+ }
412
+ });
413
+ };
414
+ const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
415
+ const response2 = await createRelease({
416
+ name,
417
+ scheduledAt,
418
+ timezone
419
+ });
420
+ if ("data" in response2) {
421
+ toggleNotification({
422
+ type: "success",
423
+ message: formatMessage({
424
+ id: "content-releases.modal.release-created-notification-success",
425
+ defaultMessage: "Release created."
426
+ })
371
427
  });
372
- } else if (isAxiosError(response.error)) {
428
+ trackUsage("didCreateRelease");
429
+ push(`/plugins/content-releases/${response2.data.data.id}`);
430
+ } else if (isAxiosError(response2.error)) {
373
431
  toggleNotification({
374
432
  type: "warning",
375
- message: formatAPIError(response.error)
433
+ message: formatAPIError(response2.error)
376
434
  });
377
435
  } else {
378
436
  toggleNotification({
@@ -381,20 +439,284 @@ const ReleaseDetailsLayout = ({
381
439
  });
382
440
  }
383
441
  };
384
- const handleRefresh = () => {
385
- dispatch(releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
386
- };
387
- const getCreatedByUser = () => {
388
- if (!release?.createdBy) {
389
- return null;
390
- }
391
- if (release.createdBy.username) {
392
- return release.createdBy.username;
393
- }
394
- if (release.createdBy.firstname) {
395
- return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
396
- }
397
- return release.createdBy.email;
442
+ return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoading, children: [
443
+ /* @__PURE__ */ jsx(
444
+ HeaderLayout,
445
+ {
446
+ title: formatMessage({
447
+ id: "content-releases.pages.Releases.title",
448
+ defaultMessage: "Releases"
449
+ }),
450
+ subtitle: formatMessage({
451
+ id: "content-releases.pages.Releases.header-subtitle",
452
+ defaultMessage: "Create and manage content updates"
453
+ }),
454
+ primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(
455
+ Button,
456
+ {
457
+ startIcon: /* @__PURE__ */ jsx(Plus, {}),
458
+ onClick: toggleAddReleaseModal,
459
+ disabled: hasReachedMaximumPendingReleases,
460
+ children: formatMessage({
461
+ id: "content-releases.header.actions.add-release",
462
+ defaultMessage: "New release"
463
+ })
464
+ }
465
+ ) })
466
+ }
467
+ ),
468
+ /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
469
+ hasReachedMaximumPendingReleases && /* @__PURE__ */ jsx(
470
+ StyledAlert,
471
+ {
472
+ marginBottom: 6,
473
+ action: /* @__PURE__ */ jsx(Link, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
474
+ id: "content-releases.pages.Releases.max-limit-reached.action",
475
+ defaultMessage: "Explore plans"
476
+ }) }),
477
+ title: formatMessage(
478
+ {
479
+ id: "content-releases.pages.Releases.max-limit-reached.title",
480
+ defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
481
+ },
482
+ { number: maximumReleases }
483
+ ),
484
+ onClose: () => {
485
+ },
486
+ closeLabel: "",
487
+ children: formatMessage({
488
+ id: "content-releases.pages.Releases.max-limit-reached.message",
489
+ defaultMessage: "Upgrade to manage an unlimited number of releases."
490
+ })
491
+ }
492
+ ),
493
+ /* @__PURE__ */ jsxs(
494
+ TabGroup,
495
+ {
496
+ label: formatMessage({
497
+ id: "content-releases.pages.Releases.tab-group.label",
498
+ defaultMessage: "Releases list"
499
+ }),
500
+ variant: "simple",
501
+ initialSelectedTabIndex: activeTabIndex,
502
+ onTabChange: handleTabChange,
503
+ ref: tabRef,
504
+ children: [
505
+ /* @__PURE__ */ jsxs(Box, { paddingBottom: 8, children: [
506
+ /* @__PURE__ */ jsxs(Tabs, { children: [
507
+ /* @__PURE__ */ jsx(Tab, { children: formatMessage(
508
+ {
509
+ id: "content-releases.pages.Releases.tab.pending",
510
+ defaultMessage: "Pending ({count})"
511
+ },
512
+ {
513
+ count: totalPendingReleases
514
+ }
515
+ ) }),
516
+ /* @__PURE__ */ jsx(Tab, { children: formatMessage({
517
+ id: "content-releases.pages.Releases.tab.done",
518
+ defaultMessage: "Done"
519
+ }) })
520
+ ] }),
521
+ /* @__PURE__ */ jsx(Divider, {})
522
+ ] }),
523
+ /* @__PURE__ */ jsxs(TabPanels, { children: [
524
+ /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
525
+ ReleasesGrid,
526
+ {
527
+ sectionTitle: "pending",
528
+ releases: response?.currentData?.data,
529
+ isError
530
+ }
531
+ ) }),
532
+ /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
533
+ ReleasesGrid,
534
+ {
535
+ sectionTitle: "done",
536
+ releases: response?.currentData?.data,
537
+ isError
538
+ }
539
+ ) })
540
+ ] })
541
+ ]
542
+ }
543
+ ),
544
+ response.currentData?.meta?.pagination?.total ? /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
545
+ /* @__PURE__ */ jsx(
546
+ PageSizeURLQuery,
547
+ {
548
+ options: ["8", "16", "32", "64"],
549
+ defaultValue: response?.currentData?.meta?.pagination?.pageSize.toString()
550
+ }
551
+ ),
552
+ /* @__PURE__ */ jsx(
553
+ PaginationURLQuery,
554
+ {
555
+ pagination: {
556
+ pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
557
+ }
558
+ }
559
+ )
560
+ ] }) : null
561
+ ] }) }),
562
+ releaseModalShown && /* @__PURE__ */ jsx(
563
+ ReleaseModal,
564
+ {
565
+ handleClose: toggleAddReleaseModal,
566
+ handleSubmit: handleAddRelease,
567
+ isLoading: isSubmittingForm,
568
+ initialValues: INITIAL_FORM_VALUES
569
+ }
570
+ )
571
+ ] });
572
+ };
573
+ const ReleaseInfoWrapper = styled(Flex)`
574
+ align-self: stretch;
575
+ border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
576
+ border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
577
+ border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
578
+ `;
579
+ const StyledMenuItem = styled(Menu.Item)`
580
+ svg path {
581
+ fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
582
+ }
583
+ span {
584
+ color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
585
+ }
586
+
587
+ &:hover {
588
+ background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
589
+ }
590
+ `;
591
+ const PencilIcon = styled(Pencil)`
592
+ width: ${({ theme }) => theme.spaces[3]};
593
+ height: ${({ theme }) => theme.spaces[3]};
594
+ path {
595
+ fill: ${({ theme }) => theme.colors.neutral600};
596
+ }
597
+ `;
598
+ const TrashIcon = styled(Trash)`
599
+ width: ${({ theme }) => theme.spaces[3]};
600
+ height: ${({ theme }) => theme.spaces[3]};
601
+ path {
602
+ fill: ${({ theme }) => theme.colors.danger600};
603
+ }
604
+ `;
605
+ const TypographyMaxWidth = styled(Typography)`
606
+ max-width: 300px;
607
+ `;
608
+ const EntryValidationText = ({ action, schema, components, entry }) => {
609
+ const { formatMessage } = useIntl();
610
+ const { validate } = unstable_useDocument();
611
+ const { errors } = validate(entry, {
612
+ contentType: schema,
613
+ components,
614
+ isCreatingEntry: false
615
+ });
616
+ if (Object.keys(errors).length > 0) {
617
+ const validationErrorsMessages = Object.entries(errors).map(
618
+ ([key, value]) => formatMessage(
619
+ { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
620
+ { field: key }
621
+ )
622
+ ).join(" ");
623
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
624
+ /* @__PURE__ */ jsx(Icon, { color: "danger600", as: CrossCircle }),
625
+ /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
626
+ ] });
627
+ }
628
+ if (action == "publish") {
629
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
630
+ /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
631
+ entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
632
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
633
+ defaultMessage: "Already published"
634
+ }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
635
+ id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
636
+ defaultMessage: "Ready to publish"
637
+ }) })
638
+ ] });
639
+ }
640
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
641
+ /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
642
+ !entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
643
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
644
+ defaultMessage: "Already unpublished"
645
+ }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
646
+ id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish",
647
+ defaultMessage: "Ready to unpublish"
648
+ }) })
649
+ ] });
650
+ };
651
+ const ReleaseDetailsLayout = ({
652
+ toggleEditReleaseModal,
653
+ toggleWarningSubmit,
654
+ children
655
+ }) => {
656
+ const { formatMessage, formatDate, formatTime } = useIntl();
657
+ const { releaseId } = useParams();
658
+ const {
659
+ data,
660
+ isLoading: isLoadingDetails,
661
+ isError,
662
+ error
663
+ } = useGetReleaseQuery({ id: releaseId });
664
+ const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();
665
+ const toggleNotification = useNotification();
666
+ const { formatAPIError } = useAPIErrorHandler();
667
+ const {
668
+ allowedActions: { canUpdate, canDelete }
669
+ } = useRBAC(PERMISSIONS);
670
+ const dispatch = useTypedDispatch();
671
+ const { trackUsage } = useTracking();
672
+ const release = data?.data;
673
+ const handlePublishRelease = async () => {
674
+ const response = await publishRelease({ id: releaseId });
675
+ if ("data" in response) {
676
+ toggleNotification({
677
+ type: "success",
678
+ message: formatMessage({
679
+ id: "content-releases.pages.ReleaseDetails.publish-notification-success",
680
+ defaultMessage: "Release was published successfully."
681
+ })
682
+ });
683
+ const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
684
+ trackUsage("didPublishRelease", {
685
+ totalEntries: totalEntries2,
686
+ totalPublishedEntries,
687
+ totalUnpublishedEntries
688
+ });
689
+ } else if (isAxiosError(response.error)) {
690
+ toggleNotification({
691
+ type: "warning",
692
+ message: formatAPIError(response.error)
693
+ });
694
+ } else {
695
+ toggleNotification({
696
+ type: "warning",
697
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
698
+ });
699
+ }
700
+ };
701
+ const handleRefresh = () => {
702
+ dispatch(
703
+ releaseApi.util.invalidateTags([
704
+ { type: "ReleaseAction", id: "LIST" },
705
+ { type: "Release", id: releaseId }
706
+ ])
707
+ );
708
+ };
709
+ const getCreatedByUser = () => {
710
+ if (!release?.createdBy) {
711
+ return null;
712
+ }
713
+ if (release.createdBy.username) {
714
+ return release.createdBy.username;
715
+ }
716
+ if (release.createdBy.firstname) {
717
+ return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
718
+ }
719
+ return release.createdBy.email;
398
720
  };
399
721
  if (isLoadingDetails) {
400
722
  return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
@@ -418,7 +740,6 @@ const ReleaseDetailsLayout = ({
418
740
  }
419
741
  const totalEntries = release.actions.meta.count || 0;
420
742
  const hasCreatedByUser = Boolean(getCreatedByUser());
421
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
422
743
  const isScheduled = release.scheduledAt && release.timezone;
423
744
  const numberOfEntriesText = formatMessage(
424
745
  {
@@ -452,8 +773,11 @@ const ReleaseDetailsLayout = ({
452
773
  HeaderLayout,
453
774
  {
454
775
  title: release.name,
455
- subtitle: numberOfEntriesText + (IsSchedulingEnabled && isScheduled ? ` - ${scheduledText}` : ""),
456
- navigationAction: /* @__PURE__ */ jsx(Link, { startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
776
+ subtitle: /* @__PURE__ */ jsxs(Flex, { gap: 2, lineHeight: 6, children: [
777
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", variant: "epsilon", children: numberOfEntriesText + (isScheduled ? ` - ${scheduledText}` : "") }),
778
+ /* @__PURE__ */ jsx(Badge, { ...getBadgeProps(release.status), children: release.status })
779
+ ] }),
780
+ navigationAction: /* @__PURE__ */ jsx(Link$1, { startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
457
781
  id: "global.back",
458
782
  defaultMessage: "Back"
459
783
  }) }),
@@ -483,42 +807,28 @@ const ReleaseDetailsLayout = ({
483
807
  padding: 1,
484
808
  width: "100%",
485
809
  children: [
486
- /* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxs(
487
- Flex,
488
- {
489
- paddingTop: 2,
490
- paddingBottom: 2,
491
- alignItems: "center",
492
- gap: 2,
493
- hasRadius: true,
494
- width: "100%",
495
- children: [
496
- /* @__PURE__ */ jsx(PencilIcon, {}),
497
- /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
498
- id: "content-releases.header.actions.edit",
499
- defaultMessage: "Edit"
500
- }) })
501
- ]
502
- }
503
- ) }),
504
- /* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canDelete, onSelect: toggleWarningSubmit, children: /* @__PURE__ */ jsxs(
505
- Flex,
810
+ /* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
811
+ /* @__PURE__ */ jsx(PencilIcon, {}),
812
+ /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
813
+ id: "content-releases.header.actions.edit",
814
+ defaultMessage: "Edit"
815
+ }) })
816
+ ] }) }),
817
+ /* @__PURE__ */ jsx(
818
+ StyledMenuItem,
506
819
  {
507
- paddingTop: 2,
508
- paddingBottom: 2,
509
- alignItems: "center",
510
- gap: 2,
511
- hasRadius: true,
512
- width: "100%",
513
- children: [
820
+ disabled: !canDelete,
821
+ onSelect: toggleWarningSubmit,
822
+ variant: "danger",
823
+ children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
514
824
  /* @__PURE__ */ jsx(TrashIcon, {}),
515
825
  /* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
516
826
  id: "content-releases.header.actions.delete",
517
827
  defaultMessage: "Delete"
518
828
  }) })
519
- ]
829
+ ] })
520
830
  }
521
- ) })
831
+ )
522
832
  ]
523
833
  }
524
834
  ),
@@ -536,7 +846,7 @@ const ReleaseDetailsLayout = ({
536
846
  defaultMessage: "Created"
537
847
  }) }),
538
848
  /* @__PURE__ */ jsxs(Typography, { variant: "pi", color: "neutral300", children: [
539
- /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(release.createdAt) }),
849
+ /* @__PURE__ */ jsx(RelativeTime$1, { timestamp: new Date(release.createdAt) }),
540
850
  formatMessage(
541
851
  {
542
852
  id: "content-releases.header.actions.created.description",
@@ -575,6 +885,7 @@ const ReleaseDetailsLayout = ({
575
885
  ] });
576
886
  };
577
887
  const GROUP_BY_OPTIONS = ["contentType", "locale", "action"];
888
+ const GROUP_BY_OPTIONS_NO_LOCALE = ["contentType", "action"];
578
889
  const getGroupByOptionLabel = (value) => {
579
890
  if (value === "locale") {
580
891
  return {
@@ -593,6 +904,21 @@ const getGroupByOptionLabel = (value) => {
593
904
  defaultMessage: "Content-Types"
594
905
  };
595
906
  };
907
+ const DEFAULT_RELEASE_DETAILS_HEADER = [
908
+ {
909
+ key: "__name__",
910
+ fieldSchema: { type: "string" },
911
+ metadatas: {
912
+ label: {
913
+ id: "content-releases.page.ReleaseDetails.table.header.label.name",
914
+ defaultMessage: "name"
915
+ },
916
+ searchable: false,
917
+ sortable: false
918
+ },
919
+ name: "name"
920
+ }
921
+ ];
596
922
  const ReleaseDetailsBody = () => {
597
923
  const { formatMessage } = useIntl();
598
924
  const { releaseId } = useParams();
@@ -608,6 +934,17 @@ const ReleaseDetailsBody = () => {
608
934
  const {
609
935
  allowedActions: { canUpdate }
610
936
  } = useRBAC(PERMISSIONS);
937
+ const { runHookWaterfall } = useStrapiApp();
938
+ const {
939
+ displayedHeaders,
940
+ hasI18nEnabled
941
+ } = runHookWaterfall(
942
+ "ContentReleases/pages/ReleaseDetails/add-locale-in-releases",
943
+ {
944
+ displayedHeaders: DEFAULT_RELEASE_DETAILS_HEADER,
945
+ hasI18nEnabled: false
946
+ }
947
+ );
611
948
  const release = releaseData?.data;
612
949
  const selectedGroupBy = query?.groupBy || "contentType";
613
950
  const {
@@ -694,7 +1031,7 @@ const ReleaseDetailsBody = () => {
694
1031
  action: /* @__PURE__ */ jsx(
695
1032
  LinkButton,
696
1033
  {
697
- as: Link$1,
1034
+ as: Link$2,
698
1035
  to: {
699
1036
  pathname: "/content-manager"
700
1037
  },
@@ -709,6 +1046,7 @@ const ReleaseDetailsBody = () => {
709
1046
  }
710
1047
  ) });
711
1048
  }
1049
+ const options = hasI18nEnabled ? GROUP_BY_OPTIONS : GROUP_BY_OPTIONS_NO_LOCALE;
712
1050
  return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
713
1051
  /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
714
1052
  SingleSelect,
@@ -728,7 +1066,7 @@ const ReleaseDetailsBody = () => {
728
1066
  ),
729
1067
  value: formatMessage(getGroupByOptionLabel(selectedGroupBy)),
730
1068
  onChange: (value) => setQuery({ groupBy: value }),
731
- children: GROUP_BY_OPTIONS.map((option) => /* @__PURE__ */ jsx(SingleSelectOption, { value: option, children: formatMessage(getGroupByOptionLabel(option)) }, option))
1069
+ children: options.map((option) => /* @__PURE__ */ jsx(SingleSelectOption, { value: option, children: formatMessage(getGroupByOptionLabel(option)) }, option))
732
1070
  }
733
1071
  ) }),
734
1072
  Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
@@ -745,28 +1083,15 @@ const ReleaseDetailsBody = () => {
745
1083
  isFetching,
746
1084
  children: /* @__PURE__ */ jsxs(Table.Content, { children: [
747
1085
  /* @__PURE__ */ jsxs(Table.Head, { children: [
748
- /* @__PURE__ */ jsx(
1086
+ displayedHeaders.map(({ key: key2, fieldSchema, metadatas, name }) => /* @__PURE__ */ jsx(
749
1087
  Table.HeaderCell,
750
1088
  {
751
- fieldSchemaType: "string",
752
- label: formatMessage({
753
- id: "content-releases.page.ReleaseDetails.table.header.label.name",
754
- defaultMessage: "name"
755
- }),
756
- name: "name"
757
- }
758
- ),
759
- /* @__PURE__ */ jsx(
760
- Table.HeaderCell,
761
- {
762
- fieldSchemaType: "string",
763
- label: formatMessage({
764
- id: "content-releases.page.ReleaseDetails.table.header.label.locale",
765
- defaultMessage: "locale"
766
- }),
767
- name: "locale"
768
- }
769
- ),
1089
+ fieldSchemaType: fieldSchema.type,
1090
+ label: formatMessage(metadatas.label),
1091
+ name
1092
+ },
1093
+ key2
1094
+ )),
770
1095
  /* @__PURE__ */ jsx(
771
1096
  Table.HeaderCell,
772
1097
  {
@@ -805,7 +1130,7 @@ const ReleaseDetailsBody = () => {
805
1130
  /* @__PURE__ */ jsx(Table.Body, { children: releaseActions[key].map(
806
1131
  ({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxs(Tr, { children: [
807
1132
  /* @__PURE__ */ jsx(Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
808
- /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
1133
+ hasI18nEnabled && /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
809
1134
  /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: contentType.displayName || "" }) }),
810
1135
  /* @__PURE__ */ jsx(Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsx(Typography, { children: formatMessage(
811
1136
  {
@@ -872,277 +1197,61 @@ const ReleaseDetailsBody = () => {
872
1197
  ] })
873
1198
  ] }) });
874
1199
  };
875
- const ReleaseDetailsPage = () => {
876
- const { formatMessage } = useIntl();
877
- const { releaseId } = useParams();
878
- const toggleNotification = useNotification();
879
- const { formatAPIError } = useAPIErrorHandler();
880
- const { push } = useHistory();
881
- const [releaseModalShown, setReleaseModalShown] = React.useState(false);
882
- const [showWarningSubmit, setWarningSubmit] = React.useState(false);
883
- const {
884
- isLoading: isLoadingDetails,
885
- data,
886
- isSuccess: isSuccessDetails
887
- } = useGetReleaseQuery({ id: releaseId });
888
- const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();
889
- const [deleteRelease, { isLoading: isDeletingRelease }] = useDeleteReleaseMutation();
890
- const toggleEditReleaseModal = () => {
891
- setReleaseModalShown((prev) => !prev);
892
- };
893
- const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);
894
- if (isLoadingDetails) {
895
- return /* @__PURE__ */ jsx(
896
- ReleaseDetailsLayout,
897
- {
898
- toggleEditReleaseModal,
899
- toggleWarningSubmit,
900
- children: /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) })
901
- }
902
- );
903
- }
904
- const releaseData = isSuccessDetails && data?.data || null;
905
- const title = releaseData?.name || "";
906
- const timezone = releaseData?.timezone ?? null;
907
- const scheduledAt = releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;
908
- const date = scheduledAt ? new Date(format(scheduledAt, "yyyy-MM-dd")) : null;
909
- const time = scheduledAt ? format(scheduledAt, "HH:mm") : "";
910
- const handleEditRelease = async (values) => {
911
- const response = await updateRelease({
912
- id: releaseId,
913
- name: values.name,
914
- scheduledAt: values.scheduledAt,
915
- timezone: values.timezone
916
- });
917
- if ("data" in response) {
918
- toggleNotification({
919
- type: "success",
920
- message: formatMessage({
921
- id: "content-releases.modal.release-updated-notification-success",
922
- defaultMessage: "Release updated."
923
- })
924
- });
925
- } else if (isAxiosError(response.error)) {
926
- toggleNotification({
927
- type: "warning",
928
- message: formatAPIError(response.error)
929
- });
930
- } else {
931
- toggleNotification({
932
- type: "warning",
933
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
934
- });
935
- }
936
- toggleEditReleaseModal();
937
- };
938
- const handleDeleteRelease = async () => {
939
- const response = await deleteRelease({
940
- id: releaseId
941
- });
942
- if ("data" in response) {
943
- push("/plugins/content-releases");
944
- } else if (isAxiosError(response.error)) {
945
- toggleNotification({
946
- type: "warning",
947
- message: formatAPIError(response.error)
948
- });
949
- } else {
950
- toggleNotification({
951
- type: "warning",
952
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
953
- });
954
- }
955
- };
956
- return /* @__PURE__ */ jsxs(
957
- ReleaseDetailsLayout,
958
- {
959
- toggleEditReleaseModal,
960
- toggleWarningSubmit,
961
- children: [
962
- /* @__PURE__ */ jsx(ReleaseDetailsBody, {}),
963
- releaseModalShown && /* @__PURE__ */ jsx(
964
- ReleaseModal,
965
- {
966
- handleClose: toggleEditReleaseModal,
967
- handleSubmit: handleEditRelease,
968
- isLoading: isLoadingDetails || isSubmittingForm,
969
- initialValues: {
970
- name: title || "",
971
- scheduledAt,
972
- date,
973
- time,
974
- isScheduled: Boolean(scheduledAt),
975
- timezone
976
- }
977
- }
978
- ),
979
- /* @__PURE__ */ jsx(
980
- ConfirmDialog,
981
- {
982
- bodyText: {
983
- id: "content-releases.dialog.confirmation-message",
984
- defaultMessage: "Are you sure you want to delete this release?"
985
- },
986
- isOpen: showWarningSubmit,
987
- isConfirmButtonLoading: isDeletingRelease,
988
- onToggleDialog: toggleWarningSubmit,
989
- onConfirm: handleDeleteRelease
990
- }
991
- )
992
- ]
993
- }
994
- );
995
- };
996
- const LinkCard = styled(Link$2)`
997
- display: block;
998
- `;
999
- const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
1000
- const { formatMessage } = useIntl();
1001
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
1002
- if (isError) {
1003
- return /* @__PURE__ */ jsx(AnErrorOccurred, {});
1004
- }
1005
- if (releases?.length === 0) {
1006
- return /* @__PURE__ */ jsx(
1007
- EmptyStateLayout,
1008
- {
1009
- content: formatMessage(
1010
- {
1011
- id: "content-releases.page.Releases.tab.emptyEntries",
1012
- defaultMessage: "No releases"
1013
- },
1014
- {
1015
- target: sectionTitle
1016
- }
1017
- ),
1018
- icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem" })
1019
- }
1020
- );
1021
- }
1022
- return /* @__PURE__ */ jsx(Grid, { gap: 4, children: releases.map(({ id, name, actions, scheduledAt }) => /* @__PURE__ */ jsx(GridItem, { col: 3, s: 6, xs: 12, children: /* @__PURE__ */ jsx(LinkCard, { href: `content-releases/${id}`, isExternal: false, children: /* @__PURE__ */ jsxs(
1023
- Flex,
1024
- {
1025
- direction: "column",
1026
- justifyContent: "space-between",
1027
- padding: 4,
1028
- hasRadius: true,
1029
- background: "neutral0",
1030
- shadow: "tableShadow",
1031
- height: "100%",
1032
- width: "100%",
1033
- alignItems: "start",
1034
- gap: 2,
1035
- children: [
1036
- /* @__PURE__ */ jsx(Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
1037
- /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: IsSchedulingEnabled ? scheduledAt ? /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
1038
- id: "content-releases.pages.Releases.not-scheduled",
1039
- defaultMessage: "Not scheduled"
1040
- }) : formatMessage(
1041
- {
1042
- id: "content-releases.page.Releases.release-item.entries",
1043
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
1044
- },
1045
- { number: actions.meta.count }
1046
- ) })
1047
- ]
1048
- }
1049
- ) }) }, id)) });
1050
- };
1051
- const StyledAlert = styled(Alert)`
1052
- button {
1053
- display: none;
1054
- }
1055
- p + div {
1056
- margin-left: auto;
1057
- }
1058
- `;
1059
- const INITIAL_FORM_VALUES = {
1060
- name: "",
1061
- date: null,
1062
- time: "",
1063
- // Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
1064
- isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
1065
- scheduledAt: null,
1066
- timezone: null
1067
- };
1068
- const ReleasesPage = () => {
1069
- const tabRef = React.useRef(null);
1070
- const location = useLocation();
1071
- const [releaseModalShown, setReleaseModalShown] = React.useState(false);
1072
- const toggleNotification = useNotification();
1200
+ const ReleaseDetailsPage = () => {
1073
1201
  const { formatMessage } = useIntl();
1074
- const { push, replace } = useHistory();
1202
+ const { releaseId } = useParams();
1203
+ const toggleNotification = useNotification();
1075
1204
  const { formatAPIError } = useAPIErrorHandler();
1076
- const [{ query }, setQuery] = useQueryParams();
1077
- const response = useGetReleasesQuery(query);
1078
- const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();
1079
- const { getFeature } = useLicenseLimits();
1080
- const { maximumReleases = 3 } = getFeature("cms-content-releases");
1081
- const { trackUsage } = useTracking();
1082
- const { isLoading, isSuccess, isError } = response;
1083
- const activeTab = response?.currentData?.meta?.activeTab || "pending";
1084
- const activeTabIndex = ["pending", "done"].indexOf(activeTab);
1085
- React.useEffect(() => {
1086
- if (location?.state?.errors) {
1087
- toggleNotification({
1088
- type: "warning",
1089
- title: formatMessage({
1090
- id: "content-releases.pages.Releases.notification.error.title",
1091
- defaultMessage: "Your request could not be processed."
1092
- }),
1093
- message: formatMessage({
1094
- id: "content-releases.pages.Releases.notification.error.message",
1095
- defaultMessage: "Please try again or open another release."
1096
- })
1097
- });
1098
- replace({ state: null });
1099
- }
1100
- }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
1101
- React.useEffect(() => {
1102
- if (tabRef.current) {
1103
- tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
1104
- }
1105
- }, [activeTabIndex]);
1106
- const toggleAddReleaseModal = () => {
1205
+ const { replace } = useHistory();
1206
+ const [releaseModalShown, setReleaseModalShown] = React.useState(false);
1207
+ const [showWarningSubmit, setWarningSubmit] = React.useState(false);
1208
+ const {
1209
+ isLoading: isLoadingDetails,
1210
+ data,
1211
+ isSuccess: isSuccessDetails
1212
+ } = useGetReleaseQuery({ id: releaseId });
1213
+ const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();
1214
+ const [deleteRelease, { isLoading: isDeletingRelease }] = useDeleteReleaseMutation();
1215
+ const toggleEditReleaseModal = () => {
1107
1216
  setReleaseModalShown((prev) => !prev);
1108
1217
  };
1109
- if (isLoading) {
1110
- return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
1111
- }
1112
- const totalReleases = isSuccess && response.currentData?.meta?.pagination?.total || 0;
1113
- const hasReachedMaximumPendingReleases = totalReleases >= maximumReleases;
1114
- const handleTabChange = (index) => {
1115
- setQuery({
1116
- ...query,
1117
- page: 1,
1118
- pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
1119
- filters: {
1120
- releasedAt: {
1121
- $notNull: index === 0 ? false : true
1122
- }
1218
+ const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);
1219
+ if (isLoadingDetails) {
1220
+ return /* @__PURE__ */ jsx(
1221
+ ReleaseDetailsLayout,
1222
+ {
1223
+ toggleEditReleaseModal,
1224
+ toggleWarningSubmit,
1225
+ children: /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) })
1123
1226
  }
1227
+ );
1228
+ }
1229
+ const releaseData = isSuccessDetails && data?.data || null;
1230
+ const title = releaseData?.name || "";
1231
+ const timezone = releaseData?.timezone ?? null;
1232
+ const scheduledAt = releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;
1233
+ const date = scheduledAt ? format(scheduledAt, "yyyy-MM-dd") : null;
1234
+ const time = scheduledAt ? format(scheduledAt, "HH:mm") : "";
1235
+ const handleEditRelease = async (values) => {
1236
+ const response = await updateRelease({
1237
+ id: releaseId,
1238
+ name: values.name,
1239
+ scheduledAt: values.scheduledAt,
1240
+ timezone: values.timezone
1124
1241
  });
1125
- };
1126
- const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
1127
- const response2 = await createRelease({
1128
- name,
1129
- scheduledAt,
1130
- timezone
1131
- });
1132
- if ("data" in response2) {
1242
+ if ("data" in response) {
1133
1243
  toggleNotification({
1134
1244
  type: "success",
1135
1245
  message: formatMessage({
1136
- id: "content-releases.modal.release-created-notification-success",
1137
- defaultMessage: "Release created."
1246
+ id: "content-releases.modal.release-updated-notification-success",
1247
+ defaultMessage: "Release updated."
1138
1248
  })
1139
1249
  });
1140
- trackUsage("didCreateRelease");
1141
- push(`/plugins/content-releases/${response2.data.data.id}`);
1142
- } else if (isAxiosError(response2.error)) {
1250
+ toggleEditReleaseModal();
1251
+ } else if (isAxiosError(response.error)) {
1143
1252
  toggleNotification({
1144
1253
  type: "warning",
1145
- message: formatAPIError(response2.error)
1254
+ message: formatAPIError(response.error)
1146
1255
  });
1147
1256
  } else {
1148
1257
  toggleNotification({
@@ -1151,134 +1260,63 @@ const ReleasesPage = () => {
1151
1260
  });
1152
1261
  }
1153
1262
  };
1154
- return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoading, children: [
1155
- /* @__PURE__ */ jsx(
1156
- HeaderLayout,
1157
- {
1158
- title: formatMessage({
1159
- id: "content-releases.pages.Releases.title",
1160
- defaultMessage: "Releases"
1161
- }),
1162
- subtitle: formatMessage(
1163
- {
1164
- id: "content-releases.pages.Releases.header-subtitle",
1165
- defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
1166
- },
1167
- { number: totalReleases }
1168
- ),
1169
- primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(
1170
- Button,
1171
- {
1172
- startIcon: /* @__PURE__ */ jsx(Plus, {}),
1173
- onClick: toggleAddReleaseModal,
1174
- disabled: hasReachedMaximumPendingReleases,
1175
- children: formatMessage({
1176
- id: "content-releases.header.actions.add-release",
1177
- defaultMessage: "New release"
1178
- })
1179
- }
1180
- ) })
1181
- }
1182
- ),
1183
- /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
1184
- activeTab === "pending" && hasReachedMaximumPendingReleases && /* @__PURE__ */ jsx(
1185
- StyledAlert,
1186
- {
1187
- marginBottom: 6,
1188
- action: /* @__PURE__ */ jsx(Link$2, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
1189
- id: "content-releases.pages.Releases.max-limit-reached.action",
1190
- defaultMessage: "Explore plans"
1191
- }) }),
1192
- title: formatMessage(
1193
- {
1194
- id: "content-releases.pages.Releases.max-limit-reached.title",
1195
- defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
1196
- },
1197
- { number: maximumReleases }
1198
- ),
1199
- onClose: () => {
1200
- },
1201
- closeLabel: "",
1202
- children: formatMessage({
1203
- id: "content-releases.pages.Releases.max-limit-reached.message",
1204
- defaultMessage: "Upgrade to manage an unlimited number of releases."
1205
- })
1206
- }
1207
- ),
1208
- /* @__PURE__ */ jsxs(
1209
- TabGroup,
1210
- {
1211
- label: formatMessage({
1212
- id: "content-releases.pages.Releases.tab-group.label",
1213
- defaultMessage: "Releases list"
1214
- }),
1215
- variant: "simple",
1216
- initialSelectedTabIndex: activeTabIndex,
1217
- onTabChange: handleTabChange,
1218
- ref: tabRef,
1219
- children: [
1220
- /* @__PURE__ */ jsxs(Box, { paddingBottom: 8, children: [
1221
- /* @__PURE__ */ jsxs(Tabs, { children: [
1222
- /* @__PURE__ */ jsx(Tab, { children: formatMessage({
1223
- id: "content-releases.pages.Releases.tab.pending",
1224
- defaultMessage: "Pending"
1225
- }) }),
1226
- /* @__PURE__ */ jsx(Tab, { children: formatMessage({
1227
- id: "content-releases.pages.Releases.tab.done",
1228
- defaultMessage: "Done"
1229
- }) })
1230
- ] }),
1231
- /* @__PURE__ */ jsx(Divider, {})
1232
- ] }),
1233
- /* @__PURE__ */ jsxs(TabPanels, { children: [
1234
- /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
1235
- ReleasesGrid,
1236
- {
1237
- sectionTitle: "pending",
1238
- releases: response?.currentData?.data,
1239
- isError
1240
- }
1241
- ) }),
1242
- /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
1243
- ReleasesGrid,
1244
- {
1245
- sectionTitle: "done",
1246
- releases: response?.currentData?.data,
1247
- isError
1248
- }
1249
- ) })
1250
- ] })
1251
- ]
1252
- }
1253
- ),
1254
- totalReleases > 0 && /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
1255
- /* @__PURE__ */ jsx(
1256
- PageSizeURLQuery,
1263
+ const handleDeleteRelease = async () => {
1264
+ const response = await deleteRelease({
1265
+ id: releaseId
1266
+ });
1267
+ if ("data" in response) {
1268
+ replace("/plugins/content-releases");
1269
+ } else if (isAxiosError(response.error)) {
1270
+ toggleNotification({
1271
+ type: "warning",
1272
+ message: formatAPIError(response.error)
1273
+ });
1274
+ } else {
1275
+ toggleNotification({
1276
+ type: "warning",
1277
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1278
+ });
1279
+ }
1280
+ };
1281
+ return /* @__PURE__ */ jsxs(
1282
+ ReleaseDetailsLayout,
1283
+ {
1284
+ toggleEditReleaseModal,
1285
+ toggleWarningSubmit,
1286
+ children: [
1287
+ /* @__PURE__ */ jsx(ReleaseDetailsBody, {}),
1288
+ releaseModalShown && /* @__PURE__ */ jsx(
1289
+ ReleaseModal,
1257
1290
  {
1258
- options: ["8", "16", "32", "64"],
1259
- defaultValue: response?.currentData?.meta?.pagination?.pageSize.toString()
1291
+ handleClose: toggleEditReleaseModal,
1292
+ handleSubmit: handleEditRelease,
1293
+ isLoading: isLoadingDetails || isSubmittingForm,
1294
+ initialValues: {
1295
+ name: title || "",
1296
+ scheduledAt,
1297
+ date,
1298
+ time,
1299
+ isScheduled: Boolean(scheduledAt),
1300
+ timezone
1301
+ }
1260
1302
  }
1261
1303
  ),
1262
1304
  /* @__PURE__ */ jsx(
1263
- PaginationURLQuery,
1305
+ ConfirmDialog,
1264
1306
  {
1265
- pagination: {
1266
- pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
1267
- }
1307
+ bodyText: {
1308
+ id: "content-releases.dialog.confirmation-message",
1309
+ defaultMessage: "Are you sure you want to delete this release?"
1310
+ },
1311
+ isOpen: showWarningSubmit,
1312
+ isConfirmButtonLoading: isDeletingRelease,
1313
+ onToggleDialog: toggleWarningSubmit,
1314
+ onConfirm: handleDeleteRelease
1268
1315
  }
1269
1316
  )
1270
- ] })
1271
- ] }) }),
1272
- releaseModalShown && /* @__PURE__ */ jsx(
1273
- ReleaseModal,
1274
- {
1275
- handleClose: toggleAddReleaseModal,
1276
- handleSubmit: handleAddRelease,
1277
- isLoading: isSubmittingForm,
1278
- initialValues: INITIAL_FORM_VALUES
1279
- }
1280
- )
1281
- ] });
1317
+ ]
1318
+ }
1319
+ );
1282
1320
  };
1283
1321
  const App = () => {
1284
1322
  return /* @__PURE__ */ jsx(CheckPagePermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(Switch, { children: [
@@ -1289,4 +1327,4 @@ const App = () => {
1289
1327
  export {
1290
1328
  App
1291
1329
  };
1292
- //# sourceMappingURL=App-xAkiD42p.mjs.map
1330
+ //# sourceMappingURL=App-jrh58sXY.mjs.map