@strapi/content-releases 0.0.0-experimental.b5b7b8260a4549f3bd7443fbd68be5ccc9857cd7 → 0.0.0-experimental.c5354c231bf2abb4fe353d2ab7812bced4a1c6fa

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 (30) hide show
  1. package/dist/_chunks/{App-AYV8n9jv.js → App-OP70yd5M.js} +784 -435
  2. package/dist/_chunks/App-OP70yd5M.js.map +1 -0
  3. package/dist/_chunks/App-x6Tjj3HN.mjs +1315 -0
  4. package/dist/_chunks/App-x6Tjj3HN.mjs.map +1 -0
  5. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs +51 -0
  6. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +1 -0
  7. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js +51 -0
  8. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +1 -0
  9. package/dist/_chunks/{en-gYDqKYFd.js → en-3SGjiVyR.js} +29 -7
  10. package/dist/_chunks/en-3SGjiVyR.js.map +1 -0
  11. package/dist/_chunks/{en-MyLPoISH.mjs → en-bpHsnU0n.mjs} +29 -7
  12. package/dist/_chunks/en-bpHsnU0n.mjs.map +1 -0
  13. package/dist/_chunks/{index-NFIckO1N.mjs → index-1ejXLtzt.mjs} +367 -48
  14. package/dist/_chunks/index-1ejXLtzt.mjs.map +1 -0
  15. package/dist/_chunks/{index-FYDbIuRi.js → index-ydocdaZ0.js} +355 -36
  16. package/dist/_chunks/index-ydocdaZ0.js.map +1 -0
  17. package/dist/admin/index.js +2 -2
  18. package/dist/admin/index.mjs +3 -3
  19. package/dist/server/index.js +1059 -377
  20. package/dist/server/index.js.map +1 -1
  21. package/dist/server/index.mjs +1060 -379
  22. package/dist/server/index.mjs.map +1 -1
  23. package/package.json +16 -11
  24. package/dist/_chunks/App-AYV8n9jv.js.map +0 -1
  25. package/dist/_chunks/App-KBaxZVmD.mjs +0 -967
  26. package/dist/_chunks/App-KBaxZVmD.mjs.map +0 -1
  27. package/dist/_chunks/en-MyLPoISH.mjs.map +0 -1
  28. package/dist/_chunks/en-gYDqKYFd.js.map +0 -1
  29. package/dist/_chunks/index-FYDbIuRi.js.map +0 -1
  30. package/dist/_chunks/index-NFIckO1N.mjs.map +0 -1
@@ -3,13 +3,17 @@ 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-FYDbIuRi.js");
6
+ const index = require("./index-ydocdaZ0.js");
7
7
  const React = require("react");
8
+ const strapiAdmin = require("@strapi/admin/strapi-admin");
8
9
  const designSystem = require("@strapi/design-system");
9
10
  const v2 = require("@strapi/design-system/v2");
10
11
  const icons = require("@strapi/icons");
12
+ const format = require("date-fns/format");
13
+ const dateFnsTz = require("date-fns-tz");
11
14
  const reactIntl = require("react-intl");
12
15
  const styled = require("styled-components");
16
+ const dateFns = require("date-fns");
13
17
  const formik = require("formik");
14
18
  const yup = require("yup");
15
19
  require("@reduxjs/toolkit/query");
@@ -36,10 +40,28 @@ function _interopNamespace(e) {
36
40
  return Object.freeze(n);
37
41
  }
38
42
  const React__namespace = /* @__PURE__ */ _interopNamespace(React);
43
+ const format__default = /* @__PURE__ */ _interopDefault(format);
39
44
  const styled__default = /* @__PURE__ */ _interopDefault(styled);
40
45
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
41
46
  const RELEASE_SCHEMA = yup__namespace.object().shape({
42
- name: yup__namespace.string().trim().required()
47
+ name: yup__namespace.string().trim().required(),
48
+ scheduledAt: yup__namespace.string().nullable(),
49
+ isScheduled: yup__namespace.boolean().optional(),
50
+ time: yup__namespace.string().when("isScheduled", {
51
+ is: true,
52
+ then: yup__namespace.string().trim().required(),
53
+ otherwise: yup__namespace.string().nullable()
54
+ }),
55
+ timezone: yup__namespace.string().when("isScheduled", {
56
+ is: true,
57
+ then: yup__namespace.string().required().nullable(),
58
+ otherwise: yup__namespace.string().nullable()
59
+ }),
60
+ date: yup__namespace.string().when("isScheduled", {
61
+ is: true,
62
+ then: yup__namespace.string().required().nullable(),
63
+ otherwise: yup__namespace.string().nullable()
64
+ })
43
65
  }).required().noUnknown();
