@strapi/content-releases 0.0.0-next.583e758623dc82206a4b2758d01dd5948b6e3f6a → 0.0.0-next.5ab818b8ee36a4f090027477a602736c6adbd1a4

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-P1kyM3gT.js → App-OP70yd5M.js} +112 -118
  2. package/dist/_chunks/App-OP70yd5M.js.map +1 -0
  3. package/dist/_chunks/{App-6ugQxqYE.mjs → App-x6Tjj3HN.mjs} +116 -122
  4. package/dist/_chunks/App-x6Tjj3HN.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-gcJJ5htG.js → en-3SGjiVyR.js} +10 -3
  10. package/dist/_chunks/en-3SGjiVyR.js.map +1 -0
  11. package/dist/_chunks/{en-WuuhP6Bn.mjs → en-bpHsnU0n.mjs} +10 -3
  12. package/dist/_chunks/en-bpHsnU0n.mjs.map +1 -0
  13. package/dist/_chunks/{index-_eBuegHN.mjs → index-1ejXLtzt.mjs} +201 -11
  14. package/dist/_chunks/index-1ejXLtzt.mjs.map +1 -0
  15. package/dist/_chunks/{index-2xzbhaQP.js → index-ydocdaZ0.js} +200 -10
  16. package/dist/_chunks/index-ydocdaZ0.js.map +1 -0
  17. package/dist/admin/index.js +1 -1
  18. package/dist/admin/index.mjs +1 -1
  19. package/dist/server/index.js +264 -154
  20. package/dist/server/index.js.map +1 -1
  21. package/dist/server/index.mjs +264 -154
  22. package/dist/server/index.mjs.map +1 -1
  23. package/package.json +10 -10
  24. package/dist/_chunks/App-6ugQxqYE.mjs.map +0 -1
  25. package/dist/_chunks/App-P1kyM3gT.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-WuuhP6Bn.mjs.map +0 -1
  29. package/dist/_chunks/en-gcJJ5htG.js.map +0 -1
  30. package/dist/_chunks/index-2xzbhaQP.js.map +0 -1
  31. package/dist/_chunks/index-_eBuegHN.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-2xzbhaQP.js");
6
+ const index = require("./index-ydocdaZ0.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,9 +261,10 @@ 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
  },
@@ -281,15 +276,18 @@ const TimezoneComponent = ({ timezoneOptions }) => {
281
276
  },
282
277
  error: errors.timezone,
283
278
  required: true,
284
- 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))
285
280
  }
286
281
  );
287
282
  };
288
283
  const LinkCard = styled__default.default(v2.Link)`
289
284
  display: block;
290
285
  `;
