@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
@@ -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-Q8Pv7enO.js");
6
+ const index = require("./index-xV3jXcZj.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(
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(
@@ -238,19 +232,11 @@ const ReleaseModal = ({
238
232
  };
239
233
  const getTimezones = (selectedDate) => {
240
234
  const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
241
- const offsetPart = new Intl.DateTimeFormat("en", {
242
- timeZone: timezone,
243
- timeZoneName: "longOffset"
244
- }).formatToParts(selectedDate).find((part) => part.type === "timeZoneName");
245
- const offset = offsetPart ? offsetPart.value : "";
246
- let utcOffset = offset.replace("GMT", "UTC");
247
- if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
248
- utcOffset = `${utcOffset}+00:00`;
249
- }
250
- return { offset: utcOffset, value: `${utcOffset}-${timezone}` };
235
+ const utcOffset = index.getTimezoneOffset(timezone, selectedDate);
236
+ return { offset: utcOffset, value: `${utcOffset}&${timezone}` };
251
237
  });
252
238
  const systemTimezone = timezoneList.find(
253
- (timezone) => timezone.value.split("-")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
239
+ (timezone) => timezone.value.split("&")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
254
240
  );
255
241
  return { timezoneList, systemTimezone };
256
242
  };
@@ -262,7 +248,7 @@ const TimezoneComponent = ({ timezoneOptions }) => {
262
248
  if (values.date) {
263
249
  const { timezoneList: timezoneList2 } = getTimezones(new Date(values.date));
264
250
  setTimezoneList(timezoneList2);
265
- 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]);
266
252
  if (updatedTimezone) {
267
253
  setFieldValue("timezone", updatedTimezone.value);
268
254
  }
@@ -275,137 +261,201 @@ const TimezoneComponent = ({ timezoneOptions }) => {
275
261
  id: "content-releases.modal.form.input.label.timezone",
276
262
  defaultMessage: "Timezone"
277
263
  }),
264
+ autocomplete: { type: "list", filter: "contains" },
278
265
  name: "timezone",
279
266
  value: values.timezone || void 0,
280
- textValue: values.timezone ? values.timezone.replace("-", " ") : void 0,
267
+ textValue: values.timezone ? values.timezone.replace(/&/, " ") : void 0,
281
268
  onChange: (timezone) => {
282
269
  setFieldValue("timezone", timezone);
283
270
  },
271
+ onTextValueChange: (timezone) => {
272
+ setFieldValue("timezone", timezone);
273
+ },
284
274
  onClear: () => {
285
275
  setFieldValue("timezone", "");
286
276
  },
287
277
  error: errors.timezone,
288
278
  required: true,
289
- 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))
290
280
  }
291
281
  );
292
282
  };
293
- const ReleaseInfoWrapper = styled__default.default(designSystem.Flex)`
294
- align-self: stretch;
295
- border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
296
- border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
297
- border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
298
- `;
299
- const StyledMenuItem = styled__default.default(v2.Menu.Item)`
300
- svg path {
301
- fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
302
- }
303
- span {
304
- color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
305
- }
283
+ const LinkCard = styled__default.default(v2.Link)`
284
+ display: block;
306
285
  `;
307
- const PencilIcon = styled__default.default(icons.Pencil)`
308
- width: ${({ theme }) => theme.spaces[3]};
309
- height: ${({ theme }) => theme.spaces[3]};
310
- path {
311
- fill: ${({ theme }) => theme.colors.neutral600};
286
+ const RelativeTime = styled__default.default(helperPlugin.RelativeTime)`
287
+ display: inline-block;
288
+ &::first-letter {
289
+ text-transform: uppercase;
312
290
  }
313
291
  `;
314
- const TrashIcon = styled__default.default(icons.Trash)`
315
- width: ${({ theme }) => theme.spaces[3]};
316
- height: ${({ theme }) => theme.spaces[3]};
317
- path {
318
- 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";
319
310
  }
320
- `;
321
- const TypographyMaxWidth = styled__default.default(designSystem.Typography)`
322
- max-width: 300px;
323
- `;
324
- 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 }) => {
325
318
  const { formatMessage } = reactIntl.useIntl();
326
- const { validate } = strapiAdmin.unstable_useDocument();
327
- const { errors } = validate(entry, {
328
- contentType: schema,
329
- components,
330
- isCreatingEntry: false
331
- });
332
- if (Object.keys(errors).length > 0) {
333
- const validationErrorsMessages = Object.entries(errors).map(
334
- ([key, value]) => formatMessage(
335
- { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
336
- { field: key }
337
- )
338
- ).join(" ");
339
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
340
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "danger600", as: icons.CrossCircle }),
341
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
342
- ] });
319
+ if (isError) {
320
+ return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
343
321
  }