44
66
  const ReleaseModal = ({
45
67
  handleClose,
@@ -50,6 +72,22 @@ const ReleaseModal = ({
50
72
  const { formatMessage } = reactIntl.useIntl();
51
73
  const { pathname } = reactRouterDom.useLocation();
52
74
  const isCreatingRelease = pathname === `/plugins/${index.pluginId}`;
75
+ const { timezoneList, systemTimezone = { value: "UTC+00:00-Africa/Abidjan " } } = getTimezones(
76
+ initialValues.scheduledAt ? new Date(initialValues.scheduledAt) : /* @__PURE__ */ new Date()
77
+ );
78
+ const getScheduledTimestamp = (values) => {
79
+ const { date, time, timezone } = values;
80
+ if (!date || !time || !timezone)
81
+ return null;
82
+ const timezoneWithoutOffset = timezone.split("&")[1];
83
+ return dateFnsTz.zonedTimeToUtc(`${date} ${time}`, timezoneWithoutOffset);
84
+ };
85
+ const getTimezoneWithOffset = () => {
86
+ const currentTimezone = timezoneList.find(
87
+ (timezone) => timezone.value.split("&")[1] === initialValues.timezone
88
+ );
89
+ return currentTimezone?.value || systemTimezone.value;
90
+ };
53
91
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
54
92
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage(
55
93
  {
@@ -61,45 +99,130 @@ const ReleaseModal = ({
61
99
  /* @__PURE__ */ jsxRuntime.jsx(
62
100
  formik.Formik,
63
101
  {
64
- validateOnChange: false,
65
- onSubmit: handleSubmit,
66
- initialValues,
102
+ onSubmit: (values) => {
103
+ handleSubmit({
104
+ ...values,
105
+ timezone: values.timezone ? values.timezone.split("&")[1] : null,
106
+ scheduledAt: values.isScheduled ? getScheduledTimestamp(values) : null
107
+ });
108
+ },
109
+ initialValues: {
110
+ ...initialValues,
111
+ timezone: initialValues.timezone ? getTimezoneWithOffset() : systemTimezone.value
112
+ },
67
113
  validationSchema: RELEASE_SCHEMA,
68
- children: ({ values, errors, handleChange }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
69
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: /* @__PURE__ */ jsxRuntime.jsx(
70
- designSystem.TextInput,
71
- {
72
- label: formatMessage({
73
- id: "content-releases.modal.form.input.label.release-name",
74
- defaultMessage: "Name"
75
- }),
76
- name: "name",
77
- value: values.name,
78
- error: errors.name,
79
- onChange: handleChange,
80
- required: true
81
- }
82
- ) }),
114
+ validateOnChange: false,
115
+ children: ({ values, errors, handleChange, setFieldValue }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
116
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
117
+ /* @__PURE__ */ jsxRuntime.jsx(
118
+ designSystem.TextInput,
119
+ {
120
+ label: formatMessage({
121
+ id: "content-releases.modal.form.input.label.release-name",
122
+ defaultMessage: "Name"
123
+ }),
124
+ name: "name",
125
+ value: values.name,
126
+ error: errors.name,
127
+ onChange: handleChange,
128
+ required: true
129
+ }
130
+ ),
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: () => {
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: () => {
205
+ setFieldValue("time", "");
206
+ },
207
+ value: values.time || void 0,
208
+ required: true
209
+ }
210
+ ) })
211
+ ] }),
212
+ /* @__PURE__ */ jsxRuntime.jsx(TimezoneComponent, { timezoneOptions: timezoneList })
213
+ ] })
214
+ ] }) }),
83
215
  /* @__PURE__ */ jsxRuntime.jsx(
84
216
  designSystem.ModalFooter,
85
217
  {
86
218
  startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }),
87
- endActions: /* @__PURE__ */ jsxRuntime.jsx(
88
- designSystem.Button,
219
+ endActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { name: "submit", loading: isLoading, type: "submit", children: formatMessage(
89
220
  {
90
- name: "submit",
91
- loading: isLoading,
92
- disabled: !values.name || values.name === initialValues.name,
93
- type: "submit",
94
- children: formatMessage(
95
- {
96
- id: "content-releases.modal.form.button.submit",
97
- defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
98
- },
99
- { isCreatingRelease }
100
- )
101
- }
102
- )
221
+ id: "content-releases.modal.form.button.submit",
222
+ defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
223
+ },
224
+ { isCreatingRelease }
225
+ ) })
103
226
  }
104
227
  )
105
228
  ] })
@@ -107,61 +230,430 @@ const ReleaseModal = ({
107
230
  )
108
231
  ] });
109
232
  };
