@strapi/content-releases 0.0.0-next.4af8963f6880c5fb9fae32ecd580f5cd33eaddda → 0.0.0-next.4dbfc9c0220552ce3e3997bf993b0978b0e60331

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 (31) hide show
  1. package/dist/_chunks/{App-w2Zq-wj5.js → App--3HPsVgM.js} +704 -647
  2. package/dist/_chunks/App--3HPsVgM.js.map +1 -0
  3. package/dist/_chunks/{App-ise7GunC.mjs → App-CRNZU_DZ.mjs} +717 -660
  4. package/dist/_chunks/App-CRNZU_DZ.mjs.map +1 -0
  5. package/dist/_chunks/{PurchaseContentReleases-Clm0iACO.mjs → PurchaseContentReleases-3tRbmbY3.mjs} +2 -2
  6. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
  7. package/dist/_chunks/{PurchaseContentReleases-YhAPgpG9.js → PurchaseContentReleases-bpIYXOfu.js} +2 -2
  8. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
  9. package/dist/_chunks/{en-7P4i1cWH.js → en-3SGjiVyR.js} +17 -6
  10. package/dist/_chunks/en-3SGjiVyR.js.map +1 -0
  11. package/dist/_chunks/{en-pb1wUzhy.mjs → en-bpHsnU0n.mjs} +17 -6
  12. package/dist/_chunks/en-bpHsnU0n.mjs.map +1 -0
  13. package/dist/_chunks/{index-D-Yjf60c.mjs → index-_wu9g0yG.mjs} +279 -25
  14. package/dist/_chunks/index-_wu9g0yG.mjs.map +1 -0
  15. package/dist/_chunks/{index-Q8Pv7enO.js → index-xV3jXcZj.js} +267 -13
  16. package/dist/_chunks/index-xV3jXcZj.js.map +1 -0
  17. package/dist/admin/index.js +1 -1
  18. package/dist/admin/index.mjs +2 -2
  19. package/dist/server/index.js +554 -170
  20. package/dist/server/index.js.map +1 -1
  21. package/dist/server/index.mjs +553 -170
  22. package/dist/server/index.mjs.map +1 -1
  23. package/package.json +12 -12
  24. package/dist/_chunks/App-ise7GunC.mjs.map +0 -1
  25. package/dist/_chunks/App-w2Zq-wj5.js.map +0 -1
  26. package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +0 -1
  27. package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +0 -1
  28. package/dist/_chunks/en-7P4i1cWH.js.map +0 -1
  29. package/dist/_chunks/en-pb1wUzhy.mjs.map +0 -1
  30. package/dist/_chunks/index-D-Yjf60c.mjs.map +0 -1
  31. package/dist/_chunks/index-Q8Pv7enO.js.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 { 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, g as ReleaseActionMenu, i as isAxiosError, r as releaseApi, h as useGetReleasesQuery, j as useCreateReleaseMutation } from "./index-D-Yjf60c.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-_wu9g0yG.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, Checkbox, Box, 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(
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(
@@ -213,19 +207,11 @@ const ReleaseModal = ({
213
207
  };
214
208
  const getTimezones = (selectedDate) => {
215
209
  const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
216
- const offsetPart = new Intl.DateTimeFormat("en", {
217
- timeZone: timezone,
218
- timeZoneName: "longOffset"
219
- }).formatToParts(selectedDate).find((part) => part.type === "timeZoneName");
220
- const offset = offsetPart ? offsetPart.value : "";
221
- let utcOffset = offset.replace("GMT", "UTC");
222
- if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
223
- utcOffset = `${utcOffset}+00:00`;
224
- }
225
- return { offset: utcOffset, value: `${utcOffset}-${timezone}` };
210
+ const utcOffset = getTimezoneOffset(timezone, selectedDate);
211
+ return { offset: utcOffset, value: `${utcOffset}&${timezone}` };
226
212
  });
227
213
  const systemTimezone = timezoneList.find(
228
- (timezone) => timezone.value.split("-")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
214
+ (timezone) => timezone.value.split("&")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
229
215
  );
230
216
  return { timezoneList, systemTimezone };
231
217
  };