344
- if (action == "publish") {
345
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
346
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "success600", as: icons.CheckCircle }),
347
- entry.publishedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
348
- id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
349
- defaultMessage: "Already published"
350
- }) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
351
- id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
352
- defaultMessage: "Ready to publish"
353
- }) })
354
- ] });
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
+ );
355
338
  }
356
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
357
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "success600", as: icons.CheckCircle }),
358
- !entry.publishedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
359
- id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
360
- defaultMessage: "Already unpublished"
361
- }) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
362
- id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish",
363
- defaultMessage: "Ready to unpublish"
364
- }) })
365
- ] });
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)) });
366
364
  };
367
- const ReleaseDetailsLayout = ({
368
- toggleEditReleaseModal,
369
- toggleWarningSubmit,
370
- children
371
- }) => {
372
- const { formatMessage } = reactIntl.useIntl();
373
- const { releaseId } = reactRouterDom.useParams();
374
- const {
375
- data,
376
- isLoading: isLoadingDetails,
377
- isError,
378
- error
379
- } = index.useGetReleaseQuery({ id: releaseId });
380
- 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);
381
385
  const toggleNotification = helperPlugin.useNotification();
386
+ const { formatMessage } = reactIntl.useIntl();
387
+ const { push, replace } = reactRouterDom.useHistory();
382
388
  const { formatAPIError } = helperPlugin.useAPIErrorHandler();
383
- const {
384
- allowedActions: { canUpdate, canDelete }
385
- } = helperPlugin.useRBAC(index.PERMISSIONS);
386
- 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");
387
394
  const { trackUsage } = helperPlugin.useTracking();
388
- const release = data?.data;
389
- const handlePublishRelease = async () => {
390
- const response = await publishRelease({ id: releaseId });
391
- 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) {
392
400
  toggleNotification({
393
- 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
+ }),
394
406
  message: formatMessage({
395
- id: "content-releases.pages.ReleaseDetails.publish-notification-success",
396
- defaultMessage: "Release was published successfully."
407
+ id: "content-releases.pages.Releases.notification.error.message",
408
+ defaultMessage: "Please try again or open another release."
397
409
  })
398
410
  });
399
- const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
400
- trackUsage("didPublishRelease", {
401
- totalEntries: totalEntries2,
402
- totalPublishedEntries,
403
- 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
+ })
404
452
  });