233
+ const getTimezones = (selectedDate) => {
234
+ const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
235
+ const utcOffset = index.getTimezoneOffset(timezone, selectedDate);
236
+ return { offset: utcOffset, value: `${utcOffset}&${timezone}` };
237
+ });
238
+ const systemTimezone = timezoneList.find(
239
+ (timezone) => timezone.value.split("&")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
240
+ );
241
+ return { timezoneList, systemTimezone };
242
+ };
243
+ const TimezoneComponent = ({ timezoneOptions }) => {
244
+ const { values, errors, setFieldValue } = formik.useFormikContext();
245
+ const { formatMessage } = reactIntl.useIntl();
246
+ const [timezoneList, setTimezoneList] = React__namespace.useState(timezoneOptions);
247
+ React__namespace.useEffect(() => {
248
+ if (values.date) {
249
+ const { timezoneList: timezoneList2 } = getTimezones(new Date(values.date));
250
+ setTimezoneList(timezoneList2);
251
+ const updatedTimezone = values.timezone && timezoneList2.find((tz) => tz.value.split("&")[1] === values.timezone.split("&")[1]);
252
+ if (updatedTimezone) {
253
+ setFieldValue("timezone", updatedTimezone.value);
254
+ }
255
+ }
256
+ }, [setFieldValue, values.date, values.timezone]);
257
+ return /* @__PURE__ */ jsxRuntime.jsx(
258
+ designSystem.Combobox,
259
+ {
260
+ label: formatMessage({
261
+ id: "content-releases.modal.form.input.label.timezone",
262
+ defaultMessage: "Timezone"
263
+ }),
264
+ autocomplete: { type: "list", filter: "contains" },
265
+ name: "timezone",
266
+ value: values.timezone || void 0,
267
+ textValue: values.timezone ? values.timezone.replace(/&/, " ") : void 0,
268
+ onChange: (timezone) => {
269
+ setFieldValue("timezone", timezone);
270
+ },
271
+ onTextValueChange: (timezone) => {
272
+ setFieldValue("timezone", timezone);
273
+ },
274
+ onClear: () => {
275
+ setFieldValue("timezone", "");
276
+ },
277
+ error: errors.timezone,
278
+ required: true,
279
+ children: timezoneList.map((timezone) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: timezone.value, children: timezone.value.replace(/&/, " ") }, timezone.value))
280
+ }
281
+ );
282
+ };
283
+ const LinkCard = styled__default.default(v2.Link)`
284
+ display: block;
285
+ `;
286
+ const RelativeTime = styled__default.default(helperPlugin.RelativeTime)`
287
+ display: inline-block;
288
+ &::first-letter {
289
+ text-transform: uppercase;
290
+ }
291
+ `;
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";
310
+ }
311
+ return {
312
+ textColor: `${color}600`,
313
+ backgroundColor: `${color}100`,
314
+ borderColor: `${color}200`
315
+ };
316
+ };
317
+ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
318
+ const { formatMessage } = reactIntl.useIntl();
319
+ if (isError) {
320
+ return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
321
+ }
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
+ );
338
+ }
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)) });
364
+ };
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);
385
+ const toggleNotification = helperPlugin.useNotification();
386
+ const { formatMessage } = reactIntl.useIntl();
387
+ const { push, replace } = reactRouterDom.useHistory();
388
+ const { formatAPIError } = helperPlugin.useAPIErrorHandler();
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");
394
+ const { trackUsage } = helperPlugin.useTracking();
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) {
400
+ toggleNotification({
401
+ type: "warning",
402
+ title: formatMessage({
403
+ id: "content-releases.pages.Releases.notification.error.title",
404
+ defaultMessage: "Your request could not be processed."
405
+ }),
406
+ message: formatMessage({
407
+ id: "content-releases.pages.Releases.notification.error.message",
408
+ defaultMessage: "Please try again or open another release."
409
+ })
410
+ });
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
+ })
452
+ });
453
+ trackUsage("didCreateRelease");
454
+ push(`/plugins/content-releases/${response2.data.data.id}`);
455
+ } else if (index.isAxiosError(response2.error)) {
456
+ toggleNotification({
457
+ type: "warning",
458
+ message: formatAPIError(response2.error)
459
+ });
460
+ } else {
461
+ toggleNotification({
462
+ type: "warning",
463
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
464
+ });
465
+ }
466
+ };
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
+ };
110
598
  const ReleaseInfoWrapper = styled__default.default(designSystem.Flex)`
111
599
  align-self: stretch;
112
600
  border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
113
601
  border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
114
602
  border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
115
603
  `;
116
- const StyledFlex = styled__default.default(designSystem.Flex)`
117
- align-self: stretch;
118
- cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
119
-
604
+ const StyledMenuItem = styled__default.default(v2.Menu.Item)`
120
605
  svg path {
121
606
  fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
122
607
  }
123
608
  span {
124
609
  color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
125
610
  }
611
+
612
+ &:hover {
613
+ background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
614
+ }
126
615
  `;
127
616
  const PencilIcon = styled__default.default(icons.Pencil)`
128
- width: ${({ theme }) => theme.spaces[4]};
129
- height: ${({ theme }) => theme.spaces[4]};
617
+ width: ${({ theme }) => theme.spaces[3]};
618
+ height: ${({ theme }) => theme.spaces[3]};
130
619
  path {
131
620
  fill: ${({ theme }) => theme.colors.neutral600};
132
621
  }
133
622
  `;
134
623
  const TrashIcon = styled__default.default(icons.Trash)`
135
- width: ${({ theme }) => theme.spaces[4]};
136
- height: ${({ theme }) => theme.spaces[4]};
624
+ width: ${({ theme }) => theme.spaces[3]};
625
+ height: ${({ theme }) => theme.spaces[3]};
137
626
  path {
138
627
  fill: ${({ theme }) => theme.colors.danger600};
139
628
  }
