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