405
- } 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)) {
406
456
  toggleNotification({
407
457
  type: "warning",
408
- message: formatAPIError(response.error)
458
+ message: formatAPIError(response2.error)
409
459
  });
410
460
  } else {
411
461
  toggleNotification({
@@ -414,17 +464,281 @@ const ReleaseDetailsLayout = ({
414
464
  });
415
465
  }
416
466
  };
417
- const handleRefresh = () => {
418
- dispatch(index.releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
419
- };
420
- const getCreatedByUser = () => {
421
- if (!release?.createdBy) {
422
- return null;
423
- }
424
- if (release.createdBy.username) {
425
- return release.createdBy.username;
426
- }
427
- if (release.createdBy.firstname) {
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) {
428
742
  return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
429
743
  }
430
744
  return release.createdBy.email;
@@ -451,18 +765,43 @@ const ReleaseDetailsLayout = ({
451
765
  }
452
766
  const totalEntries = release.actions.meta.count || 0;
453
767
  const hasCreatedByUser = Boolean(getCreatedByUser());
768
+ const isScheduled = release.scheduledAt && release.timezone;
769
+ const numberOfEntriesText = formatMessage(
770
+ {
771
+ id: "content-releases.pages.Details.header-subtitle",
772
+ defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
773
+ },
774
+ { number: totalEntries }
775
+ );
776
+ const scheduledText = isScheduled ? formatMessage(
777
+ {
778
+ id: "content-releases.pages.ReleaseDetails.header-subtitle.scheduled",
779
+ defaultMessage: "Scheduled for {date} at {time} ({offset})"
780
+ },
781
+ {
782
+ date: formatDate(new Date(release.scheduledAt), {
783
+ weekday: "long",
784
+ day: "numeric",
785
+ month: "long",
786
+ year: "numeric",
787
+ timeZone: release.timezone
788
+ }),
789
+ time: formatTime(new Date(release.scheduledAt), {
790
+ timeZone: release.timezone,
791
+ hourCycle: "h23"
792
+ }),
793
+ offset: index.getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
794
+ }
795
+ ) : "";
454
796
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoadingDetails, children: [
455
797
  /* @__PURE__ */ jsxRuntime.jsx(
456
798
  designSystem.HeaderLayout,
457
799
  {
458
800
  title: release.name,
459
- subtitle: formatMessage(
460
- {
461
- id: "content-releases.pages.Details.header-subtitle",
462
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
463
- },
464
- { number: totalEntries }
465
- ),
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
+ ] }),
466
805
  navigationAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
467
806
  id: "global.back",
468
807
  defaultMessage: "Back"
@@ -493,42 +832,28 @@ const ReleaseDetailsLayout = ({
493
832
  padding: 1,
494
833
  width: "100%",
495
834
  children: [
496
- /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxRuntime.jsxs(
497
- designSystem.Flex,
498
- {
499
- paddingTop: 2,
500
- paddingBottom: 2,
501
- alignItems: "center",
502
- gap: 2,
503
- hasRadius: true,
504
- width: "100%",
505
- children: [
506
- /* @__PURE__ */ jsxRuntime.jsx(PencilIcon, {}),
507
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: formatMessage({
508
- id: "content-releases.header.actions.edit",
509
- defaultMessage: "Edit"
510
- }) })
511
- ]
512
- }
513
- ) }),
514
- /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canDelete, onSelect: toggleWarningSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(
515
- 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,
516
844
  {
517
- paddingTop: 2,
518
- paddingBottom: 2,
519
- alignItems: "center",
520
- gap: 2,
521
- hasRadius: true,
522
- width: "100%",
523
- 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: [
524
849
  /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {}),
525
850
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
526
851
  id: "content-releases.header.actions.delete",
527
852
  defaultMessage: "Delete"
528
853
  }) })
529
- ]
854
+ ] })
530
855
  }
531
- ) })
856
+ )
532
857
  ]
533
858
  }
534
859
  ),
@@ -585,6 +910,7 @@ const ReleaseDetailsLayout = ({
585
910
  ] });
586
911
  };
587
912
  const GROUP_BY_OPTIONS = ["contentType", "locale", "action"];
913
+ const GROUP_BY_OPTIONS_NO_LOCALE = ["contentType", "action"];
588
914
  const getGroupByOptionLabel = (value) => {
589
915
  if (value === "locale") {
590
916
  return {
@@ -603,6 +929,21 @@ const getGroupByOptionLabel = (value) => {
603
929
  defaultMessage: "Content-Types"
604
930
  };
605
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
+ ];
606
947
  const ReleaseDetailsBody = () => {
607
948
  const { formatMessage } = reactIntl.useIntl();
608
949
  const { releaseId } = reactRouterDom.useParams();
@@ -618,6 +959,17 @@ const ReleaseDetailsBody = () => {
618
959
  const {
619
960
  allowedActions: { canUpdate }
620
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
+ );
621
973
  const release = releaseData?.data;
622
974
  const selectedGroupBy = query?.groupBy || "contentType";
623
975
  const {
@@ -719,6 +1071,7 @@ const ReleaseDetailsBody = () => {
719
1071
  }
720
1072
  ) });
721
1073
  }
1074
+ const options = hasI18nEnabled ? GROUP_BY_OPTIONS : GROUP_BY_OPTIONS_NO_LOCALE;
722
1075
  return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
723
1076
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
724
1077
  designSystem.SingleSelect,
@@ -738,7 +1091,7 @@ const ReleaseDetailsBody = () => {
738
1091
  ),
739
1092
  value: formatMessage(getGroupByOptionLabel(selectedGroupBy)),
740
1093
  onChange: (value) => setQuery({ groupBy: value }),
741
- 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))
742
1095
  }
743
1096
  ) }),
744
1097
  Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