@@ -237,7 +223,7 @@ const TimezoneComponent = ({ timezoneOptions }) => {
237
223
  if (values.date) {
238
224
  const { timezoneList: timezoneList2 } = getTimezones(new Date(values.date));
239
225
  setTimezoneList(timezoneList2);
240
- 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]);
241
227
  if (updatedTimezone) {
242
228
  setFieldValue("timezone", updatedTimezone.value);
243
229
  }
@@ -250,137 +236,201 @@ const TimezoneComponent = ({ timezoneOptions }) => {
250
236
  id: "content-releases.modal.form.input.label.timezone",
251
237
  defaultMessage: "Timezone"
252
238
  }),
239
+ autocomplete: { type: "list", filter: "contains" },
253
240
  name: "timezone",
254
241
  value: values.timezone || void 0,
255
- textValue: values.timezone ? values.timezone.replace("-", " ") : void 0,
242
+ textValue: values.timezone ? values.timezone.replace(/&/, " ") : void 0,
256
243
  onChange: (timezone) => {
257
244
  setFieldValue("timezone", timezone);
258
245
  },
246
+ onTextValueChange: (timezone) => {
247
+ setFieldValue("timezone", timezone);
248
+ },
259
249
  onClear: () => {
260
250
  setFieldValue("timezone", "");
261
251
  },
262
252
  error: errors.timezone,
263
253
  required: true,
264
- 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))
265
255
  }
266
256
  );
267
257
  };
268
- const ReleaseInfoWrapper = styled(Flex)`
269
- align-self: stretch;
270
- border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
271
- border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
272
- border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
273
- `;
274
- const StyledMenuItem = styled(Menu.Item)`
275
- svg path {
276
- fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
277
- }
278
- span {
279
- color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
280
- }
258
+ const LinkCard = styled(Link)`
259
+ display: block;
281
260
  `;
282
- const PencilIcon = styled(Pencil)`
283
- width: ${({ theme }) => theme.spaces[3]};
284
- height: ${({ theme }) => theme.spaces[3]};
285
- path {
286
- fill: ${({ theme }) => theme.colors.neutral600};
261
+ const RelativeTime = styled(RelativeTime$1)`
262
+ display: inline-block;
263
+ &::first-letter {
264
+ text-transform: uppercase;
287
265
  }
288
266
  `;
289
- const TrashIcon = styled(Trash)`
290
- width: ${({ theme }) => theme.spaces[3]};
291
- height: ${({ theme }) => theme.spaces[3]};
292
- path {
293
- 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";
294
285
  }
295
- `;
296
- const TypographyMaxWidth = styled(Typography)`
297
- max-width: 300px;
298
- `;
299
- 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 }) => {
300
293
  const { formatMessage } = useIntl();
301
- const { validate } = unstable_useDocument();
302
- const { errors } = validate(entry, {
303
- contentType: schema,
304
- components,
305
- isCreatingEntry: false
306
- });
307
- if (Object.keys(errors).length > 0) {
308
- const validationErrorsMessages = Object.entries(errors).map(
309
- ([key, value]) => formatMessage(
310
- { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
311
- { field: key }
312
- )
313
- ).join(" ");
314
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
315
- /* @__PURE__ */ jsx(Icon, { color: "danger600", as: CrossCircle }),
316
- /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
317
- ] });
294
+ if (isError) {
295
+ return /* @__PURE__ */ jsx(AnErrorOccurred, {});
318
296
  }
319
- if (action == "publish") {
320
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
321
- /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
322
- entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
323
- id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
324
- defaultMessage: "Already published"
325
- }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
326
- id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
327
- defaultMessage: "Ready to publish"
328
- }) })
329
- ] });
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
+ );
330
313
  }
331
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
332
- /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
333
- !entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
334
- id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
335
- defaultMessage: "Already unpublished"
336
- }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
337
- id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish",
338
- defaultMessage: "Ready to unpublish"
339
- }) })
340
- ] });
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)) });
341
339
  };
342
- const ReleaseDetailsLayout = ({
343
- toggleEditReleaseModal,
344
- toggleWarningSubmit,
345
- children
346
- }) => {
347
- const { formatMessage } = useIntl();
348
- const { releaseId } = useParams();
349
- const {
350
- data,
351
- isLoading: isLoadingDetails,
352
- isError,
353
- error
354
- } = useGetReleaseQuery({ id: releaseId });
355
- 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);
356
360
  const toggleNotification = useNotification();