291
- const CapitalizeRelativeTime = styled__default.default(helperPlugin.RelativeTime)`
292
- text-transform: capitalize;
286
+ const RelativeTime = styled__default.default(helperPlugin.RelativeTime)`
287
+ display: inline-block;
288
+ &::first-letter {
289
+ text-transform: uppercase;
290
+ }
293
291
  `;
294
292
  const getBadgeProps = (status) => {
295
293
  let color;
@@ -318,7 +316,6 @@ const getBadgeProps = (status) => {
318
316
  };
319
317
  const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
320
318
  const { formatMessage } = reactIntl.useIntl();
321
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
322
319
  if (isError) {
323
320
  return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
324
321
  }
@@ -339,7 +336,7 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
339
336
  }
340
337
  );
341
338
  }
342
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid, { gap: 4, children: releases.map(({ id, name, actions, 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(
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(
343
340
  designSystem.Flex,
344
341
  {
345
342
  direction: "column",
@@ -355,16 +352,10 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
355
352
  children: [
356
353
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "start", gap: 1, children: [
357
354
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
358
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: IsSchedulingEnabled ? scheduledAt ? /* @__PURE__ */ jsxRuntime.jsx(CapitalizeRelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
355
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: scheduledAt ? /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
359
356
  id: "content-releases.pages.Releases.not-scheduled",
360
357
  defaultMessage: "Not scheduled"
361
- }) : formatMessage(
362
- {
363
- id: "content-releases.page.Releases.release-item.entries",
364
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
365
- },
366
- { number: actions.meta.count }
367
- ) })
358
+ }) })
368
359
  ] }),
369
360
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { ...getBadgeProps(status), children: status })
370
361
  ]
@@ -383,8 +374,7 @@ const INITIAL_FORM_VALUES = {
383
374
  name: "",
384
375
  date: null,
385
376
  time: "",
386
- // Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
387
- isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
377
+ isScheduled: true,
388
378
  scheduledAt: null,
389
379
  timezone: null
390
380
  };
@@ -734,7 +724,12 @@ const ReleaseDetailsLayout = ({
734
724
  }
735
725
  };
736
726
  const handleRefresh = () => {
737
- dispatch(index.releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
727
+ dispatch(
728
+ index.releaseApi.util.invalidateTags([
729
+ { type: "ReleaseAction", id: "LIST" },
730
+ { type: "Release", id: releaseId }
731
+ ])
732
+ );
738
733
  };
739
734
  const getCreatedByUser = () => {
740
735
  if (!release?.createdBy) {
@@ -770,7 +765,6 @@ const ReleaseDetailsLayout = ({
770
765
  }
771
766
  const totalEntries = release.actions.meta.count || 0;
772
767
  const hasCreatedByUser = Boolean(getCreatedByUser());
773
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
774
768
  const isScheduled = release.scheduledAt && release.timezone;
775
769
  const numberOfEntriesText = formatMessage(
776
770
  {
@@ -805,7 +799,7 @@ const ReleaseDetailsLayout = ({
805
799
  {
806
800
  title: release.name,
807
801
  subtitle: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, lineHeight: 6, children: [
808
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", variant: "epsilon", children: numberOfEntriesText + (IsSchedulingEnabled && isScheduled ? ` - ${scheduledText}` : "") }),
802
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", variant: "epsilon", children: numberOfEntriesText + (isScheduled ? ` - ${scheduledText}` : "") }),
809
803
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { ...getBadgeProps(release.status), children: release.status })
810
804
  ] }),
811
805
  navigationAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
@@ -1218,7 +1212,7 @@ const ReleaseDetailsPage = () => {
1218
1212
  const { releaseId } = reactRouterDom.useParams();
1219
1213
  const toggleNotification = helperPlugin.useNotification();
1220
1214
  const { formatAPIError } = helperPlugin.useAPIErrorHandler();
1221
- const { push } = reactRouterDom.useHistory();
1215
+ const { replace } = reactRouterDom.useHistory();
1222
1216
  const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
1223
1217
  const [showWarningSubmit, setWarningSubmit] = React__namespace.useState(false);
1224
1218
  const {
@@ -1246,7 +1240,7 @@ const ReleaseDetailsPage = () => {
1246
1240
  const title = releaseData?.name || "";
1247
1241
  const timezone = releaseData?.timezone ?? null;
1248
1242
  const scheduledAt = releaseData?.scheduledAt && timezone ? dateFnsTz.utcToZonedTime(releaseData.scheduledAt, timezone) : null;
1249
- const date = scheduledAt ? new Date(format__default.default(scheduledAt, "yyyy-MM-dd")) : null;
1243
+ const date = scheduledAt ? format__default.default(scheduledAt, "yyyy-MM-dd") : null;
1250
1244
  const time = scheduledAt ? format__default.default(scheduledAt, "HH:mm") : "";
1251
1245
  const handleEditRelease = async (values) => {
1252
1246
  const response = await updateRelease({
@@ -1263,6 +1257,7 @@ const ReleaseDetailsPage = () => {
1263
1257
  defaultMessage: "Release updated."
1264
1258
  })
1265
1259
  });
1260
+ toggleEditReleaseModal();
1266
1261
  } else if (index.isAxiosError(response.error)) {
1267
1262
  toggleNotification({
1268
1263
  type: "warning",
@@ -1274,14 +1269,13 @@ const ReleaseDetailsPage = () => {
1274
1269
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1275
1270
  });
1276
1271
  }
1277
- toggleEditReleaseModal();
1278
1272
  };
1279
1273
  const handleDeleteRelease = async () => {
1280
1274
  const response = await deleteRelease({
1281
1275
  id: releaseId
1282
1276
  });
1283
1277
  if ("data" in response) {
1284
- push("/plugins/content-releases");
1278
+ replace("/plugins/content-releases");
1285
1279
  } else if (index.isAxiosError(response.error)) {
1286
1280
  toggleNotification({
1287
1281
  type: "warning",
@@ -1341,4 +1335,4 @@ const App = () => {
1341
1335
  ] }) });
1342
1336
  };
1343
1337
  exports.App = App;
1344
- //# sourceMappingURL=App-P1kyM3gT.js.map
1338
+ //# sourceMappingURL=App-OP70yd5M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App-OP70yd5M.js","sources":["../../shared/validation-schemas.ts","../../admin/src/components/ReleaseModal.tsx","../../admin/src/pages/ReleasesPage.tsx","../../admin/src/pages/ReleaseDetailsPage.tsx","../../admin/src/pages/App.tsx"],"sourcesContent":["import * as yup from 'yup';\n\nexport const RELEASE_SCHEMA = yup\n .object()\n .shape({\n name: yup.string().trim().required(),\n scheduledAt: yup.string().nullable(),\n isScheduled: yup.boolean().optional(),\n time: yup.string().when('isScheduled', {\n is: true,\n then: yup.string().trim().required(),\n otherwise: yup.string().nullable(),\n }),\n timezone: yup.string().when('isScheduled', {\n is: true,\n then: yup.string().required().nullable(),\n otherwise: yup.string().nullable(),\n }),\n date: yup.string().when('isScheduled', {\n is: true,\n then: yup.string().required().nullable(),\n otherwise: yup.string().nullable(),\n }),\n })\n .required()\n .noUnknown();\n","import * as React from 'react';\n\nimport {\n Button,\n ModalBody,\n ModalFooter,\n ModalLayout,\n ModalHeader,\n TextInput,\n Typography,\n Checkbox,\n Flex,\n Box,\n DatePicker,\n TimePicker,\n Combobox,\n ComboboxOption,\n} from '@strapi/design-system';\nimport { formatISO } from 'date-fns';\nimport { utcToZonedTime, zonedTimeToUtc } from 'date-fns-tz';\nimport { Formik, Form, useFormikContext } from 'formik';\nimport { useIntl } from 'react-intl';\nimport { useLocation } from 'react-router-dom';\n\nimport { RELEASE_SCHEMA } from '../../../shared/validation-schemas';\nimport { pluginId } from '../pluginId';\nimport { getTimezoneOffset } from '../utils/time';\n\nexport interface FormValues {\n name: string;\n date: string | null;\n time: string;\n timezone: string | null;\n isScheduled?: boolean;\n scheduledAt: Date | null;\n}\n\ninterface ReleaseModalProps {\n handleClose: () => void;\n handleSubmit: (values: FormValues) => void;\n isLoading?: boolean;\n initialValues: FormValues;\n}\n\nexport const ReleaseModal = ({\n handleClose,\n handleSubmit,\n initialValues,\n isLoading = false,\n}: ReleaseModalProps) => {\n const { formatMessage } = useIntl();\n const { pathname } = useLocation();\n const isCreatingRelease = pathname === `/plugins/${pluginId}`;\n // Set default first timezone from the list if no system timezone detected\n const { timezoneList, systemTimezone = { value: 'UTC+00:00-Africa/Abidjan ' } } = getTimezones(\n initialValues.scheduledAt ? new Date(initialValues.scheduledAt) : new Date()\n );\n\n /**\n * Generate scheduled time using selected date, time and timezone\n */\n const getScheduledTimestamp = (values: FormValues) => {\n const { date, time, timezone } = values;\n if (!date || !time || !timezone) return null;\n const timezoneWithoutOffset = timezone.split('&')[1];\n return zonedTimeToUtc(`${date} ${time}`, timezoneWithoutOffset);\n };\n\n /**\n * Get timezone with offset to show the selected value in the dropdown\n */\n const getTimezoneWithOffset = () => {\n const currentTimezone = timezoneList.find(\n (timezone) => timezone.value.split('&')[1] === initialValues.timezone\n );\n return currentTimezone?.value || systemTimezone.value;\n };\n\n return (\n <ModalLayout onClose={handleClose} labelledBy=\"title\">\n <ModalHeader>\n <Typography id=\"title\" fontWeight=\"bold\" textColor=\"neutral800\">\n {formatMessage(\n {\n id: 'content-releases.modal.title',\n defaultMessage:\n '{isCreatingRelease, select, true {New release} other {Edit release}}',\n },\n { isCreatingRelease: isCreatingRelease }\n )}\n </Typography>\n </ModalHeader>\n <Formik\n onSubmit={(values) => {\n handleSubmit({\n ...values,\n timezone: values.timezone ? values.timezone.split('&')[1] : null,\n scheduledAt: values.isScheduled ? getScheduledTimestamp(values) : null,\n });\n }}\n initialValues={{\n ...initialValues,\n timezone: initialValues.timezone ? getTimezoneWithOffset() : systemTimezone.value,\n }}\n validationSchema={RELEASE_SCHEMA}\n validateOnChange={false}\n >\n {({ values, errors, handleChange, setFieldValue }) => (\n <Form>\n <ModalBody>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={6}>\n <TextInput\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.release-name',\n defaultMessage: 'Name',\n })}\n name=\"name\"\n value={values.name}\n error={errors.name}\n onChange={handleChange}\n required\n />\n <Box width=\"max-content\">\n <Checkbox\n name=\"isScheduled\"\n value={values.isScheduled}\n onChange={(event) => {\n setFieldValue('isScheduled', event.target.checked);\n if (!event.target.checked) {\n // Clear scheduling info from a release on unchecking schedule release, which reset scheduling info in DB\n setFieldValue('date', null);\n setFieldValue('time', '');\n setFieldValue('timezone', null);\n } else {\n // On ticking back schedule release date, time and timezone should be restored to the initial state\n setFieldValue('date', initialValues.date);\n setFieldValue('time', initialValues.time);\n setFieldValue('timezone', initialValues.timezone ?? systemTimezone?.value);\n }\n }}\n >\n <Typography\n textColor={values.isScheduled ? 'primary600' : 'neutral800'}\n fontWeight={values.isScheduled ? 'semiBold' : 'regular'}\n >\n {formatMessage({\n id: 'modal.form.input.label.schedule-release',\n defaultMessage: 'Schedule release',\n })}\n </Typography>\n </Checkbox>\n </Box>\n {values.isScheduled && (\n <>\n <Flex gap={4} alignItems=\"start\">\n <Box width=\"100%\">\n <DatePicker\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.date',\n defaultMessage: 'Date',\n })}\n name=\"date\"\n error={errors.date}\n onChange={(date) => {\n const isoFormatDate = date\n ? formatISO(date, { representation: 'date' })\n : null;\n setFieldValue('date', isoFormatDate);\n }}\n clearLabel={formatMessage({\n id: 'content-releases.modal.form.input.clearLabel',\n defaultMessage: 'Clear',\n })}\n onClear={() => {\n setFieldValue('date', null);\n }}\n selectedDate={values.date || undefined}\n required\n minDate={utcToZonedTime(new Date(), values.timezone.split('&')[1])}\n />\n </Box>\n <Box width=\"100%\">\n <TimePicker\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.time',\n defaultMessage: 'Time',\n })}\n name=\"time\"\n error={errors.time}\n onChange={(time) => {\n setFieldValue('time', time);\n }}\n clearLabel={formatMessage({\n id: 'content-releases.modal.form.input.clearLabel',\n defaultMessage: 'Clear',\n })}\n onClear={() => {\n setFieldValue('time', '');\n }}\n value={values.time || undefined}\n required\n />\n </Box>\n </Flex>\n <TimezoneComponent timezoneOptions={timezoneList} />\n </>\n )}\n </Flex>\n </ModalBody>\n <ModalFooter\n startActions={\n <Button onClick={handleClose} variant=\"tertiary\" name=\"cancel\">\n {formatMessage({ id: 'cancel', defaultMessage: 'Cancel' })}\n </Button>\n }\n endActions={\n <Button name=\"submit\" loading={isLoading} type=\"submit\">\n {formatMessage(\n {\n id: 'content-releases.modal.form.button.submit',\n defaultMessage: '{isCreatingRelease, select, true {Continue} other {Save}}',\n },\n { isCreatingRelease: isCreatingRelease }\n )}\n </Button>\n }\n />\n </Form>\n )}\n </Formik>\n </ModalLayout>\n );\n};\n\n/**\n * Generates the list of timezones and user's current timezone(system timezone)\n */\ninterface ITimezoneOption {\n offset: string;\n value: string;\n}\n\nconst getTimezones = (selectedDate: Date) => {\n const timezoneList: ITimezoneOption[] = Intl.supportedValuesOf('timeZone').map((timezone) => {\n // Timezone will be in the format GMT${OFFSET} where offset could be nothing,\n // a four digit string e.g. +05:00 or -08:00\n const utcOffset = getTimezoneOffset(timezone, selectedDate);\n\n // Offset and timezone are concatenated with '&', so to split and save the required timezone in DB\n return { offset: utcOffset, value: `${utcOffset}&${timezone}` } satisfies ITimezoneOption;\n });\n\n const systemTimezone = timezoneList.find(\n (timezone) => timezone.value.split('&')[1] === Intl.DateTimeFormat().resolvedOptions().timeZone\n );\n\n return { timezoneList, systemTimezone };\n};\n\nconst TimezoneComponent = ({ timezoneOptions }: { timezoneOptions: ITimezoneOption[] }) => {\n const { values, errors, setFieldValue } = useFormikContext<FormValues>();\n const { formatMessage } = useIntl();\n const [timezoneList, setTimezoneList] = React.useState<ITimezoneOption[]>(timezoneOptions);\n\n React.useEffect(() => {\n if (values.date) {\n // Update the timezone offset which varies with DST based on the date selected\n const { timezoneList } = getTimezones(new Date(values.date));\n setTimezoneList(timezoneList);\n\n const updatedTimezone =\n values.timezone &&\n timezoneList.find((tz) => tz.value.split('&')[1] === values.timezone!.split('&')[1]);\n if (updatedTimezone) {\n setFieldValue('timezone', updatedTimezone!.value);\n }\n }\n }, [setFieldValue, values.date, values.timezone]);\n\n return (\n <Combobox\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.timezone',\n defaultMessage: 'Timezone',\n })}\n autocomplete={{ type: 'list', filter: 'contains' }}\n name=\"timezone\"\n value={values.timezone || undefined}\n textValue={values.timezone ? values.timezone.replace(/&/, ' ') : undefined} // textValue is required to show the updated DST timezone\n onChange={(timezone) => {\n setFieldValue('timezone', timezone);\n }}\n onTextValueChange={(timezone) => {\n setFieldValue('timezone', timezone);\n }}\n onClear={() => {\n setFieldValue('timezone', '');\n }}\n error={errors.timezone}\n required\n >\n {timezoneList.map((timezone) => (\n <ComboboxOption key={timezone.value} value={timezone.value}>\n {timezone.value.replace(/&/, ' ')}\n </ComboboxOption>\n ))}\n </Combobox>\n );\n};\n","import * as React from 'react';\n\n// TODO: Replace this import with the same hook exported from the @strapi/admin/strapi-admin/ee in another iteration of this solution\nimport { useLicenseLimits } from '@strapi/admin/strapi-admin';\nimport {\n Alert,\n Badge,\n Box,\n Button,\n ContentLayout,\n Divider,\n EmptyStateLayout,\n Flex,\n Grid,\n GridItem,\n HeaderLayout,\n Main,\n Tab,\n TabGroup,\n TabPanel,\n TabPanels,\n Tabs,\n Typography,\n} from '@strapi/design-system';\nimport { Link } from '@strapi/design-system/v2';\nimport {\n AnErrorOccurred,\n CheckPermissions,\n LoadingIndicatorPage,\n PageSizeURLQuery,\n PaginationURLQuery,\n useQueryParams,\n useAPIErrorHandler,\n useNotification,\n useTracking,\n RelativeTime as BaseRelativeTime,\n} from '@strapi/helper-plugin';\nimport { EmptyDocuments, Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { useHistory, useLocation } from 'react-router-dom';\nimport styled from 'styled-components';\n\nimport { GetReleases, type Release } from '../../../shared/contracts/releases';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport { isAxiosError } from '../services/axios';\nimport {\n useGetReleasesQuery,\n GetReleasesQueryParams,\n useCreateReleaseMutation,\n} from '../services/release';\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesGrid\n * -----------------------------------------------------------------------------------------------*/\ninterface ReleasesGridProps {\n sectionTitle: 'pending' | 'done';\n releases?: GetReleases.Response['data'];\n isError?: boolean;\n}\n\nconst LinkCard = styled(Link)`\n display: block;\n`;\n\nconst RelativeTime = styled(BaseRelativeTime)`\n display: inline-block;\n &::first-letter {\n text-transform: uppercase;\n }\n`;\n\nconst getBadgeProps = (status: Release['status']) => {\n let color;\n switch (status) {\n case 'ready':\n color = 'success';\n break;\n case 'blocked':\n color = 'warning';\n break;\n case 'failed':\n color = 'danger';\n break;\n case 'done':\n color = 'primary';\n break;\n case 'empty':\n default:\n color = 'neutral';\n }\n\n return {\n textColor: `${color}600`,\n backgroundColor: `${color}100`,\n borderColor: `${color}200`,\n };\n};\n\nconst ReleasesGrid = ({ sectionTitle, releases = [], isError = false }: ReleasesGridProps) => {\n const { formatMessage } = useIntl();\n\n if (isError) {\n return <AnErrorOccurred />;\n }\n\n if (releases?.length === 0) {\n return (\n <EmptyStateLayout\n content={formatMessage(\n {\n id: 'content-releases.page.Releases.tab.emptyEntries',\n defaultMessage: 'No releases',\n },\n {\n target: sectionTitle,\n }\n )}\n icon={<EmptyDocuments width=\"10rem\" />}\n />\n );\n }\n\n return (\n <Grid gap={4}>\n {releases.map(({ id, name, scheduledAt, status }) => (\n <GridItem col={3} s={6} xs={12} key={id}>\n <LinkCard href={`content-releases/${id}`} isExternal={false}>\n <Flex\n direction=\"column\"\n justifyContent=\"space-between\"\n padding={4}\n hasRadius\n background=\"neutral0\"\n shadow=\"tableShadow\"\n height=\"100%\"\n width=\"100%\"\n alignItems=\"start\"\n gap={4}\n >\n <Flex direction=\"column\" alignItems=\"start\" gap={1}>\n <Typography as=\"h3\" variant=\"delta\" fontWeight=\"bold\">\n {name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {scheduledAt ? (\n <RelativeTime timestamp={new Date(scheduledAt)} />\n ) : (\n formatMessage({\n id: 'content-releases.pages.Releases.not-scheduled',\n defaultMessage: 'Not scheduled',\n })\n )}\n </Typography>\n </Flex>\n <Badge {...getBadgeProps(status)}>{status}</Badge>\n </Flex>\n </LinkCard>\n </GridItem>\n ))}\n </Grid>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesPage\n * -----------------------------------------------------------------------------------------------*/\ninterface CustomLocationState {\n errors?: Record<'code', string>[];\n}\n\nconst StyledAlert = styled(Alert)`\n button {\n display: none;\n }\n p + div {\n margin-left: auto;\n }\n`;\n\nconst INITIAL_FORM_VALUES = {\n name: '',\n date: null,\n time: '',\n isScheduled: true,\n scheduledAt: null,\n timezone: null,\n} satisfies FormValues;\n\nconst ReleasesPage = () => {\n const tabRef = React.useRef<any>(null);\n const location = useLocation<CustomLocationState>();\n const [releaseModalShown, setReleaseModalShown] = React.useState(false);\n const toggleNotification = useNotification();\n const { formatMessage } = useIntl();\n const { push, replace } = useHistory();\n const { formatAPIError } = useAPIErrorHandler();\n const [{ query }, setQuery] = useQueryParams<GetReleasesQueryParams>();\n const response = useGetReleasesQuery(query);\n const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();\n const { getFeature } = useLicenseLimits();\n const { maximumReleases = 3 } = getFeature('cms-content-releases') as {\n maximumReleases: number;\n };\n const { trackUsage } = useTracking();\n\n const { isLoading, isSuccess, isError } = response;\n const activeTab = response?.currentData?.meta?.activeTab || 'pending';\n const activeTabIndex = ['pending', 'done'].indexOf(activeTab);\n\n // Check if we have some errors and show a notification to the user to explain the error\n React.useEffect(() => {\n if (location?.state?.errors) {\n toggleNotification({\n type: 'warning',\n title: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.title',\n defaultMessage: 'Your request could not be processed.',\n }),\n message: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.message',\n defaultMessage: 'Please try again or open another release.',\n }),\n });\n replace({ state: null });\n }\n }, [formatMessage, location?.state?.errors, replace, toggleNotification]);\n\n // TODO: Replace this solution with v2 of the Design System\n // Check if the active tab index changes and call the handler of the ref to update the tab group component\n React.useEffect(() => {\n if (tabRef.current) {\n tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);\n }\n }, [activeTabIndex]);\n\n const toggleAddReleaseModal = () => {\n setReleaseModalShown((prev) => !prev);\n };\n\n if (isLoading) {\n return (\n <Main aria-busy={isLoading}>\n <LoadingIndicatorPage />\n </Main>\n );\n }\n\n const totalPendingReleases = (isSuccess && response.currentData?.meta?.pendingReleasesCount) || 0;\n const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;\n\n const handleTabChange = (index: number) => {\n setQuery({\n ...query,\n page: 1,\n pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,\n filters: {\n releasedAt: {\n $notNull: index === 0 ? false : true,\n },\n },\n });\n };\n\n const handleAddRelease = async ({ name, scheduledAt, timezone }: FormValues) => {\n const response = await createRelease({\n name,\n scheduledAt,\n timezone,\n });\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.modal.release-created-notification-success',\n defaultMessage: 'Release created.',\n }),\n });\n\n trackUsage('didCreateRelease');\n\n push(`/plugins/content-releases/${response.data.data.id}`);\n } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n return (\n <Main aria-busy={isLoading}>\n <HeaderLayout\n title={formatMessage({\n id: 'content-releases.pages.Releases.title',\n defaultMessage: 'Releases',\n })}\n subtitle={formatMessage({\n id: 'content-releases.pages.Releases.header-subtitle',\n defaultMessage: 'Create and manage content updates',\n })}\n primaryAction={\n <CheckPermissions permissions={PERMISSIONS.create}>\n <Button\n startIcon={<Plus />}\n onClick={toggleAddReleaseModal}\n disabled={hasReachedMaximumPendingReleases}\n >\n {formatMessage({\n id: 'content-releases.header.actions.add-release',\n defaultMessage: 'New release',\n })}\n </Button>\n </CheckPermissions>\n }\n />\n <ContentLayout>\n <>\n {hasReachedMaximumPendingReleases && (\n <StyledAlert\n marginBottom={6}\n action={\n <Link href=\"https://strapi.io/pricing-cloud\" isExternal>\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.action',\n defaultMessage: 'Explore plans',\n })}\n </Link>\n }\n title={formatMessage(\n {\n id: 'content-releases.pages.Releases.max-limit-reached.title',\n defaultMessage:\n 'You have reached the {number} pending {number, plural, one {release} other {releases}} limit.',\n },\n { number: maximumReleases }\n )}\n onClose={() => {}}\n closeLabel=\"\"\n >\n {formatMessage({\n id: 'content-releases.pages.Releases.max-limit-reached.message',\n defaultMessage: 'Upgrade to manage an unlimited number of releases.',\n })}\n </StyledAlert>\n )}\n <TabGroup\n label={formatMessage({\n id: 'content-releases.pages.Releases.tab-group.label',\n defaultMessage: 'Releases list',\n })}\n variant=\"simple\"\n initialSelectedTabIndex={activeTabIndex}\n onTabChange={handleTabChange}\n ref={tabRef}\n >\n <Box paddingBottom={8}>\n <Tabs>\n <Tab>\n {formatMessage(\n {\n id: 'content-releases.pages.Releases.tab.pending',\n defaultMessage: 'Pending ({count})',\n },\n {\n count: totalPendingReleases,\n }\n )}\n </Tab>\n <Tab>\n {formatMessage({\n id: 'content-releases.pages.Releases.tab.done',\n defaultMessage: 'Done',\n })}\n </Tab>\n </Tabs>\n <Divider />\n </Box>\n <TabPanels>\n {/* Pending releases */}\n <TabPanel>\n <ReleasesGrid\n sectionTitle=\"pending\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </TabPanel>\n {/* Done releases */}\n <TabPanel>\n <ReleasesGrid\n sectionTitle=\"done\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </TabPanel>\n </TabPanels>\n </TabGroup>\n {response.currentData?.meta?.pagination?.total ? (\n <Flex paddingTop={4} alignItems=\"flex-end\" justifyContent=\"space-between\">\n <PageSizeURLQuery\n options={['8', '16', '32', '64']}\n defaultValue={response?.currentData?.meta?.pagination?.pageSize.toString()}\n />\n <PaginationURLQuery\n pagination={{\n pageCount: response?.currentData?.meta?.pagination?.pageCount || 0,\n }}\n />\n </Flex>\n ) : null}\n </>\n </ContentLayout>\n {releaseModalShown && (\n <ReleaseModal\n handleClose={toggleAddReleaseModal}\n handleSubmit={handleAddRelease}\n isLoading={isSubmittingForm}\n initialValues={INITIAL_FORM_VALUES}\n />\n )}\n </Main>\n );\n};\n\nexport { ReleasesPage, getBadgeProps };\n","import * as React from 'react';\n\nimport { unstable_useDocument } from '@strapi/admin/strapi-admin';\nimport {\n Button,\n ContentLayout,\n Flex,\n HeaderLayout,\n IconButton,\n Link,\n Main,\n Tr,\n Td,\n Typography,\n Badge,\n SingleSelect,\n SingleSelectOption,\n Icon,\n Tooltip,\n} from '@strapi/design-system';\nimport { LinkButton, Menu } from '@strapi/design-system/v2';\nimport {\n CheckPermissions,\n LoadingIndicatorPage,\n NoContent,\n PageSizeURLQuery,\n PaginationURLQuery,\n RelativeTime,\n Table,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n ConfirmDialog,\n useRBAC,\n AnErrorOccurred,\n useTracking,\n} from '@strapi/helper-plugin';\nimport { ArrowLeft, CheckCircle, More, Pencil, Trash, CrossCircle } from '@strapi/icons';\nimport format from 'date-fns/format';\nimport { utcToZonedTime } from 'date-fns-tz';\nimport { useIntl } from 'react-intl';\nimport { useParams, useHistory, Link as ReactRouterLink, Redirect } from 'react-router-dom';\nimport styled from 'styled-components';\n\nimport { ReleaseActionMenu } from '../components/ReleaseActionMenu';\nimport { ReleaseActionOptions } from '../components/ReleaseActionOptions';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport { isAxiosError } from '../services/axios';\nimport {\n GetReleaseActionsQueryParams,\n useGetReleaseActionsQuery,\n useGetReleaseQuery,\n useUpdateReleaseMutation,\n useUpdateReleaseActionMutation,\n usePublishReleaseMutation,\n useDeleteReleaseMutation,\n releaseApi,\n} from '../services/release';\nimport { useTypedDispatch } from '../store/hooks';\nimport { getTimezoneOffset } from '../utils/time';\n\nimport { getBadgeProps } from './ReleasesPage';\n\nimport type {\n ReleaseAction,\n ReleaseActionGroupBy,\n ReleaseActionEntry,\n} from '../../../shared/contracts/release-actions';\nimport type { Schema } from '@strapi/types';\n\n/* -------------------------------------------------------------------------------------------------\n * ReleaseDetailsLayout\n * -----------------------------------------------------------------------------------------------*/\nconst ReleaseInfoWrapper = styled(Flex)`\n align-self: stretch;\n border-bottom-right-radius: ${({ theme }) => theme.borderRadius};\n border-bottom-left-radius: ${({ theme }) => theme.borderRadius};\n border-top: 1px solid ${({ theme }) => theme.colors.neutral150};\n`;\n\nconst StyledMenuItem = styled(Menu.Item)<{\n disabled?: boolean;\n variant?: 'neutral' | 'danger';\n}>`\n svg path {\n fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};\n }\n span {\n color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};\n }\n\n &:hover {\n background: ${({ theme, variant = 'neutral' }) => theme.colors[`${variant}100`]};\n }\n`;\n\nconst PencilIcon = styled(Pencil)`\n width: ${({ theme }) => theme.spaces[3]};\n height: ${({ theme }) => theme.spaces[3]};\n path {\n fill: ${({ theme }) => theme.colors.neutral600};\n }\n`;\n\nconst TrashIcon = styled(Trash)`\n width: ${({ theme }) => theme.spaces[3]};\n height: ${({ theme }) => theme.spaces[3]};\n path {\n fill: ${({ theme }) => theme.colors.danger600};\n }\n`;\n\nconst TypographyMaxWidth = styled(Typography)`\n max-width: 300px;\n`;\n\ninterface EntryValidationTextProps {\n action: ReleaseAction['type'];\n schema: Schema.ContentType;\n components: { [key: Schema.Component['uid']]: Schema.Component };\n entry: ReleaseActionEntry;\n}\n\nconst EntryValidationText = ({ action, schema, components, entry }: EntryValidationTextProps) => {\n const { formatMessage } = useIntl();\n const { validate } = unstable_useDocument();\n\n const { errors } = validate(entry, {\n contentType: schema,\n components,\n isCreatingEntry: false,\n });\n\n if (Object.keys(errors).length > 0) {\n const validationErrorsMessages = Object.entries(errors)\n .map(([key, value]) =>\n formatMessage(\n { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },\n { field: key }\n )\n )\n .join(' ');\n\n return (\n <Flex gap={2}>\n <Icon color=\"danger600\" as={CrossCircle} />\n <Tooltip description={validationErrorsMessages}>\n <TypographyMaxWidth textColor=\"danger600\" variant=\"omega\" fontWeight=\"semiBold\" ellipsis>\n {validationErrorsMessages}\n </TypographyMaxWidth>\n </Tooltip>\n </Flex>\n );\n }\n\n if (action == 'publish') {\n return (\n <Flex gap={2}>\n <Icon color=\"success600\" as={CheckCircle} />\n {entry.publishedAt ? (\n <Typography textColor=\"success600\" fontWeight=\"bold\">\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.already-published',\n defaultMessage: 'Already published',\n })}\n </Typography>\n ) : (\n <Typography>\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish',\n defaultMessage: 'Ready to publish',\n })}\n </Typography>\n )}\n </Flex>\n );\n }\n\n return (\n <Flex gap={2}>\n <Icon color=\"success600\" as={CheckCircle} />\n {!entry.publishedAt ? (\n <Typography textColor=\"success600\" fontWeight=\"bold\">\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.already-unpublished',\n defaultMessage: 'Already unpublished',\n })}\n </Typography>\n ) : (\n <Typography>\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish',\n defaultMessage: 'Ready to unpublish',\n })}\n </Typography>\n )}\n </Flex>\n );\n};\ninterface ReleaseDetailsLayoutProps {\n toggleEditReleaseModal: () => void;\n toggleWarningSubmit: () => void;\n children: React.ReactNode;\n}\n\nexport const ReleaseDetailsLayout = ({\n toggleEditReleaseModal,\n toggleWarningSubmit,\n children,\n}: ReleaseDetailsLayoutProps) => {\n const { formatMessage, formatDate, formatTime } = useIntl();\n const { releaseId } = useParams<{ releaseId: string }>();\n const {\n data,\n isLoading: isLoadingDetails,\n isError,\n error,\n } = useGetReleaseQuery({ id: releaseId });\n const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();\n const toggleNotification = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const {\n allowedActions: { canUpdate, canDelete },\n } = useRBAC(PERMISSIONS);\n const dispatch = useTypedDispatch();\n const { trackUsage } = useTracking();\n\n const release = data?.data;\n\n const handlePublishRelease = async () => {\n const response = await publishRelease({ id: releaseId });\n\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.pages.ReleaseDetails.publish-notification-success',\n defaultMessage: 'Release was published successfully.',\n }),\n });\n\n const { totalEntries, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;\n\n trackUsage('didPublishRelease', {\n totalEntries,\n totalPublishedEntries,\n totalUnpublishedEntries,\n });\n } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n const handleRefresh = () => {\n dispatch(\n releaseApi.util.invalidateTags([\n { type: 'ReleaseAction', id: 'LIST' },\n { type: 'Release', id: releaseId },\n ])\n );\n };\n\n const getCreatedByUser = () => {\n if (!release?.createdBy) {\n return null;\n }\n\n // Favor the username\n if (release.createdBy.username) {\n return release.createdBy.username;\n }\n\n // Firstname may not exist if created with SSO\n if (release.createdBy.firstname) {\n return `${release.createdBy.firstname} ${release.createdBy.lastname || ''}`.trim();\n }\n\n // All users must have at least an email\n return release.createdBy.email;\n };\n\n if (isLoadingDetails) {\n return (\n <Main aria-busy={isLoadingDetails}>\n <LoadingIndicatorPage />\n </Main>\n );\n }\n\n if (isError || !release) {\n return (\n <Redirect\n to={{\n pathname: '/plugins/content-releases',\n state: {\n errors: [\n {\n code: error?.code,\n },\n ],\n },\n }}\n />\n );\n }\n\n const totalEntries = release.actions.meta.count || 0;\n const hasCreatedByUser = Boolean(getCreatedByUser());\n\n const isScheduled = release.scheduledAt && release.timezone;\n const numberOfEntriesText = formatMessage(\n {\n id: 'content-releases.pages.Details.header-subtitle',\n defaultMessage: '{number, plural, =0 {No entries} one {# entry} other {# entries}}',\n },\n { number: totalEntries }\n );\n const scheduledText = isScheduled\n ? formatMessage(\n {\n id: 'content-releases.pages.ReleaseDetails.header-subtitle.scheduled',\n defaultMessage: 'Scheduled for {date} at {time} ({offset})',\n },\n {\n date: formatDate(new Date(release.scheduledAt!), {\n weekday: 'long',\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n timeZone: release.timezone!,\n }),\n time: formatTime(new Date(release.scheduledAt!), {\n timeZone: release.timezone!,\n hourCycle: 'h23',\n }),\n offset: getTimezoneOffset(release.timezone!, new Date(release.scheduledAt!)),\n }\n )\n : '';\n\n return (\n <Main aria-busy={isLoadingDetails}>\n <HeaderLayout\n title={release.name}\n subtitle={\n <Flex gap={2} lineHeight={6}>\n <Typography textColor=\"neutral600\" variant=\"epsilon\">\n {numberOfEntriesText + (isScheduled ? ` - ${scheduledText}` : '')}\n </Typography>\n <Badge {...getBadgeProps(release.status)}>{release.status}</Badge>\n </Flex>\n }\n navigationAction={\n <Link startIcon={<ArrowLeft />} to=\"/plugins/content-releases\">\n {formatMessage({\n id: 'global.back',\n defaultMessage: 'Back',\n })}\n </Link>\n }\n primaryAction={\n !release.releasedAt && (\n <Flex gap={2}>\n <Menu.Root>\n {/* \n TODO Fix in the DS\n - as={IconButton} has TS error: Property 'icon' does not exist on type 'IntrinsicAttributes & TriggerProps & RefAttributes<HTMLButtonElement>'\n - The Icon doesn't actually show unless you hack it with some padding...and it's still a little strange\n */}\n <Menu.Trigger\n as={IconButton}\n paddingLeft={2}\n paddingRight={2}\n aria-label={formatMessage({\n id: 'content-releases.header.actions.open-release-actions',\n defaultMessage: 'Release edit and delete menu',\n })}\n // @ts-expect-error See above\n icon={<More />}\n variant=\"tertiary\"\n />\n {/*\n TODO: Using Menu instead of SimpleMenu mainly because there is no positioning provided from the DS,\n Refactor this once fixed in the DS\n */}\n <Menu.Content top={1} popoverPlacement=\"bottom-end\">\n <Flex\n alignItems=\"center\"\n justifyContent=\"center\"\n direction=\"column\"\n padding={1}\n width=\"100%\"\n >\n <StyledMenuItem disabled={!canUpdate} onSelect={toggleEditReleaseModal}>\n <Flex alignItems=\"center\" gap={2} hasRadius width=\"100%\">\n <PencilIcon />\n <Typography ellipsis>\n {formatMessage({\n id: 'content-releases.header.actions.edit',\n defaultMessage: 'Edit',\n })}\n </Typography>\n </Flex>\n </StyledMenuItem>\n <StyledMenuItem\n disabled={!canDelete}\n onSelect={toggleWarningSubmit}\n variant=\"danger\"\n >\n <Flex alignItems=\"center\" gap={2} hasRadius width=\"100%\">\n <TrashIcon />\n <Typography ellipsis textColor=\"danger600\">\n {formatMessage({\n id: 'content-releases.header.actions.delete',\n defaultMessage: 'Delete',\n })}\n </Typography>\n </Flex>\n </StyledMenuItem>\n </Flex>\n <ReleaseInfoWrapper\n direction=\"column\"\n justifyContent=\"center\"\n alignItems=\"flex-start\"\n gap={1}\n padding={5}\n >\n <Typography variant=\"pi\" fontWeight=\"bold\">\n {formatMessage({\n id: 'content-releases.header.actions.created',\n defaultMessage: 'Created',\n })}\n </Typography>\n <Typography variant=\"pi\" color=\"neutral300\">\n <RelativeTime timestamp={new Date(release.createdAt)} />\n {formatMessage(\n {\n id: 'content-releases.header.actions.created.description',\n defaultMessage:\n '{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}',\n },\n { createdBy: getCreatedByUser(), hasCreatedByUser }\n )}\n </Typography>\n </ReleaseInfoWrapper>\n </Menu.Content>\n </Menu.Root>\n <Button size=\"S\" variant=\"tertiary\" onClick={handleRefresh}>\n {formatMessage({\n id: 'content-releases.header.actions.refresh',\n defaultMessage: 'Refresh',\n })}\n </Button>\n <CheckPermissions permissions={PERMISSIONS.publish}>\n <Button\n size=\"S\"\n variant=\"default\"\n onClick={handlePublishRelease}\n loading={isPublishing}\n disabled={release.actions.meta.count === 0}\n >\n {formatMessage({\n id: 'content-releases.header.actions.publish',\n defaultMessage: 'Publish',\n })}\n </Button>\n </CheckPermissions>\n </Flex>\n )\n }\n />\n {children}\n </Main>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleaseDetailsBody\n * -----------------------------------------------------------------------------------------------*/\nconst GROUP_BY_OPTIONS = ['contentType', 'locale', 'action'] as const;\nconst getGroupByOptionLabel = (value: (typeof GROUP_BY_OPTIONS)[number]) => {\n if (value === 'locale') {\n return {\n id: 'content-releases.pages.ReleaseDetails.groupBy.option.locales',\n defaultMessage: 'Locales',\n };\n }\n\n if (value === 'action') {\n return {\n id: 'content-releases.pages.ReleaseDetails.groupBy.option.actions',\n defaultMessage: 'Actions',\n };\n }\n\n return {\n id: 'content-releases.pages.ReleaseDetails.groupBy.option.content-type',\n defaultMessage: 'Content-Types',\n };\n};\n\nconst ReleaseDetailsBody = () => {\n const { formatMessage } = useIntl();\n const { releaseId } = useParams<{ releaseId: string }>();\n const [{ query }, setQuery] = useQueryParams<GetReleaseActionsQueryParams>();\n const toggleNotification = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const {\n data: releaseData,\n isLoading: isReleaseLoading,\n isError: isReleaseError,\n error: releaseError,\n } = useGetReleaseQuery({ id: releaseId });\n const {\n allowedActions: { canUpdate },\n } = useRBAC(PERMISSIONS);\n\n const release = releaseData?.data;\n const selectedGroupBy = query?.groupBy || 'contentType';\n\n const {\n isLoading,\n isFetching,\n isError,\n data,\n error: releaseActionsError,\n } = useGetReleaseActionsQuery({\n ...query,\n releaseId,\n });\n\n const [updateReleaseAction] = useUpdateReleaseActionMutation();\n\n const handleChangeType = async (\n e: React.ChangeEvent<HTMLInputElement>,\n actionId: ReleaseAction['id'],\n actionPath: [string, number]\n ) => {\n const response = await updateReleaseAction({\n params: {\n releaseId,\n actionId,\n },\n body: {\n type: e.target.value as ReleaseAction['type'],\n },\n query, // We are passing the query params to make optimistic updates\n actionPath, // We are passing the action path to found the position in the cache of the action for optimistic updates\n });\n\n if ('error' in response) {\n if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n }\n };\n\n if (isLoading || isReleaseLoading) {\n return (\n <ContentLayout>\n <LoadingIndicatorPage />\n </ContentLayout>\n );\n }\n\n const releaseActions = data?.data;\n const releaseMeta = data?.meta;\n const contentTypes = releaseMeta?.contentTypes || {};\n const components = releaseMeta?.components || {};\n\n if (isReleaseError || !release) {\n const errorsArray = [];\n if (releaseError) {\n errorsArray.push({\n code: releaseError.code,\n });\n }\n if (releaseActionsError) {\n errorsArray.push({\n code: releaseActionsError.code,\n });\n }\n return (\n <Redirect\n to={{\n pathname: '/plugins/content-releases',\n state: {\n errors: errorsArray,\n },\n }}\n />\n );\n }\n\n if (isError || !releaseActions) {\n return (\n <ContentLayout>\n <AnErrorOccurred />\n </ContentLayout>\n );\n }\n\n if (Object.keys(releaseActions).length === 0) {\n return (\n <ContentLayout>\n <NoContent\n content={{\n id: 'content-releases.pages.Details.tab.emptyEntries',\n defaultMessage:\n 'This release is empty. Open the Content Manager, select an entry and add it to the release.',\n }}\n action={\n <LinkButton\n as={ReactRouterLink}\n // @ts-expect-error - types are not inferred correctly through the as prop.\n to={{\n pathname: '/content-manager',\n }}\n style={{ textDecoration: 'none' }}\n variant=\"secondary\"\n >\n {formatMessage({\n id: 'content-releases.page.Details.button.openContentManager',\n defaultMessage: 'Open the Content Manager',\n })}\n </LinkButton>\n }\n />\n </ContentLayout>\n );\n }\n\n return (\n <ContentLayout>\n <Flex gap={8} direction=\"column\" alignItems=\"stretch\">\n <Flex>\n <SingleSelect\n aria-label={formatMessage({\n id: 'content-releases.pages.ReleaseDetails.groupBy.aria-label',\n defaultMessage: 'Group by',\n })}\n customizeContent={(value) =>\n formatMessage(\n {\n id: `content-releases.pages.ReleaseDetails.groupBy.label`,\n defaultMessage: `Group by {groupBy}`,\n },\n {\n groupBy: value,\n }\n )\n }\n value={formatMessage(getGroupByOptionLabel(selectedGroupBy))}\n onChange={(value) => setQuery({ groupBy: value as ReleaseActionGroupBy })}\n >\n {GROUP_BY_OPTIONS.map((option) => (\n <SingleSelectOption key={option} value={option}>\n {formatMessage(getGroupByOptionLabel(option))}\n </SingleSelectOption>\n ))}\n </SingleSelect>\n </Flex>\n {Object.keys(releaseActions).map((key) => (\n <Flex key={`releases-group-${key}`} gap={4} direction=\"column\" alignItems=\"stretch\">\n <Flex role=\"separator\" aria-label={key}>\n <Badge>{key}</Badge>\n </Flex>\n <Table.Root\n rows={releaseActions[key].map((item) => ({\n ...item,\n id: Number(item.entry.id),\n }))}\n colCount={releaseActions[key].length}\n isLoading={isLoading}\n isFetching={isFetching}\n >\n <Table.Content>\n <Table.Head>\n <Table.HeaderCell\n fieldSchemaType=\"string\"\n label={formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.name',\n defaultMessage: 'name',\n })}\n name=\"name\"\n />\n <Table.HeaderCell\n fieldSchemaType=\"string\"\n label={formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.locale',\n defaultMessage: 'locale',\n })}\n name=\"locale\"\n />\n <Table.HeaderCell\n fieldSchemaType=\"string\"\n label={formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.content-type',\n defaultMessage: 'content-type',\n })}\n name=\"content-type\"\n />\n <Table.HeaderCell\n fieldSchemaType=\"string\"\n label={formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.action',\n defaultMessage: 'action',\n })}\n name=\"action\"\n />\n {!release.releasedAt && (\n <Table.HeaderCell\n fieldSchemaType=\"string\"\n label={formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.status',\n defaultMessage: 'status',\n })}\n name=\"status\"\n />\n )}\n </Table.Head>\n <Table.LoadingBody />\n <Table.Body>\n {releaseActions[key].map(\n ({ id, contentType, locale, type, entry }, actionIndex) => (\n <Tr key={id}>\n <Td width=\"25%\" maxWidth=\"200px\">\n <Typography ellipsis>{`${\n contentType.mainFieldValue || entry.id\n }`}</Typography>\n </Td>\n <Td width=\"10%\">\n <Typography>{`${locale?.name ? locale.name : '-'}`}</Typography>\n </Td>\n <Td width=\"10%\">\n <Typography>{contentType.displayName || ''}</Typography>\n </Td>\n <Td width=\"20%\">\n {release.releasedAt ? (\n <Typography>\n {formatMessage(\n {\n id: 'content-releases.page.ReleaseDetails.table.action-published',\n defaultMessage:\n 'This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>.',\n },\n {\n isPublish: type === 'publish',\n b: (children: React.ReactNode) => (\n <Typography fontWeight=\"bold\">{children}</Typography>\n ),\n }\n )}\n </Typography>\n ) : (\n <ReleaseActionOptions\n selected={type}\n handleChange={(e) => handleChangeType(e, id, [key, actionIndex])}\n name={`release-action-${id}-type`}\n disabled={!canUpdate}\n />\n )}\n </Td>\n {!release.releasedAt && (\n <>\n <Td width=\"20%\" minWidth=\"200px\">\n <EntryValidationText\n action={type}\n schema={contentTypes?.[contentType.uid]}\n components={components}\n entry={entry}\n />\n </Td>\n <Td>\n <Flex justifyContent=\"flex-end\">\n <ReleaseActionMenu.Root>\n <ReleaseActionMenu.ReleaseActionEntryLinkItem\n contentTypeUid={contentType.uid}\n entryId={entry.id}\n locale={locale?.code}\n />\n <ReleaseActionMenu.DeleteReleaseActionItem\n releaseId={release.id}\n actionId={id}\n />\n </ReleaseActionMenu.Root>\n </Flex>\n </Td>\n </>\n )}\n </Tr>\n )\n )}\n </Table.Body>\n </Table.Content>\n </Table.Root>\n </Flex>\n ))}\n <Flex paddingTop={4} alignItems=\"flex-end\" justifyContent=\"space-between\">\n <PageSizeURLQuery defaultValue={releaseMeta?.pagination?.pageSize.toString()} />\n <PaginationURLQuery\n pagination={{\n pageCount: releaseMeta?.pagination?.pageCount || 0,\n }}\n />\n </Flex>\n </Flex>\n </ContentLayout>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleaseDetailsPage\n * -----------------------------------------------------------------------------------------------*/\nconst ReleaseDetailsPage = () => {\n const { formatMessage } = useIntl();\n const { releaseId } = useParams<{ releaseId: string }>();\n const toggleNotification = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const { replace } = useHistory();\n const [releaseModalShown, setReleaseModalShown] = React.useState(false);\n const [showWarningSubmit, setWarningSubmit] = React.useState(false);\n\n const {\n isLoading: isLoadingDetails,\n data,\n isSuccess: isSuccessDetails,\n } = useGetReleaseQuery({ id: releaseId });\n const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();\n const [deleteRelease, { isLoading: isDeletingRelease }] = useDeleteReleaseMutation();\n\n const toggleEditReleaseModal = () => {\n setReleaseModalShown((prev) => !prev);\n };\n\n const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);\n\n if (isLoadingDetails) {\n return (\n <ReleaseDetailsLayout\n toggleEditReleaseModal={toggleEditReleaseModal}\n toggleWarningSubmit={toggleWarningSubmit}\n >\n <ContentLayout>\n <LoadingIndicatorPage />\n </ContentLayout>\n </ReleaseDetailsLayout>\n );\n }\n\n const releaseData = (isSuccessDetails && data?.data) || null;\n\n const title = releaseData?.name || '';\n const timezone = releaseData?.timezone ?? null;\n const scheduledAt =\n releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;\n // Just get the date and time to display without considering updated timezone time\n const date = scheduledAt ? format(scheduledAt, 'yyyy-MM-dd') : null;\n const time = scheduledAt ? format(scheduledAt, 'HH:mm') : '';\n\n const handleEditRelease = async (values: FormValues) => {\n const response = await updateRelease({\n id: releaseId,\n name: values.name,\n scheduledAt: values.scheduledAt,\n timezone: values.timezone,\n });\n\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.modal.release-updated-notification-success',\n defaultMessage: 'Release updated.',\n }),\n });\n toggleEditReleaseModal();\n } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n const handleDeleteRelease = async () => {\n const response = await deleteRelease({\n id: releaseId,\n });\n\n if ('data' in response) {\n replace('/plugins/content-releases');\n } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n return (\n <ReleaseDetailsLayout\n toggleEditReleaseModal={toggleEditReleaseModal}\n toggleWarningSubmit={toggleWarningSubmit}\n >\n <ReleaseDetailsBody />\n {releaseModalShown && (\n <ReleaseModal\n handleClose={toggleEditReleaseModal}\n handleSubmit={handleEditRelease}\n isLoading={isLoadingDetails || isSubmittingForm}\n initialValues={{\n name: title || '',\n scheduledAt,\n date,\n time,\n isScheduled: Boolean(scheduledAt),\n timezone,\n }}\n />\n )}\n <ConfirmDialog\n bodyText={{\n id: 'content-releases.dialog.confirmation-message',\n defaultMessage: 'Are you sure you want to delete this release?',\n }}\n isOpen={showWarningSubmit}\n isConfirmButtonLoading={isDeletingRelease}\n onToggleDialog={toggleWarningSubmit}\n onConfirm={handleDeleteRelease}\n />\n </ReleaseDetailsLayout>\n );\n};\n\nexport { ReleaseDetailsPage };\n","import { CheckPagePermissions } from '@strapi/helper-plugin';\nimport { Route, Switch } from 'react-router-dom';\n\nimport { PERMISSIONS } from '../constants';\nimport { pluginId } from '../pluginId';\n\nimport { ReleaseDetailsPage } from './ReleaseDetailsPage';\nimport { ReleasesPage } from './ReleasesPage';\n\nexport const App = () => {\n return (\n <CheckPagePermissions permissions={PERMISSIONS.main}>\n <Switch>\n <Route exact path={`/plugins/${pluginId}`} component={ReleasesPage} />\n <Route exact path={`/plugins/${pluginId}/:releaseId`} component={ReleaseDetailsPage} />\n </Switch>\n </CheckPagePermissions>\n );\n};\n"],"names":["yup","useIntl","useLocation","pluginId","zonedTimeToUtc","jsxs","ModalLayout","jsx","ModalHeader","Typography","Formik","Form","ModalBody","Flex","TextInput","Box","Checkbox","Fragment","DatePicker","formatISO","utcToZonedTime","TimePicker","ModalFooter","Button","getTimezoneOffset","useFormikContext","React","timezoneList","Combobox","ComboboxOption","styled","Link","BaseRelativeTime","AnErrorOccurred","EmptyStateLayout","EmptyDocuments","Grid","GridItem","Badge","Alert","useNotification","useHistory","useAPIErrorHandler","useQueryParams","useGetReleasesQuery","useCreateReleaseMutation","useLicenseLimits","useTracking","Main","LoadingIndicatorPage","index","response","isAxiosError","HeaderLayout","CheckPermissions","PERMISSIONS","Plus","ContentLayout","TabGroup","Tabs","Tab","Divider","TabPanels","TabPanel","PageSizeURLQuery","PaginationURLQuery","Menu","Pencil","Trash","unstable_useDocument","Icon","CrossCircle","Tooltip","CheckCircle","useParams","useGetReleaseQuery","usePublishReleaseMutation","useRBAC","useTypedDispatch","totalEntries","releaseApi","Redirect","ArrowLeft","IconButton","More","RelativeTime","useGetReleaseActionsQuery","useUpdateReleaseActionMutation","NoContent","LinkButton","ReactRouterLink","SingleSelect","SingleSelectOption","Table","Tr","Td","ReleaseActionOptions","ReleaseActionMenu","useUpdateReleaseMutation","useDeleteReleaseMutation","format","ConfirmDialog","CheckPagePermissions","Switch","Route"],"mappings":"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"}