@@ -755,28 +1108,15 @@ const ReleaseDetailsBody = () => {
755
1108
  isFetching,
756
1109
  children: /* @__PURE__ */ jsxRuntime.jsxs(helperPlugin.Table.Content, { children: [
757
1110
  /* @__PURE__ */ jsxRuntime.jsxs(helperPlugin.Table.Head, { children: [
758
- /* @__PURE__ */ jsxRuntime.jsx(
1111
+ displayedHeaders.map(({ key: key2, fieldSchema, metadatas, name }) => /* @__PURE__ */ jsxRuntime.jsx(
759
1112
  helperPlugin.Table.HeaderCell,
760
1113
  {
761
- fieldSchemaType: "string",
762
- label: formatMessage({
763
- id: "content-releases.page.ReleaseDetails.table.header.label.name",
764
- defaultMessage: "name"
765
- }),
766
- name: "name"
767
- }
768
- ),
769
- /* @__PURE__ */ jsxRuntime.jsx(
770
- helperPlugin.Table.HeaderCell,
771
- {
772
- fieldSchemaType: "string",
773
- label: formatMessage({
774
- id: "content-releases.page.ReleaseDetails.table.header.label.locale",
775
- defaultMessage: "locale"
776
- }),
777
- name: "locale"
778
- }
779
- ),
1114
+ fieldSchemaType: fieldSchema.type,
1115
+ label: formatMessage(metadatas.label),
1116
+ name
1117
+ },
1118
+ key2
1119
+ )),
780
1120
  /* @__PURE__ */ jsxRuntime.jsx(
781
1121
  helperPlugin.Table.HeaderCell,
782
1122
  {
@@ -815,7 +1155,7 @@ const ReleaseDetailsBody = () => {
815
1155
  /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.Body, { children: releaseActions[key].map(
816
1156
  ({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
817
1157
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
818
- /* @__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 : "-"}` }) }),
819
1159
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: contentType.displayName || "" }) }),
820
1160
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage(
821
1161
  {
@@ -884,271 +1224,59 @@ const ReleaseDetailsBody = () => {
884
1224
  };
885
1225
  const ReleaseDetailsPage = () => {
886
1226
  const { formatMessage } = reactIntl.useIntl();
887
- const { releaseId } = reactRouterDom.useParams();
888
- const toggleNotification = helperPlugin.useNotification();
889
- const { formatAPIError } = helperPlugin.useAPIErrorHandler();
890
- const { push } = reactRouterDom.useHistory();
891
- const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
892
- const [showWarningSubmit, setWarningSubmit] = React__namespace.useState(false);
893
- const {
894
- isLoading: isLoadingDetails,
895
- data,
896
- isSuccess: isSuccessDetails
897
- } = index.useGetReleaseQuery({ id: releaseId });
898
- const [updateRelease, { isLoading: isSubmittingForm }] = index.useUpdateReleaseMutation();
899
- const [deleteRelease, { isLoading: isDeletingRelease }] = index.useDeleteReleaseMutation();
900
- const toggleEditReleaseModal = () => {
901
- setReleaseModalShown((prev) => !prev);
902
- };
903
- const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);
904
- if (isLoadingDetails) {
905
- return /* @__PURE__ */ jsxRuntime.jsx(
906
- ReleaseDetailsLayout,
907
- {
908
- toggleEditReleaseModal,
909
- toggleWarningSubmit,
910
- children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) })
911
- }
912
- );
913
- }
914
- const releaseData = isSuccessDetails && data?.data || null;
915
- const title = releaseData?.name || "";
916
- const timezone = releaseData?.timezone ?? null;
917
- const scheduledAt = releaseData?.scheduledAt && timezone ? dateFnsTz.utcToZonedTime(releaseData.scheduledAt, timezone) : null;
918
- const date = scheduledAt ? new Date(format__default.default(scheduledAt, "yyyy-MM-dd")) : null;
919
- const time = scheduledAt ? format__default.default(scheduledAt, "HH:mm") : "";
920
- const handleEditRelease = async (values) => {
921
- const response = await updateRelease({
922
- id: releaseId,
923
- name: values.name,
924
- scheduledAt: values.scheduledAt,
925
- timezone: values.timezone
926
- });
927
- if ("data" in response) {
928
- toggleNotification({
929
- type: "success",
930
- message: formatMessage({
931
- id: "content-releases.modal.release-updated-notification-success",
932
- defaultMessage: "Release updated."
933
- })
934
- });
935
- } else if (index.isAxiosError(response.error)) {
936
- toggleNotification({
937
- type: "warning",
938
- message: formatAPIError(response.error)
939
- });
940
- } else {
941
- toggleNotification({
942
- type: "warning",
943
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
944
- });
945
- }
946
- toggleEditReleaseModal();
947
- };
948
- const handleDeleteRelease = async () => {
949
- const response = await deleteRelease({
950
- id: releaseId
951
- });
952
- if ("data" in response) {
953
- push("/plugins/content-releases");
954
- } else if (index.isAxiosError(response.error)) {
955
- toggleNotification({
956
- type: "warning",
957
- message: formatAPIError(response.error)
958
- });
959
- } else {
960
- toggleNotification({
961
- type: "warning",
962
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
963
- });
964
- }
965
- };
966
- return /* @__PURE__ */ jsxRuntime.jsxs(
967
- ReleaseDetailsLayout,
968
- {
969
- toggleEditReleaseModal,
970
- toggleWarningSubmit,
971
- children: [
972
- /* @__PURE__ */ jsxRuntime.jsx(ReleaseDetailsBody, {}),
973
- releaseModalShown && /* @__PURE__ */ jsxRuntime.jsx(
974
- ReleaseModal,
975
- {
976
- handleClose: toggleEditReleaseModal,
977
- handleSubmit: handleEditRelease,
978
- isLoading: isLoadingDetails || isSubmittingForm,
979
- initialValues: {
980
- name: title || "",
981
- scheduledAt,
982
- date,
983
- time,
984
- isScheduled: Boolean(scheduledAt),
985
- timezone
986
- }
987
- }
988
- ),
989
- /* @__PURE__ */ jsxRuntime.jsx(
990
- helperPlugin.ConfirmDialog,
991
- {
992
- bodyText: {
993
- id: "content-releases.dialog.confirmation-message",
994
- defaultMessage: "Are you sure you want to delete this release?"
995
- },
996
- isOpen: showWarningSubmit,
997
- isConfirmButtonLoading: isDeletingRelease,
998
- onToggleDialog: toggleWarningSubmit,
999
- onConfirm: handleDeleteRelease
1000
- }
1001
- )
1002
- ]
1003
- }
1004
- );
1005
- };
1006
- const LinkCard = styled__default.default(v2.Link)`
1007
- display: block;
1008
- `;
1009
- const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
1010
- const { formatMessage } = reactIntl.useIntl();
1011
- if (isError) {
1012
- return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
1013
- }
1014
- if (releases?.length === 0) {
1015
- return /* @__PURE__ */ jsxRuntime.jsx(
1016
- designSystem.EmptyStateLayout,
1017
- {
1018
- content: formatMessage(
1019
- {
1020
- id: "content-releases.page.Releases.tab.emptyEntries",
1021
- defaultMessage: "No releases"
1022
- },
1023
- {
1024
- target: sectionTitle
1025
- }
1026
- ),
1027
- icon: /* @__PURE__ */ jsxRuntime.jsx(icons.EmptyDocuments, { width: "10rem" })
1028
- }
1029
- );
1030
- }
1031
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid, { gap: 4, children: releases.map(({ id, name, actions }) => /* @__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(
1032
- designSystem.Flex,
1033
- {
1034
- direction: "column",
1035
- justifyContent: "space-between",
1036
- padding: 4,
1037
- hasRadius: true,
1038
- background: "neutral0",
1039
- shadow: "tableShadow",
1040
- height: "100%",
1041
- width: "100%",
1042
- alignItems: "start",
1043
- gap: 2,
1044
- children: [
1045
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
1046
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", children: formatMessage(
1047
- {
1048
- id: "content-releases.page.Releases.release-item.entries",
1049
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
1050
- },
1051
- { number: actions.meta.count }
1052
- ) })
1053
- ]
1054
- }
1055
- ) }) }, id)) });
1056
- };
1057
- const StyledAlert = styled__default.default(designSystem.Alert)`
1058
- button {
1059
- display: none;
1060
- }
1061
- p + div {
1062
- margin-left: auto;
1063
- }
1064
- `;
1065
- const INITIAL_FORM_VALUES = {
1066
- name: "",
1067
- date: null,
1068
- time: "",
1069
- // Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
1070
- isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
1071
- scheduledAt: null,
1072
- timezone: null
1073
- };
1074
- const ReleasesPage = () => {
1075
- const tabRef = React__namespace.useRef(null);
1076
- const location = reactRouterDom.useLocation();
1077
- const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
1078
- const toggleNotification = helperPlugin.useNotification();
1079
- const { formatMessage } = reactIntl.useIntl();
1080
- const { push, replace } = reactRouterDom.useHistory();
1227
+ const { releaseId } = reactRouterDom.useParams();
1228
+ const toggleNotification = helperPlugin.useNotification();
1081
1229
  const { formatAPIError } = helperPlugin.useAPIErrorHandler();
1082
- const [{ query }, setQuery] = helperPlugin.useQueryParams();
1083
- const response = index.useGetReleasesQuery(query);
1084
- const [createRelease, { isLoading: isSubmittingForm }] = index.useCreateReleaseMutation();
1085
- const { getFeature } = strapiAdmin.useLicenseLimits();
1086
- const { maximumReleases = 3 } = getFeature("cms-content-releases");
1087
- const { trackUsage } = helperPlugin.useTracking();
1088
- const { isLoading, isSuccess, isError } = response;
1089
- const activeTab = response?.currentData?.meta?.activeTab || "pending";
1090
- const activeTabIndex = ["pending", "done"].indexOf(activeTab);
1091
- React__namespace.useEffect(() => {
1092
- if (location?.state?.errors) {
1093
- toggleNotification({
1094
- type: "warning",
1095
- title: formatMessage({
1096
- id: "content-releases.pages.Releases.notification.error.title",
1097
- defaultMessage: "Your request could not be processed."
1098
- }),
1099
- message: formatMessage({
1100
- id: "content-releases.pages.Releases.notification.error.message",
1101
- defaultMessage: "Please try again or open another release."
1102
- })
1103
- });
1104
- replace({ state: null });
1105
- }
1106
- }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
1107
- React__namespace.useEffect(() => {
1108
- if (tabRef.current) {
1109
- tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
1110
- }
1111
- }, [activeTabIndex]);
1112
- 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 = () => {
1113
1241
  setReleaseModalShown((prev) => !prev);
1114
1242
  };
1115
- if (isLoading) {
1116
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
1117
- }
1118
- const totalReleases = isSuccess && response.currentData?.meta?.pagination?.total || 0;
1119
- const hasReachedMaximumPendingReleases = totalReleases >= maximumReleases;
1120
- const handleTabChange = (index2) => {
1121
- setQuery({
1122
- ...query,
1123
- page: 1,
1124
- pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
1125
- filters: {
1126
- releasedAt: {
1127
- $notNull: index2 === 0 ? false : true
1128
- }
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, {}) })
1129
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
1130
1266
  });
1131
- };
1132
- const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
1133
- const response2 = await createRelease({
1134
- name,
1135
- scheduledAt,
1136
- timezone
1137
- });
1138
- if ("data" in response2) {
1267
+ if ("data" in response) {
1139
1268
  toggleNotification({
1140
1269
  type: "success",
1141
1270
  message: formatMessage({
1142
- id: "content-releases.modal.release-created-notification-success",
1143
- defaultMessage: "Release created."
1271
+ id: "content-releases.modal.release-updated-notification-success",
1272
+ defaultMessage: "Release updated."
1144
1273
  })
1145
1274
  });
1146
- trackUsage("didCreateRelease");
1147
- push(`/plugins/content-releases/${response2.data.data.id}`);
1148
- } else if (index.isAxiosError(response2.error)) {
1275
+ toggleEditReleaseModal();
1276
+ } else if (index.isAxiosError(response.error)) {
1149
1277
  toggleNotification({
1150
1278
  type: "warning",
1151
- message: formatAPIError(response2.error)
1279
+ message: formatAPIError(response.error)
1152
1280
  });
1153
1281
  } else {
1154
1282
  toggleNotification({
@@ -1157,134 +1285,63 @@ const ReleasesPage = () => {
1157
1285
  });
1158
1286
  }
1159
1287
  };
1160
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
1161
- /* @__PURE__ */ jsxRuntime.jsx(
1162
- designSystem.HeaderLayout,
1163
- {
1164
- title: formatMessage({
1165
- id: "content-releases.pages.Releases.title",
1166
- defaultMessage: "Releases"
1167
- }),
1168
- subtitle: formatMessage(
1169
- {
1170
- id: "content-releases.pages.Releases.header-subtitle",
1171
- defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
1172
- },
1173
- { number: totalReleases }
1174
- ),
1175
- primaryAction: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.create, children: /* @__PURE__ */ jsxRuntime.jsx(
1176
- designSystem.Button,
1177
- {
1178
- startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
1179
- onClick: toggleAddReleaseModal,
1180
- disabled: hasReachedMaximumPendingReleases,
1181
- children: formatMessage({
1182
- id: "content-releases.header.actions.add-release",
1183
- defaultMessage: "New release"
1184
- })
1185
- }
1186
- ) })
1187
- }
1188
- ),
1189
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1190
- activeTab === "pending" && hasReachedMaximumPendingReleases && /* @__PURE__ */ jsxRuntime.jsx(
1191
- StyledAlert,
1192
- {
1193
- marginBottom: 6,
1194
- action: /* @__PURE__ */ jsxRuntime.jsx(v2.Link, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
1195
- id: "content-releases.pages.Releases.max-limit-reached.action",
1196
- defaultMessage: "Explore plans"
1197
- }) }),
1198
- title: formatMessage(
1199
- {
1200
- id: "content-releases.pages.Releases.max-limit-reached.title",
1201
- defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
1202
- },
1203
- { number: maximumReleases }
1204
- ),
1205
- onClose: () => {
1206
- },
1207
- closeLabel: "",
1208
- children: formatMessage({
1209
- id: "content-releases.pages.Releases.max-limit-reached.message",
1210
- defaultMessage: "Upgrade to manage an unlimited number of releases."
1211
- })
1212
- }
1213
- ),
1214
- /* @__PURE__ */ jsxRuntime.jsxs(
1215
- designSystem.TabGroup,
1216
- {
1217
- label: formatMessage({
1218
- id: "content-releases.pages.Releases.tab-group.label",
1219
- defaultMessage: "Releases list"
1220
- }),
1221
- variant: "simple",
1222
- initialSelectedTabIndex: activeTabIndex,
1223
- onTabChange: handleTabChange,
1224
- ref: tabRef,
1225
- children: [
1226
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingBottom: 8, children: [
1227
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs, { children: [
1228
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage({
1229
- id: "content-releases.pages.Releases.tab.pending",
1230
- defaultMessage: "Pending"
1231
- }) }),
1232
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage({
1233
- id: "content-releases.pages.Releases.tab.done",
1234
- defaultMessage: "Done"
1235
- }) })
1236
- ] }),
1237
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {})
1238
- ] }),
1239
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.TabPanels, { children: [
1240
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
1241
- ReleasesGrid,
1242
- {
1243
- sectionTitle: "pending",
1244
- releases: response?.currentData?.data,
1245
- isError
1246
- }
1247
- ) }),
1248
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
1249
- ReleasesGrid,
1250
- {
1251
- sectionTitle: "done",
1252
- releases: response?.currentData?.data,
1253
- isError
1254
- }
1255
- ) })
1256
- ] })
1257
- ]
1258
- }
1259
- ),
1260
- totalReleases > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
1261
- /* @__PURE__ */ jsxRuntime.jsx(
1262
- 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,
1263
1315
  {
1264
- options: ["8", "16", "32", "64"],
1265
- 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
+ }
1266
1327
  }