361
+ const { formatMessage } = useIntl();
362
+ const { push, replace } = useHistory();
357
363
  const { formatAPIError } = useAPIErrorHandler();
358
- const {
359
- allowedActions: { canUpdate, canDelete }
360
- } = useRBAC(PERMISSIONS);
361
- 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");
362
369
  const { trackUsage } = useTracking();
363
- const release = data?.data;
364
- const handlePublishRelease = async () => {
365
- const response = await publishRelease({ id: releaseId });
366
- 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) {
367
375
  toggleNotification({
368
- 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
+ }),
369
381
  message: formatMessage({
370
- id: "content-releases.pages.ReleaseDetails.publish-notification-success",
371
- defaultMessage: "Release was published successfully."
382
+ id: "content-releases.pages.Releases.notification.error.message",
383
+ defaultMessage: "Please try again or open another release."
372
384
  })
373
385
  });
374
- const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
375
- trackUsage("didPublishRelease", {
376
- totalEntries: totalEntries2,
377
- totalPublishedEntries,
378
- 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
+ })
379
427
  });
380
- } else if (isAxiosError(response.error)) {
428
+ trackUsage("didCreateRelease");
429
+ push(`/plugins/content-releases/${response2.data.data.id}`);
430
+ } else if (isAxiosError(response2.error)) {
381
431
  toggleNotification({
382
432
  type: "warning",
383
- message: formatAPIError(response.error)
433
+ message: formatAPIError(response2.error)
384
434
  });
385
435
  } else {
386
436
  toggleNotification({
@@ -389,18 +439,282 @@ const ReleaseDetailsLayout = ({
389
439
  });
390
440
  }
391
441
  };
392
- const handleRefresh = () => {
393
- dispatch(releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
394
- };
395
- const getCreatedByUser = () => {
396
- if (!release?.createdBy) {
397
- return null;
398
- }
399
- if (release.createdBy.username) {
400
- return release.createdBy.username;
401
- }
402
- if (release.createdBy.firstname) {
403
- return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
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();
404
718
  }
405
719
  return release.createdBy.email;
406
720
  };
@@ -426,19 +740,44 @@ const ReleaseDetailsLayout = ({
426
740
  }
427
741
  const totalEntries = release.actions.meta.count || 0;
428
742
  const hasCreatedByUser = Boolean(getCreatedByUser());
743
+ const isScheduled = release.scheduledAt && release.timezone;
744
+ const numberOfEntriesText = formatMessage(
745
+ {
746
+ id: "content-releases.pages.Details.header-subtitle",
747
+ defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
748
+ },
749
+ { number: totalEntries }
750
+ );
751
+ const scheduledText = isScheduled ? formatMessage(
752
+ {
753
+ id: "content-releases.pages.ReleaseDetails.header-subtitle.scheduled",
754
+ defaultMessage: "Scheduled for {date} at {time} ({offset})"
755
+ },
756
+ {
757
+ date: formatDate(new Date(release.scheduledAt), {
758
+ weekday: "long",
759
+ day: "numeric",
760
+ month: "long",
761
+ year: "numeric",
762
+ timeZone: release.timezone
763
+ }),
764
+ time: formatTime(new Date(release.scheduledAt), {
765
+ timeZone: release.timezone,
766
+ hourCycle: "h23"
767
+ }),
768
+ offset: getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
769
+ }
770
+ ) : "";
429
771
  return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
430
772
  /* @__PURE__ */ jsx(
431
773
  HeaderLayout,
432
774
  {
433
775
  title: release.name,
434
- subtitle: formatMessage(
435
- {
436
- id: "content-releases.pages.Details.header-subtitle",
437
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
438
- },
439
- { number: totalEntries }
440
- ),
441
- 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({
442
781
  id: "global.back",
443
782
  defaultMessage: "Back"
444
783
  }) }),
@@ -468,42 +807,28 @@ const ReleaseDetailsLayout = ({
468
807
  padding: 1,
469
808
  width: "100%",
470
809
  children: [
471
- /* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxs(
472
- Flex,
473
- {
474
- paddingTop: 2,
475
- paddingBottom: 2,
476
- alignItems: "center",
477
- gap: 2,
478
- hasRadius: true,
479
- width: "100%",
480
- children: [
481
- /* @__PURE__ */ jsx(PencilIcon, {}),
482
- /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
483
- id: "content-releases.header.actions.edit",
484
- defaultMessage: "Edit"
485
- }) })
486
- ]
487
- }
488
- ) }),
489
- /* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canDelete, onSelect: toggleWarningSubmit, children: /* @__PURE__ */ jsxs(
490
- 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,
491
819
  {
492
- paddingTop: 2,
493
- paddingBottom: 2,
494
- alignItems: "center",
495
- gap: 2,
496
- hasRadius: true,
497
- width: "100%",
498
- children: [
820
+ disabled: !canDelete,
821
+ onSelect: toggleWarningSubmit,
822
+ variant: "danger",
823
+ children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
499
824
  /* @__PURE__ */ jsx(TrashIcon, {}),
500
825
  /* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
501
826
  id: "content-releases.header.actions.delete",
502
827
  defaultMessage: "Delete"
503
828
  }) })
504
- ]
829
+ ] })
505
830
  }
506
- ) })
831
+ )
507
832
  ]
508
833
  }
509
834
  ),
@@ -521,7 +846,7 @@ const ReleaseDetailsLayout = ({
521
846
  defaultMessage: "Created"
522
847
  }) }),
523
848
  /* @__PURE__ */ jsxs(Typography, { variant: "pi", color: "neutral300", children: [
524
- /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(release.createdAt) }),
849
+ /* @__PURE__ */ jsx(RelativeTime$1, { timestamp: new Date(release.createdAt) }),
525
850
  formatMessage(
526
851
  {
527
852
  id: "content-releases.header.actions.created.description",
@@ -560,6 +885,7 @@ const ReleaseDetailsLayout = ({
560
885
  ] });
561
886
  };
562
887
  const GROUP_BY_OPTIONS = ["contentType", "locale", "action"];
888
+ const GROUP_BY_OPTIONS_NO_LOCALE = ["contentType", "action"];
563
889
  const getGroupByOptionLabel = (value) => {
564
890
  if (value === "locale") {
565
891
  return {
@@ -578,6 +904,21 @@ const getGroupByOptionLabel = (value) => {
578
904
  defaultMessage: "Content-Types"
579
905
  };
580
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
+ ];
581
922
  const ReleaseDetailsBody = () => {
582
923
  const { formatMessage } = useIntl();
583
924
  const { releaseId } = useParams();
@@ -593,6 +934,17 @@ const ReleaseDetailsBody = () => {
593
934
  const {
594
935
  allowedActions: { canUpdate }
595
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
+ );
596
948
  const release = releaseData?.data;
597
949
  const selectedGroupBy = query?.groupBy || "contentType";
598
950
  const {
@@ -679,7 +1031,7 @@ const ReleaseDetailsBody = () => {
679
1031
  action: /* @__PURE__ */ jsx(
680
1032
  LinkButton,
681
1033
  {
682
- as: Link$1,
1034
+ as: Link$2,
683
1035
  to: {
684
1036
  pathname: "/content-manager"
685
1037
  },
@@ -694,6 +1046,7 @@ const ReleaseDetailsBody = () => {
694
1046
  }
695
1047
  ) });
696
1048
  }
1049
+ const options = hasI18nEnabled ? GROUP_BY_OPTIONS : GROUP_BY_OPTIONS_NO_LOCALE;
697
1050
  return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
698
1051
  /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
699
1052
  SingleSelect,
@@ -713,7 +1066,7 @@ const ReleaseDetailsBody = () => {
713
1066
  ),
714
1067
  value: formatMessage(getGroupByOptionLabel(selectedGroupBy)),
715
1068
  onChange: (value) => setQuery({ groupBy: value }),
716
- 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))
717
1070
  }
718
1071
  ) }),
719
1072
  Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
@@ -730,28 +1083,15 @@ const ReleaseDetailsBody = () => {
730
1083
  isFetching,
731
1084
  children: /* @__PURE__ */ jsxs(Table.Content, { children: [
732
1085
  /* @__PURE__ */ jsxs(Table.Head, { children: [
733
- /* @__PURE__ */ jsx(
1086
+ displayedHeaders.map(({ key: key2, fieldSchema, metadatas, name }) => /* @__PURE__ */ jsx(
734
1087
  Table.HeaderCell,
735
1088
  {
736
- fieldSchemaType: "string",
737
- label: formatMessage({
738
- id: "content-releases.page.ReleaseDetails.table.header.label.name",
739
- defaultMessage: "name"
740
- }),
741
- name: "name"
742
- }
743
- ),
744
- /* @__PURE__ */ jsx(
745
- Table.HeaderCell,
746
- {
747
- fieldSchemaType: "string",
748
- label: formatMessage({
749
- id: "content-releases.page.ReleaseDetails.table.header.label.locale",
750
- defaultMessage: "locale"
751
- }),
752
- name: "locale"
753
- }
754
- ),
1089
+ fieldSchemaType: fieldSchema.type,
1090
+ label: formatMessage(metadatas.label),
1091
+ name
1092
+ },
1093
+ key2
1094
+ )),
755
1095
  /* @__PURE__ */ jsx(
756
1096
  Table.HeaderCell,
757
1097
  {
@@ -790,7 +1130,7 @@ const ReleaseDetailsBody = () => {
790
1130
  /* @__PURE__ */ jsx(Table.Body, { children: releaseActions[key].map(
791
1131
  ({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxs(Tr, { children: [
792
1132
  /* @__PURE__ */ jsx(Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
793
- /* @__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 : "-"}` }) }),
794
1134
  /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: contentType.displayName || "" }) }),
795
1135
  /* @__PURE__ */ jsx(Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsx(Typography, { children: formatMessage(
796
1136
  {
@@ -857,273 +1197,61 @@ const ReleaseDetailsBody = () => {
857
1197
  ] })
858
1198
  ] }) });
859
1199
  };
860
- const ReleaseDetailsPage = () => {
861
- const { formatMessage } = useIntl();
862
- const { releaseId } = useParams();
863
- const toggleNotification = useNotification();
864
- const { formatAPIError } = useAPIErrorHandler();
865
- const { push } = useHistory();
866
- const [releaseModalShown, setReleaseModalShown] = React.useState(false);
867
- const [showWarningSubmit, setWarningSubmit] = React.useState(false);
868
- const {
869
- isLoading: isLoadingDetails,
870
- data,
871
- isSuccess: isSuccessDetails
872
- } = useGetReleaseQuery({ id: releaseId });
873
- const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();
874
- const [deleteRelease, { isLoading: isDeletingRelease }] = useDeleteReleaseMutation();
875
- const toggleEditReleaseModal = () => {
876
- setReleaseModalShown((prev) => !prev);
877
- };
878
- const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);
879
- if (isLoadingDetails) {
880
- return /* @__PURE__ */ jsx(
881
- ReleaseDetailsLayout,
882
- {
883
- toggleEditReleaseModal,
884
- toggleWarningSubmit,
885
- children: /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) })
886
- }
887
- );
888
- }
889
- const releaseData = isSuccessDetails && data?.data || null;
890
- const title = releaseData?.name || "";
891
- const timezone = releaseData?.timezone ?? null;
892
- const scheduledAt = releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;
893
- const date = scheduledAt ? new Date(format(scheduledAt, "yyyy-MM-dd")) : null;
894
- const time = scheduledAt ? format(scheduledAt, "HH:mm") : "";
895
- const handleEditRelease = async (values) => {
896
- const response = await updateRelease({
897
- id: releaseId,
898
- name: values.name,
899
- scheduledAt: values.scheduledAt,
900
- timezone: values.timezone
901
- });
902
- if ("data" in response) {
903
- toggleNotification({
904
- type: "success",
905
- message: formatMessage({
906
- id: "content-releases.modal.release-updated-notification-success",
907
- defaultMessage: "Release updated."
908
- })
909
- });
910
- } else if (isAxiosError(response.error)) {
911
- toggleNotification({
912
- type: "warning",
913
- message: formatAPIError(response.error)
914
- });
915
- } else {
916
- toggleNotification({
917
- type: "warning",
918
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
919
- });
920
- }
921
- toggleEditReleaseModal();
922
- };
923
- const handleDeleteRelease = async () => {
924
- const response = await deleteRelease({
925
- id: releaseId
926
- });
927
- if ("data" in response) {
928
- push("/plugins/content-releases");
929
- } else if (isAxiosError(response.error)) {
930
- toggleNotification({
931
- type: "warning",
932
- message: formatAPIError(response.error)
933
- });
934
- } else {
935
- toggleNotification({
936
- type: "warning",
937
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
938
- });
939
- }
940
- };
941
- return /* @__PURE__ */ jsxs(
942
- ReleaseDetailsLayout,
943
- {
944
- toggleEditReleaseModal,
945
- toggleWarningSubmit,
946
- children: [
947
- /* @__PURE__ */ jsx(ReleaseDetailsBody, {}),
948
- releaseModalShown && /* @__PURE__ */ jsx(
949
- ReleaseModal,
950
- {
951
- handleClose: toggleEditReleaseModal,
952
- handleSubmit: handleEditRelease,
953
- isLoading: isLoadingDetails || isSubmittingForm,
954
- initialValues: {
955
- name: title || "",
956
- scheduledAt,
957
- date,
958
- time,
959
- isScheduled: Boolean(scheduledAt),
960
- timezone
961
- }
962
- }
963
- ),
964
- /* @__PURE__ */ jsx(
965
- ConfirmDialog,
966
- {
967
- bodyText: {
968
- id: "content-releases.dialog.confirmation-message",
969
- defaultMessage: "Are you sure you want to delete this release?"
970
- },
971
- isOpen: showWarningSubmit,
972
- isConfirmButtonLoading: isDeletingRelease,
973
- onToggleDialog: toggleWarningSubmit,
974
- onConfirm: handleDeleteRelease
975
- }
976
- )
977
- ]
978
- }
979
- );
980
- };
981
- const LinkCard = styled(Link$2)`
982
- display: block;
983
- `;
984
- const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
985
- const { formatMessage } = useIntl();
986
- if (isError) {
987
- return /* @__PURE__ */ jsx(AnErrorOccurred, {});
988
- }
989
- if (releases?.length === 0) {
990
- return /* @__PURE__ */ jsx(
991
- EmptyStateLayout,
992
- {
993
- content: formatMessage(
994
- {
995
- id: "content-releases.page.Releases.tab.emptyEntries",
996
- defaultMessage: "No releases"
997
- },
998
- {
999
- target: sectionTitle
1000
- }
1001
- ),
1002
- icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem" })
1003
- }
1004
- );
1005
- }
1006
- return /* @__PURE__ */ jsx(Grid, { gap: 4, children: releases.map(({ id, name, actions }) => /* @__PURE__ */ jsx(GridItem, { col: 3, s: 6, xs: 12, children: /* @__PURE__ */ jsx(LinkCard, { href: `content-releases/${id}`, isExternal: false, children: /* @__PURE__ */ jsxs(
1007
- Flex,
1008
- {
1009
- direction: "column",
1010
- justifyContent: "space-between",
1011
- padding: 4,
1012
- hasRadius: true,
1013
- background: "neutral0",
1014
- shadow: "tableShadow",
1015
- height: "100%",
1016
- width: "100%",
1017
- alignItems: "start",
1018
- gap: 2,
1019
- children: [
1020
- /* @__PURE__ */ jsx(Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
1021
- /* @__PURE__ */ jsx(Typography, { variant: "pi", children: formatMessage(
1022
- {
1023
- id: "content-releases.page.Releases.release-item.entries",
1024
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
1025
- },
1026
- { number: actions.meta.count }
1027
- ) })
1028
- ]
1029
- }
1030
- ) }) }, id)) });
1031
- };
1032
- const StyledAlert = styled(Alert)`
1033
- button {
1034
- display: none;
1035
- }
1036
- p + div {
1037
- margin-left: auto;
1038
- }
1039
- `;
1040
- const INITIAL_FORM_VALUES = {
1041
- name: "",
1042
- date: null,
1043
- time: "",
1044
- // Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
1045
- isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
1046
- scheduledAt: null,
1047
- timezone: null
1048
- };
1049
- const ReleasesPage = () => {
1050
- const tabRef = React.useRef(null);
1051
- const location = useLocation();
1052
- const [releaseModalShown, setReleaseModalShown] = React.useState(false);
1053
- const toggleNotification = useNotification();
1200
+ const ReleaseDetailsPage = () => {
1054
1201
  const { formatMessage } = useIntl();
1055
- const { push, replace } = useHistory();
1202
+ const { releaseId } = useParams();
1203
+ const toggleNotification = useNotification();
1056
1204
  const { formatAPIError } = useAPIErrorHandler();
1057
- const [{ query }, setQuery] = useQueryParams();
1058
- const response = useGetReleasesQuery(query);
1059
- const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();
1060
- const { getFeature } = useLicenseLimits();
1061
- const { maximumReleases = 3 } = getFeature("cms-content-releases");
1062
- const { trackUsage } = useTracking();
1063
- const { isLoading, isSuccess, isError } = response;
1064
- const activeTab = response?.currentData?.meta?.activeTab || "pending";
1065
- const activeTabIndex = ["pending", "done"].indexOf(activeTab);
1066
- React.useEffect(() => {
1067
- if (location?.state?.errors) {
1068
- toggleNotification({
1069
- type: "warning",
1070
- title: formatMessage({
1071
- id: "content-releases.pages.Releases.notification.error.title",
1072
- defaultMessage: "Your request could not be processed."
1073
- }),
1074
- message: formatMessage({
1075
- id: "content-releases.pages.Releases.notification.error.message",
1076
- defaultMessage: "Please try again or open another release."
1077
- })
1078
- });
1079
- replace({ state: null });
1080
- }
1081
- }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
1082
- React.useEffect(() => {
1083
- if (tabRef.current) {
1084
- tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
1085
- }
1086
- }, [activeTabIndex]);
1087
- 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 = () => {
1088
1216
  setReleaseModalShown((prev) => !prev);
1089
1217
  };
1090
- if (isLoading) {
1091
- return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
1092
- }
1093
- const totalReleases = isSuccess && response.currentData?.meta?.pagination?.total || 0;
1094
- const hasReachedMaximumPendingReleases = totalReleases >= maximumReleases;
1095
- const handleTabChange = (index) => {
1096
- setQuery({
1097
- ...query,
1098
- page: 1,
1099
- pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
1100
- filters: {
1101
- releasedAt: {
1102
- $notNull: index === 0 ? false : true
1103
- }
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, {}) })
1104
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
1105
1241
  });
1106
- };
1107
- const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
1108
- const response2 = await createRelease({
1109
- name,
1110
- scheduledAt,
1111
- timezone
1112
- });
1113
- if ("data" in response2) {
1242
+ if ("data" in response) {
1114
1243
  toggleNotification({
1115
1244
  type: "success",
1116
1245
  message: formatMessage({
1117
- id: "content-releases.modal.release-created-notification-success",
1118
- defaultMessage: "Release created."
1246
+ id: "content-releases.modal.release-updated-notification-success",
1247
+ defaultMessage: "Release updated."
1119
1248
  })
1120
1249
  });
1121
- trackUsage("didCreateRelease");
1122
- push(`/plugins/content-releases/${response2.data.data.id}`);
1123
- } else if (isAxiosError(response2.error)) {
1250
+ toggleEditReleaseModal();
1251
+ } else if (isAxiosError(response.error)) {
1124
1252
  toggleNotification({
1125
1253
  type: "warning",
1126
- message: formatAPIError(response2.error)
1254
+ message: formatAPIError(response.error)
1127
1255
  });
1128
1256
  } else {
1129
1257
  toggleNotification({
@@ -1132,134 +1260,63 @@ const ReleasesPage = () => {
1132
1260
  });
1133
1261
  }
1134
1262
  };
1135
- return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoading, children: [
1136
- /* @__PURE__ */ jsx(
1137
- HeaderLayout,
1138
- {
1139
- title: formatMessage({
1140
- id: "content-releases.pages.Releases.title",
1141
- defaultMessage: "Releases"
1142
- }),
1143
- subtitle: formatMessage(
1144
- {
1145
- id: "content-releases.pages.Releases.header-subtitle",
1146
- defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
1147
- },
1148
- { number: totalReleases }
1149
- ),
1150
- primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(
1151
- Button,
1152
- {
1153
- startIcon: /* @__PURE__ */ jsx(Plus, {}),
1154
- onClick: toggleAddReleaseModal,
1155
- disabled: hasReachedMaximumPendingReleases,
1156
- children: formatMessage({
1157
- id: "content-releases.header.actions.add-release",
1158
- defaultMessage: "New release"
1159
- })
1160
- }
1161
- ) })
1162
- }
1163
- ),
1164
- /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
1165
- activeTab === "pending" && hasReachedMaximumPendingReleases && /* @__PURE__ */ jsx(
1166
- StyledAlert,
1167
- {
1168
- marginBottom: 6,
1169
- action: /* @__PURE__ */ jsx(Link$2, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
1170
- id: "content-releases.pages.Releases.max-limit-reached.action",
1171
- defaultMessage: "Explore plans"
1172
- }) }),
1173
- title: formatMessage(
1174
- {
1175
- id: "content-releases.pages.Releases.max-limit-reached.title",
1176
- defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
1177
- },
1178
- { number: maximumReleases }
1179
- ),
1180
- onClose: () => {
1181
- },
1182
- closeLabel: "",
1183
- children: formatMessage({
1184
- id: "content-releases.pages.Releases.max-limit-reached.message",
1185
- defaultMessage: "Upgrade to manage an unlimited number of releases."
1186
- })
1187
- }
1188
- ),
1189
- /* @__PURE__ */ jsxs(
1190
- TabGroup,
1191
- {
1192
- label: formatMessage({
1193
- id: "content-releases.pages.Releases.tab-group.label",
1194
- defaultMessage: "Releases list"
1195
- }),
1196
- variant: "simple",
1197
- initialSelectedTabIndex: activeTabIndex,
1198
- onTabChange: handleTabChange,
1199
- ref: tabRef,
1200
- children: [
1201
- /* @__PURE__ */ jsxs(Box, { paddingBottom: 8, children: [
1202
- /* @__PURE__ */ jsxs(Tabs, { children: [
1203
- /* @__PURE__ */ jsx(Tab, { children: formatMessage({
1204
- id: "content-releases.pages.Releases.tab.pending",
1205
- defaultMessage: "Pending"
1206
- }) }),
1207
- /* @__PURE__ */ jsx(Tab, { children: formatMessage({
1208
- id: "content-releases.pages.Releases.tab.done",
1209
- defaultMessage: "Done"
1210
- }) })
1211
- ] }),
1212
- /* @__PURE__ */ jsx(Divider, {})
1213
- ] }),
1214
- /* @__PURE__ */ jsxs(TabPanels, { children: [
1215
- /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
1216
- ReleasesGrid,
1217
- {
1218
- sectionTitle: "pending",
1219
- releases: response?.currentData?.data,
1220
- isError
1221
- }
1222
- ) }),
1223
- /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
1224
- ReleasesGrid,
1225
- {
1226
- sectionTitle: "done",
1227
- releases: response?.currentData?.data,
1228
- isError
1229
- }
1230
- ) })
1231
- ] })
1232
- ]
1233
- }
1234
- ),
1235
- totalReleases > 0 && /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
1236
- /* @__PURE__ */ jsx(
1237
- 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,
1238
1290
  {
1239
- options: ["8", "16", "32", "64"],
1240
- 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
+ }
1241
1302
  }
1242
1303
  ),
1243
1304
  /* @__PURE__ */ jsx(
1244
- PaginationURLQuery,
1305
+ ConfirmDialog,
1245
1306
  {
1246
- pagination: {
1247
- pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
1248
- }
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
1249
1315
  }
1250
1316
  )
1251
- ] })
1252
- ] }) }),
1253
- releaseModalShown && /* @__PURE__ */ jsx(
1254
- ReleaseModal,
1255
- {
1256
- handleClose: toggleAddReleaseModal,
1257
- handleSubmit: handleAddRelease,
1258
- isLoading: isSubmittingForm,
1259
- initialValues: INITIAL_FORM_VALUES
1260
- }
1261
- )
1262
- ] });
1317
+ ]
1318
+ }
1319
+ );
1263
1320
  };
1264
1321
  const App = () => {
1265
1322
  return /* @__PURE__ */ jsx(CheckPagePermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(Switch, { children: [
@@ -1270,4 +1327,4 @@ const App = () => {
1270
1327
  export {
1271
1328
  App
1272
1329
  };
1273
- //# sourceMappingURL=App-ise7GunC.mjs.map
1330
+ //# sourceMappingURL=App-CRNZU_DZ.mjs.map