140
629
  `;
141
- const PopoverButton = ({ onClick, disabled, children }) => {
142
- return /* @__PURE__ */ jsxRuntime.jsx(
143
- StyledFlex,
144
- {
145
- paddingTop: 2,
146
- paddingBottom: 2,
147
- paddingLeft: 4,
148
- paddingRight: 4,
149
- alignItems: "center",
150
- gap: 2,
151
- as: "button",
152
- hasRadius: true,
153
- onClick,
154
- disabled,
155
- children
156
- }
157
- );
158
- };
159
- const EntryValidationText = ({ status, action }) => {
630
+ const TypographyMaxWidth = styled__default.default(designSystem.Typography)`
631
+ max-width: 300px;
632
+ `;
633
+ const EntryValidationText = ({ action, schema, components, entry }) => {
160
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
+ }
161
653
  if (action == "publish") {
162
654
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
163
655
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "success600", as: icons.CheckCircle }),
164
- status === "published" ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
656
+ entry.publishedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
165
657
  id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
166
658
  defaultMessage: "Already published"
167
659
  }) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
@@ -172,7 +664,7 @@ const EntryValidationText = ({ status, action }) => {
172
664
  }
173
665
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
174
666
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "success600", as: icons.CheckCircle }),
175
- status === "draft" ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
667
+ !entry.publishedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
176
668
  id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
177
669
  defaultMessage: "Already unpublished"
178
670
  }) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
@@ -186,10 +678,8 @@ const ReleaseDetailsLayout = ({
186
678
  toggleWarningSubmit,
187
679
  children
188
680
  }) => {
189
- const { formatMessage } = reactIntl.useIntl();
681
+ const { formatMessage, formatDate, formatTime } = reactIntl.useIntl();
190
682
  const { releaseId } = reactRouterDom.useParams();
191
- const [isPopoverVisible, setIsPopoverVisible] = React__namespace.useState(false);
192
- const moreButtonRef = React__namespace.useRef(null);
193
683
  const {
194
684
  data,
195
685
  isLoading: isLoadingDetails,
@@ -202,14 +692,9 @@ const ReleaseDetailsLayout = ({
202
692
  const {
203
693
  allowedActions: { canUpdate, canDelete }
204
694
  } = helperPlugin.useRBAC(index.PERMISSIONS);
695
+ const dispatch = index.useTypedDispatch();
696
+ const { trackUsage } = helperPlugin.useTracking();
205
697
  const release = data?.data;
206
- const handleTogglePopover = () => {
207
- setIsPopoverVisible((prev) => !prev);
208
- };
209
- const openReleaseModal = () => {
210
- toggleEditReleaseModal();
211
- handleTogglePopover();
212
- };
213
698
  const handlePublishRelease = async () => {
214
699
  const response = await publishRelease({ id: releaseId });
215
700
  if ("data" in response) {
@@ -220,6 +705,12 @@ const ReleaseDetailsLayout = ({
220
705
  defaultMessage: "Release was published successfully."
221
706
  })
222
707
  });
708
+ const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
709
+ trackUsage("didPublishRelease", {
710
+ totalEntries: totalEntries2,
711
+ totalPublishedEntries,
712
+ totalUnpublishedEntries
713
+ });
223
714
  } else if (index.isAxiosError(response.error)) {
224
715
  toggleNotification({
225
716
  type: "warning",
@@ -232,9 +723,25 @@ const ReleaseDetailsLayout = ({
232
723
  });
233
724
  }
234
725
  };
235
- const openWarningConfirmDialog = () => {
236
- toggleWarningSubmit();
237
- handleTogglePopover();
726
+ const handleRefresh = () => {
727
+ dispatch(
728
+ index.releaseApi.util.invalidateTags([
729
+ { type: "ReleaseAction", id: "LIST" },
730
+ { type: "Release", id: releaseId }
731
+ ])
732
+ );
733
+ };
734
+ const getCreatedByUser = () => {
735
+ if (!release?.createdBy) {
736
+ return null;
737
+ }
738
+ if (release.createdBy.username) {
739
+ return release.createdBy.username;
740
+ }
741
+ if (release.createdBy.firstname) {
742
+ return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
743
+ }
744
+ return release.createdBy.email;
238
745
  };
239
746
  if (isLoadingDetails) {
240
747
  return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
@@ -257,90 +764,131 @@ const ReleaseDetailsLayout = ({
257
764
  );
258
765
  }
259
766
  const totalEntries = release.actions.meta.count || 0;
260
- const createdBy = release.createdBy.lastname ? `${release.createdBy.firstname} ${release.createdBy.lastname}` : `${release.createdBy.firstname}`;
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
+ ) : "";
261
796
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoadingDetails, children: [
262
797
  /* @__PURE__ */ jsxRuntime.jsx(
263
798
  designSystem.HeaderLayout,
264
799
  {
265
800
  title: release.name,
266
- subtitle: formatMessage(
267
- {
268
- id: "content-releases.pages.Details.header-subtitle",
269
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
270
- },
271
- { number: totalEntries }
272
- ),
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
+ ] }),
273
805
  navigationAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
274
806
  id: "global.back",
275
807
  defaultMessage: "Back"
276
808
  }) }),
277
809
  primaryAction: !release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
278
- /* @__PURE__ */ jsxRuntime.jsx(
279
- designSystem.IconButton,
280
- {
281
- label: formatMessage({
282
- id: "content-releases.header.actions.open-release-actions",
283
- defaultMessage: "Release actions"
284
- }),
285
- ref: moreButtonRef,
286
- onClick: handleTogglePopover,
287
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {})
288
- }
289
- ),
290
- isPopoverVisible && /* @__PURE__ */ jsxRuntime.jsxs(
291
- designSystem.Popover,
292
- {
293
- source: moreButtonRef,
294
- placement: "bottom-end",
295
- onDismiss: handleTogglePopover,
296
- spacing: 4,
297
- minWidth: "242px",
298
- children: [
299
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", justifyContent: "center", direction: "column", padding: 1, children: [
300
- /* @__PURE__ */ jsxRuntime.jsxs(PopoverButton, { disabled: !canUpdate, onClick: openReleaseModal, children: [
301
- /* @__PURE__ */ jsxRuntime.jsx(PencilIcon, {}),
302
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: formatMessage({
303
- id: "content-releases.header.actions.edit",
304
- defaultMessage: "Edit"
305
- }) })
306
- ] }),
307
- /* @__PURE__ */ jsxRuntime.jsxs(PopoverButton, { disabled: !canDelete, onClick: openWarningConfirmDialog, children: [
308
- /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {}),
309
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
310
- id: "content-releases.header.actions.delete",
311
- defaultMessage: "Delete"
312
- }) })
313
- ] })
314
- ] }),
315
- /* @__PURE__ */ jsxRuntime.jsxs(
316
- ReleaseInfoWrapper,
317
- {
318
- direction: "column",
319
- justifyContent: "center",
320
- alignItems: "flex-start",
321
- gap: 1,
322
- padding: 5,
323
- children: [
324
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
325
- id: "content-releases.header.actions.created",
326
- defaultMessage: "Created"
327
- }) }),
328
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", color: "neutral300", children: [
329
- /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.RelativeTime, { timestamp: new Date(release.createdAt) }),
330
- formatMessage(
331
- {
332
- id: "content-releases.header.actions.created.description",
333
- defaultMessage: " by {createdBy}"
334
- },
335
- { createdBy }
336
- )
337
- ] })
338
- ]
339
- }
340
- )
341
- ]
342
- }
343
- ),
810
+ /* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Root, { children: [
811
+ /* @__PURE__ */ jsxRuntime.jsx(
812
+ v2.Menu.Trigger,
813
+ {
814
+ as: designSystem.IconButton,
815
+ paddingLeft: 2,
816
+ paddingRight: 2,
817
+ "aria-label": formatMessage({
818
+ id: "content-releases.header.actions.open-release-actions",
819
+ defaultMessage: "Release edit and delete menu"
820
+ }),
821
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {}),
822
+ variant: "tertiary"
823
+ }
824
+ ),
825
+ /* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: [
826
+ /* @__PURE__ */ jsxRuntime.jsxs(
827
+ designSystem.Flex,
828
+ {
829
+ alignItems: "center",
830
+ justifyContent: "center",
831
+ direction: "column",
832
+ padding: 1,
833
+ width: "100%",
834
+ children: [
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,
844
+ {
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: [
849
+ /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {}),
850
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
851
+ id: "content-releases.header.actions.delete",
852
+ defaultMessage: "Delete"
853
+ }) })
854
+ ] })
855
+ }
856
+ )
857
+ ]
858
+ }
859
+ ),
860
+ /* @__PURE__ */ jsxRuntime.jsxs(
861
+ ReleaseInfoWrapper,
862
+ {
863
+ direction: "column",
864
+ justifyContent: "center",
865
+ alignItems: "flex-start",
866
+ gap: 1,
867
+ padding: 5,
868
+ children: [
869
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
870
+ id: "content-releases.header.actions.created",
871
+ defaultMessage: "Created"
872
+ }) }),
873
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", color: "neutral300", children: [
874
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.RelativeTime, { timestamp: new Date(release.createdAt) }),
875
+ formatMessage(
876
+ {
877
+ id: "content-releases.header.actions.created.description",
878
+ defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
879
+ },
880
+ { createdBy: getCreatedByUser(), hasCreatedByUser }
881
+ )
882
+ ] })
883
+ ]
884
+ }
885
+ )
886
+ ] })
887
+ ] }),
888
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
889
+ id: "content-releases.header.actions.refresh",
890
+ defaultMessage: "Refresh"
891
+ }) }),
344
892
  /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.publish, children: /* @__PURE__ */ jsxRuntime.jsx(
345
893
  designSystem.Button,
346
894
  {
@@ -392,6 +940,9 @@ const ReleaseDetailsBody = () => {
392
940
  isError: isReleaseError,
393
941
  error: releaseError
394
942
  } = index.useGetReleaseQuery({ id: releaseId });
943
+ const {
944
+ allowedActions: { canUpdate }
945
+ } = helperPlugin.useRBAC(index.PERMISSIONS);
395
946
  const release = releaseData?.data;
396
947
  const selectedGroupBy = query?.groupBy || "contentType";
397
948
  const {
@@ -405,7 +956,7 @@ const ReleaseDetailsBody = () => {
405
956
  releaseId
406
957
  });
407
958
  const [updateReleaseAction] = index.useUpdateReleaseActionMutation();
408
- const handleChangeType = async (e, actionId) => {
959
+ const handleChangeType = async (e, actionId, actionPath) => {
409
960
  const response = await updateReleaseAction({
410
961
  params: {
411
962
  releaseId,
@@ -413,7 +964,11 @@ const ReleaseDetailsBody = () => {
413
964
  },
414
965
  body: {
415
966
  type: e.target.value
416
- }
967
+ },
968
+ query,
969
+ // We are passing the query params to make optimistic updates
970
+ actionPath
971
+ // We are passing the action path to found the position in the cache of the action for optimistic updates
417
972
  });
418
973
  if ("error" in response) {
419
974
  if (index.isAxiosError(response.error)) {
@@ -434,6 +989,8 @@ const ReleaseDetailsBody = () => {
434
989
  }
435
990
  const releaseActions = data?.data;
436
991
  const releaseMeta = data?.meta;
992
+ const contentTypes = releaseMeta?.contentTypes || {};
993
+ const components = releaseMeta?.components || {};
437
994
  if (isReleaseError || !release) {
438
995
  const errorsArray = [];
439
996
  if (releaseError) {
@@ -492,7 +1049,7 @@ const ReleaseDetailsBody = () => {
492
1049
  designSystem.SingleSelect,
493
1050
  {
494
1051
  "aria-label": formatMessage({
495
- id: "content-releases.pages.ReleaseDetails.groupBy.label",
1052
+ id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
496
1053
  defaultMessage: "Group by"
497
1054
  }),
498
1055
  customizeContent: (value) => formatMessage(
@@ -510,7 +1067,7 @@ const ReleaseDetailsBody = () => {
510
1067
  }
511
1068
  ) }),
512
1069
  Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
513
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: key }) }),
1070
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { role: "separator", "aria-label": key, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: key }) }),
514
1071
  /* @__PURE__ */ jsxRuntime.jsx(
515
1072
  helperPlugin.Table.Root,
516
1073
  {
@@ -580,48 +1137,59 @@ const ReleaseDetailsBody = () => {
580
1137
  )
581
1138
  ] }),
582
1139
  /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.LoadingBody, {}),
583
- /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.Body, { children: releaseActions[key].map(({ id, type, entry, contentType, locale }) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
584
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: `${entry.contentType.mainFieldValue || entry.id}` }) }),
585
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: `${entry?.locale?.name ? entry.locale.name : "-"}` }) }),
586
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: entry.contentType.displayName || "" }) }),
587
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage(
588
- {
589
- id: "content-releases.page.ReleaseDetails.table.action-published",
590
- defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
591
- },
592
- {
593
- isPublish: type === "publish",
594
- b: (children) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children })
595
- }
596
- ) }) : /* @__PURE__ */ jsxRuntime.jsx(
597
- index.ReleaseActionOptions,
598
- {
599
- selected: type,
600
- handleChange: (e) => handleChangeType(e, id),
601
- name: `release-action-${id}-type`
602
- }
603
- ) }),
604
- !release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
605
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", minWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(EntryValidationText, { status: entry.status, action: type }) }),
606
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxRuntime.jsxs(index.ReleaseActionMenu.Root, { children: [
607
- /* @__PURE__ */ jsxRuntime.jsx(
608
- index.ReleaseActionMenu.ReleaseActionEntryLinkItem,
609
- {
610
- contentTypeUid: contentType,
611
- entryId: entry.id,
612
- locale
613
- }
614
- ),
615
- /* @__PURE__ */ jsxRuntime.jsx(
616
- index.ReleaseActionMenu.DeleteReleaseActionItem,
1140
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.Body, { children: releaseActions[key].map(
1141
+ ({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
1142
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
1143
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
1144
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: contentType.displayName || "" }) }),
1145
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage(
1146
+ {
1147
+ id: "content-releases.page.ReleaseDetails.table.action-published",
1148
+ defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
1149
+ },
1150
+ {
1151
+ isPublish: type === "publish",
1152
+ b: (children) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children })
1153
+ }
1154
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(
1155
+ index.ReleaseActionOptions,
1156
+ {
1157
+ selected: type,
1158
+ handleChange: (e) => handleChangeType(e, id, [key, actionIndex]),
1159
+ name: `release-action-${id}-type`,
1160
+ disabled: !canUpdate
1161
+ }
1162
+ ) }),
1163
+ !release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1164
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", minWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(
1165
+ EntryValidationText,
617
1166
  {
618
- releaseId: release.id,
619
- actionId: id
1167
+ action: type,
1168
+ schema: contentTypes?.[contentType.uid],
1169
+ components,
1170
+ entry
620
1171
  }
621
- )
622
- ] }) }) })
623
- ] })
624
- ] }, id)) })
1172
+ ) }),
1173
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxRuntime.jsxs(index.ReleaseActionMenu.Root, { children: [
1174
+ /* @__PURE__ */ jsxRuntime.jsx(
1175
+ index.ReleaseActionMenu.ReleaseActionEntryLinkItem,
1176
+ {
1177
+ contentTypeUid: contentType.uid,
1178
+ entryId: entry.id,
1179
+ locale: locale?.code
1180
+ }
1181
+ ),
1182
+ /* @__PURE__ */ jsxRuntime.jsx(
1183
+ index.ReleaseActionMenu.DeleteReleaseActionItem,
1184
+ {
1185
+ releaseId: release.id,
1186
+ actionId: id
1187
+ }
1188
+ )
1189
+ ] }) }) })
1190
+ ] })
1191
+ ] }, id)
1192
+ ) })
625
1193
  ] })
626
1194
  }
627
1195
  )
@@ -644,7 +1212,7 @@ const ReleaseDetailsPage = () => {
644
1212
  const { releaseId } = reactRouterDom.useParams();
645
1213
  const toggleNotification = helperPlugin.useNotification();
646
1214
  const { formatAPIError } = helperPlugin.useAPIErrorHandler();
647
- const { push } = reactRouterDom.useHistory();
1215
+ const { replace } = reactRouterDom.useHistory();
648
1216
  const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
649
1217
  const [showWarningSubmit, setWarningSubmit] = React__namespace.useState(false);
650
1218
  const {
@@ -668,11 +1236,18 @@ const ReleaseDetailsPage = () => {
668
1236
  }
669
1237
  );
670
1238
  }
671
- const title = isSuccessDetails && data?.data?.name || "";
1239
+ const releaseData = isSuccessDetails && data?.data || null;
1240
+ const title = releaseData?.name || "";
1241
+ const timezone = releaseData?.timezone ?? null;
1242
+ const scheduledAt = releaseData?.scheduledAt && timezone ? dateFnsTz.utcToZonedTime(releaseData.scheduledAt, timezone) : null;
1243
+ const date = scheduledAt ? format__default.default(scheduledAt, "yyyy-MM-dd") : null;
1244
+ const time = scheduledAt ? format__default.default(scheduledAt, "HH:mm") : "";
672
1245
  const handleEditRelease = async (values) => {
673
1246
  const response = await updateRelease({
674
1247
  id: releaseId,
675
- name: values.name
1248
+ name: values.name,
1249
+ scheduledAt: values.scheduledAt,
1250
+ timezone: values.timezone
676
1251
  });
677
1252
  if ("data" in response) {
678
1253
  toggleNotification({
@@ -682,6 +1257,7 @@ const ReleaseDetailsPage = () => {
682
1257
  defaultMessage: "Release updated."
683
1258
  })
684
1259
  });
1260
+ toggleEditReleaseModal();
685
1261
  } else if (index.isAxiosError(response.error)) {
686
1262
  toggleNotification({
687
1263
  type: "warning",
@@ -693,14 +1269,13 @@ const ReleaseDetailsPage = () => {
693
1269
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
694
1270
  });
695
1271
  }
696
- toggleEditReleaseModal();
697
1272
  };
698
1273
  const handleDeleteRelease = async () => {
699
1274
  const response = await deleteRelease({
700
1275
  id: releaseId
701
1276
  });
702
1277
  if ("data" in response) {
703
- push("/plugins/content-releases");
1278
+ replace("/plugins/content-releases");
704
1279
  } else if (index.isAxiosError(response.error)) {
705
1280
  toggleNotification({
706
1281
  type: "warning",
@@ -726,7 +1301,14 @@ const ReleaseDetailsPage = () => {
726
1301
  handleClose: toggleEditReleaseModal,
727
1302
  handleSubmit: handleEditRelease,
728
1303
  isLoading: isLoadingDetails || isSubmittingForm,
729
- initialValues: { name: title || "" }
1304
+ initialValues: {
1305
+ name: title || "",
1306
+ scheduledAt,
1307
+ date,
1308
+ time,
1309
+ isScheduled: Boolean(scheduledAt),
1310
+ timezone
1311
+ }
730
1312
  }
731
1313
  ),
732
1314
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -746,239 +1328,6 @@ const ReleaseDetailsPage = () => {
746
1328
  }
747
1329
  );
748
1330
  };
749
- const ReleasesLayout = ({
750
- isLoading,
751
- totalReleases,
752
- onClickAddRelease,
753
- children
754
- }) => {
755
- const { formatMessage } = reactIntl.useIntl();
756
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
757
- /* @__PURE__ */ jsxRuntime.jsx(
758
- designSystem.HeaderLayout,
759
- {
760
- title: formatMessage({
761
- id: "content-releases.pages.Releases.title",
762
- defaultMessage: "Releases"
763
- }),
764
- subtitle: !isLoading && formatMessage(
765
- {
766
- id: "content-releases.pages.Releases.header-subtitle",
767
- defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
768
- },
769
- { number: totalReleases }
770
- ),
771
- primaryAction: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.create, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}), onClick: onClickAddRelease, children: formatMessage({
772
- id: "content-releases.header.actions.add-release",
773
- defaultMessage: "New release"
774
- }) }) })
775
- }
776
- ),
777
- children
778
- ] });
779
- };
780
- const LinkCard = styled__default.default(v2.Link)`
781
- display: block;
782
- `;
783
- const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
784
- const { formatMessage } = reactIntl.useIntl();
785
- if (isError) {
786
- return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
787
- }
788
- if (releases?.length === 0) {
789
- return /* @__PURE__ */ jsxRuntime.jsx(
790
- designSystem.EmptyStateLayout,
791
- {
792
- content: formatMessage(
793
- {
794
- id: "content-releases.page.Releases.tab.emptyEntries",
795
- defaultMessage: "No releases"
796
- },
797
- {
798
- target: sectionTitle
799
- }
800
- ),
801
- icon: /* @__PURE__ */ jsxRuntime.jsx(icons.EmptyDocuments, { width: "10rem" })
802
- }
803
- );
804
- }
805
- 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(
806
- designSystem.Flex,
807
- {
808
- direction: "column",
809
- justifyContent: "space-between",
810
- padding: 4,
811
- hasRadius: true,
812
- background: "neutral0",
813
- shadow: "tableShadow",
814
- height: "100%",
815
- width: "100%",
816
- alignItems: "start",
817
- gap: 2,
818
- children: [
819
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
820
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", children: formatMessage(
821
- {
822
- id: "content-releases.page.Releases.release-item.entries",
823
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
824
- },
825
- { number: actions.meta.count }
826
- ) })
827
- ]
828
- }
829
- ) }) }, id)) });
830
- };
831
- const INITIAL_FORM_VALUES = {
832
- name: ""
833
- };
834
- const ReleasesPage = () => {
835
- const location = reactRouterDom.useLocation();
836
- const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
837
- const toggleNotification = helperPlugin.useNotification();
838
- const { formatMessage } = reactIntl.useIntl();
839
- const { push, replace } = reactRouterDom.useHistory();
840
- const { formatAPIError } = helperPlugin.useAPIErrorHandler();
841
- const [{ query }, setQuery] = helperPlugin.useQueryParams();
842
- const response = index.useGetReleasesQuery(query);
843
- const [createRelease, { isLoading: isSubmittingForm }] = index.useCreateReleaseMutation();
844
- const { isLoading, isSuccess, isError } = response;
845
- React__namespace.useEffect(() => {
846
- if (location?.state?.errors) {
847
- toggleNotification({
848
- type: "warning",
849
- title: formatMessage({
850
- id: "content-releases.pages.Releases.notification.error.title",
851
- defaultMessage: "Your request could not be processed."
852
- }),
853
- message: formatMessage({
854
- id: "content-releases.pages.Releases.notification.error.message",
855
- defaultMessage: "Please try again or open another release."
856
- })
857
- });
858
- replace({ state: null });
859
- }
860
- }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
861
- const toggleAddReleaseModal = () => {
862
- setReleaseModalShown((prev) => !prev);
863
- };
864
- if (isLoading) {
865
- return /* @__PURE__ */ jsxRuntime.jsx(ReleasesLayout, { onClickAddRelease: toggleAddReleaseModal, isLoading: true, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) }) });
866
- }
867
- const totalReleases = isSuccess && response.currentData?.meta?.pagination?.total || 0;
868
- const handleTabChange = (index2) => {
869
- setQuery({
870
- ...query,
871
- page: 1,
872
- pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
873
- filters: {
874
- releasedAt: {
875
- $notNull: index2 === 0 ? false : true
876
- }
877
- }
878
- });
879
- };
880
- const activeTab = response?.currentData?.meta?.activeTab || "pending";
881
- const handleAddRelease = async (values) => {
882
- const response2 = await createRelease({
883
- name: values.name
884
- });
885
- if ("data" in response2) {
886
- toggleNotification({
887
- type: "success",
888
- message: formatMessage({
889
- id: "content-releases.modal.release-created-notification-success",
890
- defaultMessage: "Release created."
891
- })
892
- });
893
- push(`/plugins/content-releases/${response2.data.data.id}`);
894
- } else if (index.isAxiosError(response2.error)) {
895
- toggleNotification({
896
- type: "warning",
897
- message: formatAPIError(response2.error)
898
- });
899
- } else {
900
- toggleNotification({
901
- type: "warning",
902
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
903
- });
904
- }
905
- };
906
- return /* @__PURE__ */ jsxRuntime.jsxs(ReleasesLayout, { onClickAddRelease: toggleAddReleaseModal, totalReleases, children: [
907
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
908
- /* @__PURE__ */ jsxRuntime.jsxs(
909
- designSystem.TabGroup,
910
- {
911
- label: formatMessage({
912
- id: "content-releases.pages.Releases.tab-group.label",
913
- defaultMessage: "Releases list"
914
- }),
915
- variant: "simple",
916
- initialSelectedTabIndex: ["pending", "done"].indexOf(activeTab),
917
- onTabChange: handleTabChange,
918
- children: [
919
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingBottom: 8, children: [
920
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs, { children: [
921
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage({
922
- id: "content-releases.pages.Releases.tab.pending",
923
- defaultMessage: "Pending"
924
- }) }),
925
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage({
926
- id: "content-releases.pages.Releases.tab.done",
927
- defaultMessage: "Done"
928
- }) })
929
- ] }),
930
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {})
931
- ] }),
932
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.TabPanels, { children: [
933
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
934
- ReleasesGrid,
935
- {
936
- sectionTitle: "pending",
937
- releases: response?.currentData?.data,
938
- isError
939
- }
940
- ) }),
941
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
942
- ReleasesGrid,
943
- {
944
- sectionTitle: "done",
945
- releases: response?.currentData?.data,
946
- isError
947
- }
948
- ) })
949
- ] })
950
- ]
951
- }
952
- ),
953
- totalReleases > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
954
- /* @__PURE__ */ jsxRuntime.jsx(
955
- helperPlugin.PageSizeURLQuery,
956
- {
957
- options: ["8", "16", "32", "64"],
958
- defaultValue: response?.currentData?.meta?.pagination?.pageSize.toString()
959
- }
960
- ),
961
- /* @__PURE__ */ jsxRuntime.jsx(
962
- helperPlugin.PaginationURLQuery,
963
- {
964
- pagination: {
965
- pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
966
- }
967
- }
968
- )
969
- ] })
970
- ] }) }),
971
- releaseModalShown && /* @__PURE__ */ jsxRuntime.jsx(
972
- ReleaseModal,
973
- {
974
- handleClose: toggleAddReleaseModal,
975
- handleSubmit: handleAddRelease,
976
- isLoading: isSubmittingForm,
977
- initialValues: INITIAL_FORM_VALUES
978
- }
979
- )
980
- ] });
981
- };
982
1331
  const App = () => {
983
1332
  return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPagePermissions, { permissions: index.PERMISSIONS.main, children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Switch, { children: [
984
1333
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { exact: true, path: `/plugins/${index.pluginId}`, component: ReleasesPage }),
@@ -986,4 +1335,4 @@ const App = () => {
986
1335
  ] }) });
987
1336
  };
988
1337
  exports.App = App;
989
- //# sourceMappingURL=App-AYV8n9jv.js.map
1338
+ //# sourceMappingURL=App-OP70yd5M.js.map