1267
1328
  ),
1268
1329
  /* @__PURE__ */ jsxRuntime.jsx(
1269
- helperPlugin.PaginationURLQuery,
1330
+ helperPlugin.ConfirmDialog,
1270
1331
  {
1271
- pagination: {
1272
- pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
1273
- }
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
1274
1340
  }
1275
1341
  )
1276
- ] })
1277
- ] }) }),
1278
- releaseModalShown && /* @__PURE__ */ jsxRuntime.jsx(
1279
- ReleaseModal,
1280
- {
1281
- handleClose: toggleAddReleaseModal,
1282
- handleSubmit: handleAddRelease,
1283
- isLoading: isSubmittingForm,
1284
- initialValues: INITIAL_FORM_VALUES
1285
- }
1286
- )
1287
- ] });
1342
+ ]
1343
+ }
1344
+ );
1288
1345
  };
1289
1346
  const App = () => {
1290
1347
  return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPagePermissions, { permissions: index.PERMISSIONS.main, children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Switch, { children: [
@@ -1293,4 +1350,4 @@ const App = () => {
1293
1350
  ] }) });
1294
1351
  };
1295
1352
  exports.App = App;
1296
- //# sourceMappingURL=App-w2Zq-wj5.js.map
1353
+ //# sourceMappingURL=App--3HPsVgM.js.map