@strapi/content-releases 4.20.2 → 4.20.4

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.
@@ -3,14 +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-l-FvkQlQ.js");
6
+ const index = require("./index-2xzbhaQP.js");
7
7
  const React = require("react");
8
8
  const strapiAdmin = require("@strapi/admin/strapi-admin");
9
9
  const designSystem = require("@strapi/design-system");
10
10
  const v2 = require("@strapi/design-system/v2");
11
11
  const icons = require("@strapi/icons");
12
+ const format = require("date-fns/format");
13
+ const dateFnsTz = require("date-fns-tz");
12
14
  const reactIntl = require("react-intl");
13
15
  const styled = require("styled-components");
16
+ const dateFns = require("date-fns");
14
17
  const formik = require("formik");
15
18
  const yup = require("yup");
16
19
  require("@reduxjs/toolkit/query");
@@ -37,15 +40,26 @@ function _interopNamespace(e) {
37
40
  return Object.freeze(n);
38
41
  }
39
42
  const React__namespace = /* @__PURE__ */ _interopNamespace(React);
43
+ const format__default = /* @__PURE__ */ _interopDefault(format);
40
44
  const styled__default = /* @__PURE__ */ _interopDefault(styled);
41
45
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
42
46
  const RELEASE_SCHEMA = yup__namespace.object().shape({
43
47
  name: yup__namespace.string().trim().required(),
44
- // scheduledAt is a date, but we always receive strings from the client
45
48
  scheduledAt: yup__namespace.string().nullable(),
46
- timezone: yup__namespace.string().when("scheduledAt", {
47
- is: (scheduledAt) => !!scheduledAt,
48
- then: yup__namespace.string().required(),
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(),
49
63
  otherwise: yup__namespace.string().nullable()
50
64
  })
51
65
  }).required().noUnknown();
@@ -58,6 +72,24 @@ const ReleaseModal = ({
58
72
  const { formatMessage } = reactIntl.useIntl();
59
73
  const { pathname } = reactRouterDom.useLocation();
60
74
  const isCreatingRelease = pathname === `/plugins/${index.pluginId}`;
75
+ const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
76
+ const { timezoneList, systemTimezone = { value: "UTC+00:00-Africa/Abidjan " } } = getTimezones(
77
+ initialValues.scheduledAt ? new Date(initialValues.scheduledAt) : /* @__PURE__ */ new Date()
78
+ );
79
+ const getScheduledTimestamp = (values) => {
80
+ const { date, time, timezone } = values;
81
+ if (!date || !time || !timezone)
82
+ 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);
86
+ };
87
+ const getTimezoneWithOffset = () => {
88
+ const currentTimezone = timezoneList.find(
89
+ (timezone) => timezone.value.split("_")[1] === initialValues.timezone
90
+ );
91
+ return currentTimezone?.value || systemTimezone.value;
92
+ };
61
93
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
62
94
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage(
63
95
  {
@@ -69,45 +101,134 @@ const ReleaseModal = ({
69
101
  /* @__PURE__ */ jsxRuntime.jsx(
70
102
  formik.Formik,
71
103
  {
72
- validateOnChange: false,
73
- onSubmit: handleSubmit,
74
- initialValues,
104
+ onSubmit: (values) => {
105
+ handleSubmit({
106
+ ...values,
107
+ timezone: values.timezone ? values.timezone.split("_")[1] : null,
108
+ scheduledAt: values.isScheduled ? getScheduledTimestamp(values) : null
109
+ });
110
+ },
111
+ initialValues: {
112
+ ...initialValues,
113
+ timezone: initialValues.timezone ? getTimezoneWithOffset() : systemTimezone.value
114
+ },
75
115
  validationSchema: RELEASE_SCHEMA,
76
- children: ({ values, errors, handleChange }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
77
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: /* @__PURE__ */ jsxRuntime.jsx(
78
- designSystem.TextInput,
79
- {
80
- label: formatMessage({
81
- id: "content-releases.modal.form.input.label.release-name",
82
- defaultMessage: "Name"
83
- }),
84
- name: "name",
85
- value: values.name,
86
- error: errors.name,
87
- onChange: handleChange,
88
- required: true
89
- }
90
- ) }),
116
+ validateOnChange: false,
117
+ children: ({ values, errors, handleChange, setFieldValue }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
118
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
119
+ /* @__PURE__ */ jsxRuntime.jsx(
120
+ designSystem.TextInput,
121
+ {
122
+ label: formatMessage({
123
+ id: "content-releases.modal.form.input.label.release-name",
124
+ defaultMessage: "Name"
125
+ }),
126
+ name: "name",
127
+ value: values.name,
128
+ error: errors.name,
129
+ onChange: handleChange,
130
+ required: true
131
+ }
132
+ ),
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) {
142
+ setFieldValue("date", null);
143
+ 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
+ ] })
219
+ ] })
220
+ ] }) }),
91
221
  /* @__PURE__ */ jsxRuntime.jsx(
92
222
  designSystem.ModalFooter,
93
223
  {
94
224
  startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }),
95
- endActions: /* @__PURE__ */ jsxRuntime.jsx(
96
- designSystem.Button,
225
+ endActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { name: "submit", loading: isLoading, type: "submit", children: formatMessage(
97
226
  {
98
- name: "submit",
99
- loading: isLoading,
100
- disabled: !values.name || values.name === initialValues.name,
101
- type: "submit",
102
- children: formatMessage(
103
- {
104
- id: "content-releases.modal.form.button.submit",
105
- defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
106
- },
107
- { isCreatingRelease }
108
- )
109
- }
110
- )
227
+ id: "content-releases.modal.form.button.submit",
228
+ defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
229
+ },
230
+ { isCreatingRelease }
231
+ ) })
111
232
  }
112
233
  )
113
234
  ] })
@@ -115,6 +236,375 @@ const ReleaseModal = ({
115
236
  )
116
237
  ] });
117
238
  };
239
+ const getTimezones = (selectedDate) => {
240
+ const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
241
+ const utcOffset = index.getTimezoneOffset(timezone, selectedDate);
242
+ return { offset: utcOffset, value: `${utcOffset}_${timezone}` };
243
+ });
244
+ const systemTimezone = timezoneList.find(
245
+ (timezone) => timezone.value.split("_")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
246
+ );
247
+ return { timezoneList, systemTimezone };
248
+ };
249
+ const TimezoneComponent = ({ timezoneOptions }) => {
250
+ const { values, errors, setFieldValue } = formik.useFormikContext();
251
+ const { formatMessage } = reactIntl.useIntl();
252
+ const [timezoneList, setTimezoneList] = React__namespace.useState(timezoneOptions);
253
+ React__namespace.useEffect(() => {
254
+ if (values.date) {
255
+ const { timezoneList: timezoneList2 } = getTimezones(new Date(values.date));
256
+ setTimezoneList(timezoneList2);
257
+ const updatedTimezone = values.timezone && timezoneList2.find((tz) => tz.value.split("_")[1] === values.timezone.split("_")[1]);
258
+ if (updatedTimezone) {
259
+ setFieldValue("timezone", updatedTimezone.value);
260
+ }
261
+ }
262
+ }, [setFieldValue, values.date, values.timezone]);
263
+ return /* @__PURE__ */ jsxRuntime.jsx(
264
+ designSystem.Combobox,
265
+ {
266
+ label: formatMessage({
267
+ id: "content-releases.modal.form.input.label.timezone",
268
+ defaultMessage: "Timezone"
269
+ }),
270
+ name: "timezone",
271
+ value: values.timezone || void 0,
272
+ textValue: values.timezone ? values.timezone.replace("_", " ") : void 0,
273
+ onChange: (timezone) => {
274
+ setFieldValue("timezone", timezone);
275
+ },
276
+ onTextValueChange: (timezone) => {
277
+ setFieldValue("timezone", timezone);
278
+ },
279
+ onClear: () => {
280
+ setFieldValue("timezone", "");
281
+ },
282
+ error: errors.timezone,
283
+ required: true,
284
+ children: timezoneList.map((timezone) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: timezone.value, children: timezone.value.replace("_", " ") }, timezone.value))
285
+ }
286
+ );
287
+ };
288
+ const LinkCard = styled__default.default(v2.Link)`
289
+ display: block;
290
+ `;
291
+ const CapitalizeRelativeTime = styled__default.default(helperPlugin.RelativeTime)`
292
+ text-transform: capitalize;
293
+ `;
294
+ const getBadgeProps = (status) => {
295
+ let color;
296
+ switch (status) {
297
+ case "ready":
298
+ color = "success";
299
+ break;
300
+ case "blocked":
301
+ color = "warning";
302
+ break;
303
+ case "failed":
304
+ color = "danger";
305
+ break;
306
+ case "done":
307
+ color = "primary";
308
+ break;
309
+ case "empty":
310
+ default:
311
+ color = "neutral";
312
+ }
313
+ return {
314
+ textColor: `${color}600`,
315
+ backgroundColor: `${color}100`,
316
+ borderColor: `${color}200`
317
+ };
318
+ };
319
+ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
320
+ const { formatMessage } = reactIntl.useIntl();
321
+ const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
322
+ if (isError) {
323
+ return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
324
+ }
325
+ if (releases?.length === 0) {
326
+ return /* @__PURE__ */ jsxRuntime.jsx(
327
+ designSystem.EmptyStateLayout,
328
+ {
329
+ content: formatMessage(
330
+ {
331
+ id: "content-releases.page.Releases.tab.emptyEntries",
332
+ defaultMessage: "No releases"
333
+ },
334
+ {
335
+ target: sectionTitle
336
+ }
337
+ ),
338
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.EmptyDocuments, { width: "10rem" })
339
+ }
340
+ );
341
+ }
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(
343
+ designSystem.Flex,
344
+ {
345
+ direction: "column",
346
+ justifyContent: "space-between",
347
+ padding: 4,
348
+ hasRadius: true,
349
+ background: "neutral0",
350
+ shadow: "tableShadow",
351
+ height: "100%",
352
+ width: "100%",
353
+ alignItems: "start",
354
+ gap: 4,
355
+ children: [
356
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "start", gap: 1, children: [
357
+ /* @__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({
359
+ id: "content-releases.pages.Releases.not-scheduled",
360
+ 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
+ ) })
368
+ ] }),
369
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { ...getBadgeProps(status), children: status })
370
+ ]
371
+ }
372
+ ) }) }, id)) });
373
+ };
374
+ const StyledAlert = styled__default.default(designSystem.Alert)`
375
+ button {
376
+ display: none;
377
+ }
378
+ p + div {
379
+ margin-left: auto;
380
+ }
381
+ `;
382
+ const INITIAL_FORM_VALUES = {
383
+ name: "",
384
+ date: null,
385
+ 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"),
388
+ scheduledAt: null,
389
+ timezone: null
390
+ };
391
+ const ReleasesPage = () => {
392
+ const tabRef = React__namespace.useRef(null);
393
+ const location = reactRouterDom.useLocation();
394
+ const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
395
+ const toggleNotification = helperPlugin.useNotification();
396
+ const { formatMessage } = reactIntl.useIntl();
397
+ const { push, replace } = reactRouterDom.useHistory();
398
+ const { formatAPIError } = helperPlugin.useAPIErrorHandler();
399
+ const [{ query }, setQuery] = helperPlugin.useQueryParams();
400
+ const response = index.useGetReleasesQuery(query);
401
+ const [createRelease, { isLoading: isSubmittingForm }] = index.useCreateReleaseMutation();
402
+ const { getFeature } = strapiAdmin.useLicenseLimits();
403
+ const { maximumReleases = 3 } = getFeature("cms-content-releases");
404
+ const { trackUsage } = helperPlugin.useTracking();
405
+ const { isLoading, isSuccess, isError } = response;
406
+ const activeTab = response?.currentData?.meta?.activeTab || "pending";
407
+ const activeTabIndex = ["pending", "done"].indexOf(activeTab);
408
+ React__namespace.useEffect(() => {
409
+ if (location?.state?.errors) {
410
+ toggleNotification({
411
+ type: "warning",
412
+ title: formatMessage({
413
+ id: "content-releases.pages.Releases.notification.error.title",
414
+ defaultMessage: "Your request could not be processed."
415
+ }),
416
+ message: formatMessage({
417
+ id: "content-releases.pages.Releases.notification.error.message",
418
+ defaultMessage: "Please try again or open another release."
419
+ })
420
+ });
421
+ replace({ state: null });
422
+ }
423
+ }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
424
+ React__namespace.useEffect(() => {
425
+ if (tabRef.current) {
426
+ tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
427
+ }
428
+ }, [activeTabIndex]);
429
+ const toggleAddReleaseModal = () => {
430
+ setReleaseModalShown((prev) => !prev);
431
+ };
432
+ if (isLoading) {
433
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
434
+ }
435
+ const totalPendingReleases = isSuccess && response.currentData?.meta?.pendingReleasesCount || 0;
436
+ const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
437
+ const handleTabChange = (index2) => {
438
+ setQuery({
439
+ ...query,
440
+ page: 1,
441
+ pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
442
+ filters: {
443
+ releasedAt: {
444
+ $notNull: index2 === 0 ? false : true
445
+ }
446
+ }
447
+ });
448
+ };
449
+ const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
450
+ const response2 = await createRelease({
451
+ name,
452
+ scheduledAt,
453
+ timezone
454
+ });
455
+ if ("data" in response2) {
456
+ toggleNotification({
457
+ type: "success",
458
+ message: formatMessage({
459
+ id: "content-releases.modal.release-created-notification-success",
460
+ defaultMessage: "Release created."
461
+ })
462
+ });
463
+ trackUsage("didCreateRelease");
464
+ push(`/plugins/content-releases/${response2.data.data.id}`);
465
+ } else if (index.isAxiosError(response2.error)) {
466
+ toggleNotification({
467
+ type: "warning",
468
+ message: formatAPIError(response2.error)
469
+ });
470
+ } else {
471
+ toggleNotification({
472
+ type: "warning",
473
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
474
+ });
475
+ }
476
+ };
477
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
478
+ /* @__PURE__ */ jsxRuntime.jsx(
479
+ designSystem.HeaderLayout,
480
+ {
481
+ title: formatMessage({
482
+ id: "content-releases.pages.Releases.title",
483
+ defaultMessage: "Releases"
484
+ }),
485
+ subtitle: formatMessage({
486
+ id: "content-releases.pages.Releases.header-subtitle",
487
+ defaultMessage: "Create and manage content updates"
488
+ }),
489
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.create, children: /* @__PURE__ */ jsxRuntime.jsx(
490
+ designSystem.Button,
491
+ {
492
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
493
+ onClick: toggleAddReleaseModal,
494
+ disabled: hasReachedMaximumPendingReleases,
495
+ children: formatMessage({
496
+ id: "content-releases.header.actions.add-release",
497
+ defaultMessage: "New release"
498
+ })
499
+ }
500
+ ) })
501
+ }
502
+ ),
503
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
504
+ hasReachedMaximumPendingReleases && /* @__PURE__ */ jsxRuntime.jsx(
505
+ StyledAlert,
506
+ {
507
+ marginBottom: 6,
508
+ action: /* @__PURE__ */ jsxRuntime.jsx(v2.Link, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
509
+ id: "content-releases.pages.Releases.max-limit-reached.action",
510
+ defaultMessage: "Explore plans"
511
+ }) }),
512
+ title: formatMessage(
513
+ {
514
+ id: "content-releases.pages.Releases.max-limit-reached.title",
515
+ defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
516
+ },
517
+ { number: maximumReleases }
518
+ ),
519
+ onClose: () => {
520
+ },
521
+ closeLabel: "",
522
+ children: formatMessage({
523
+ id: "content-releases.pages.Releases.max-limit-reached.message",
524
+ defaultMessage: "Upgrade to manage an unlimited number of releases."
525
+ })
526
+ }
527
+ ),
528
+ /* @__PURE__ */ jsxRuntime.jsxs(
529
+ designSystem.TabGroup,
530
+ {
531
+ label: formatMessage({
532
+ id: "content-releases.pages.Releases.tab-group.label",
533
+ defaultMessage: "Releases list"
534
+ }),
535
+ variant: "simple",
536
+ initialSelectedTabIndex: activeTabIndex,
537
+ onTabChange: handleTabChange,
538
+ ref: tabRef,
539
+ children: [
540
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingBottom: 8, children: [
541
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs, { children: [
542
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage(
543
+ {
544
+ id: "content-releases.pages.Releases.tab.pending",
545
+ defaultMessage: "Pending ({count})"
546
+ },
547
+ {
548
+ count: totalPendingReleases
549
+ }
550
+ ) }),
551
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage({
552
+ id: "content-releases.pages.Releases.tab.done",
553
+ defaultMessage: "Done"
554
+ }) })
555
+ ] }),
556
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {})
557
+ ] }),
558
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.TabPanels, { children: [
559
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
560
+ ReleasesGrid,
561
+ {
562
+ sectionTitle: "pending",
563
+ releases: response?.currentData?.data,
564
+ isError
565
+ }
566
+ ) }),
567
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
568
+ ReleasesGrid,
569
+ {
570
+ sectionTitle: "done",
571
+ releases: response?.currentData?.data,
572
+ isError
573
+ }
574
+ ) })
575
+ ] })
576
+ ]
577
+ }
578
+ ),
579
+ response.currentData?.meta?.pagination?.total ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
580
+ /* @__PURE__ */ jsxRuntime.jsx(
581
+ helperPlugin.PageSizeURLQuery,
582
+ {
583
+ options: ["8", "16", "32", "64"],
584
+ defaultValue: response?.currentData?.meta?.pagination?.pageSize.toString()
585
+ }
586
+ ),
587
+ /* @__PURE__ */ jsxRuntime.jsx(
588
+ helperPlugin.PaginationURLQuery,
589
+ {
590
+ pagination: {
591
+ pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
592
+ }
593
+ }
594
+ )
595
+ ] }) : null
596
+ ] }) }),
597
+ releaseModalShown && /* @__PURE__ */ jsxRuntime.jsx(
598
+ ReleaseModal,
599
+ {
600
+ handleClose: toggleAddReleaseModal,
601
+ handleSubmit: handleAddRelease,
602
+ isLoading: isSubmittingForm,
603
+ initialValues: INITIAL_FORM_VALUES
604
+ }
605
+ )
606
+ ] });
607
+ };
118
608
  const ReleaseInfoWrapper = styled__default.default(designSystem.Flex)`
119
609
  align-self: stretch;
120
610
  border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
@@ -128,6 +618,10 @@ const StyledMenuItem = styled__default.default(v2.Menu.Item)`
128
618
  span {
129
619
  color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
130
620
  }
621
+
622
+ &:hover {
623
+ background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
624
+ }
131
625
  `;
132
626
  const PencilIcon = styled__default.default(icons.Pencil)`
133
627
  width: ${({ theme }) => theme.spaces[3]};
@@ -194,7 +688,7 @@ const ReleaseDetailsLayout = ({
194
688
  toggleWarningSubmit,
195
689
  children
196
690
  }) => {
197
- const { formatMessage } = reactIntl.useIntl();
691
+ const { formatMessage, formatDate, formatTime } = reactIntl.useIntl();
198
692
  const { releaseId } = reactRouterDom.useParams();
199
693
  const {
200
694
  data,
@@ -276,18 +770,44 @@ const ReleaseDetailsLayout = ({
276
770
  }
277
771
  const totalEntries = release.actions.meta.count || 0;
278
772
  const hasCreatedByUser = Boolean(getCreatedByUser());
773
+ const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
774
+ const isScheduled = release.scheduledAt && release.timezone;
775
+ const numberOfEntriesText = formatMessage(
776
+ {
777
+ id: "content-releases.pages.Details.header-subtitle",
778
+ defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
779
+ },
780
+ { number: totalEntries }
781
+ );
782
+ const scheduledText = isScheduled ? formatMessage(
783
+ {
784
+ id: "content-releases.pages.ReleaseDetails.header-subtitle.scheduled",
785
+ defaultMessage: "Scheduled for {date} at {time} ({offset})"
786
+ },
787
+ {
788
+ date: formatDate(new Date(release.scheduledAt), {
789
+ weekday: "long",
790
+ day: "numeric",
791
+ month: "long",
792
+ year: "numeric",
793
+ timeZone: release.timezone
794
+ }),
795
+ time: formatTime(new Date(release.scheduledAt), {
796
+ timeZone: release.timezone,
797
+ hourCycle: "h23"
798
+ }),
799
+ offset: index.getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
800
+ }
801
+ ) : "";
279
802
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoadingDetails, children: [
280
803
  /* @__PURE__ */ jsxRuntime.jsx(
281
804
  designSystem.HeaderLayout,
282
805
  {
283
806
  title: release.name,
284
- subtitle: formatMessage(
285
- {
286
- id: "content-releases.pages.Details.header-subtitle",
287
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
288
- },
289
- { number: totalEntries }
290
- ),
807
+ 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}` : "") }),
809
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { ...getBadgeProps(release.status), children: release.status })
810
+ ] }),
291
811
  navigationAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
292
812
  id: "global.back",
293
813
  defaultMessage: "Back"
@@ -318,42 +838,28 @@ const ReleaseDetailsLayout = ({
318
838
  padding: 1,
319
839
  width: "100%",
320
840
  children: [
321
- /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxRuntime.jsxs(
322
- designSystem.Flex,
323
- {
324
- paddingTop: 2,
325
- paddingBottom: 2,
326
- alignItems: "center",
327
- gap: 2,
328
- hasRadius: true,
329
- width: "100%",
330
- children: [
331
- /* @__PURE__ */ jsxRuntime.jsx(PencilIcon, {}),
332
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: formatMessage({
333
- id: "content-releases.header.actions.edit",
334
- defaultMessage: "Edit"
335
- }) })
336
- ]
337
- }
338
- ) }),
339
- /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canDelete, onSelect: toggleWarningSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(
340
- designSystem.Flex,
841
+ /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
842
+ /* @__PURE__ */ jsxRuntime.jsx(PencilIcon, {}),
843
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: formatMessage({
844
+ id: "content-releases.header.actions.edit",
845
+ defaultMessage: "Edit"
846
+ }) })
847
+ ] }) }),
848
+ /* @__PURE__ */ jsxRuntime.jsx(
849
+ StyledMenuItem,
341
850
  {
342
- paddingTop: 2,
343
- paddingBottom: 2,
344
- alignItems: "center",
345
- gap: 2,
346
- hasRadius: true,
347
- width: "100%",
348
- children: [
851
+ disabled: !canDelete,
852
+ onSelect: toggleWarningSubmit,
853
+ variant: "danger",
854
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
349
855
  /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {}),
350
856
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
351
857
  id: "content-releases.header.actions.delete",
352
858
  defaultMessage: "Delete"
353
859
  }) })
354
- ]
860
+ ] })
355
861
  }
356
- ) })
862
+ )
357
863
  ]
358
864
  }
359
865
  ),
@@ -736,11 +1242,18 @@ const ReleaseDetailsPage = () => {
736
1242
  }
737
1243
  );
738
1244
  }
739
- const title = isSuccessDetails && data?.data?.name || "";
1245
+ const releaseData = isSuccessDetails && data?.data || null;
1246
+ const title = releaseData?.name || "";
1247
+ const timezone = releaseData?.timezone ?? null;
1248
+ 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;
1250
+ const time = scheduledAt ? format__default.default(scheduledAt, "HH:mm") : "";
740
1251
  const handleEditRelease = async (values) => {
741
1252
  const response = await updateRelease({
742
1253
  id: releaseId,
743
- name: values.name
1254
+ name: values.name,
1255
+ scheduledAt: values.scheduledAt,
1256
+ timezone: values.timezone
744
1257
  });
745
1258
  if ("data" in response) {
746
1259
  toggleNotification({
@@ -794,7 +1307,14 @@ const ReleaseDetailsPage = () => {
794
1307
  handleClose: toggleEditReleaseModal,
795
1308
  handleSubmit: handleEditRelease,
796
1309
  isLoading: isLoadingDetails || isSubmittingForm,
797
- initialValues: { name: title || "" }
1310
+ initialValues: {
1311
+ name: title || "",
1312
+ scheduledAt,
1313
+ date,
1314
+ time,
1315
+ isScheduled: Boolean(scheduledAt),
1316
+ timezone
1317
+ }
798
1318
  }
799
1319
  ),
800
1320
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -814,281 +1334,6 @@ const ReleaseDetailsPage = () => {
814
1334
  }
815
1335
  );
816
1336
  };
817
- const LinkCard = styled__default.default(v2.Link)`
818
- display: block;
819
- `;
820
- const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
821
- const { formatMessage } = reactIntl.useIntl();
822
- if (isError) {
823
- return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
824
- }
825
- if (releases?.length === 0) {
826
- return /* @__PURE__ */ jsxRuntime.jsx(
827
- designSystem.EmptyStateLayout,
828
- {
829
- content: formatMessage(
830
- {
831
- id: "content-releases.page.Releases.tab.emptyEntries",
832
- defaultMessage: "No releases"
833
- },
834
- {
835
- target: sectionTitle
836
- }
837
- ),
838
- icon: /* @__PURE__ */ jsxRuntime.jsx(icons.EmptyDocuments, { width: "10rem" })
839
- }
840
- );
841
- }
842
- 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(
843
- designSystem.Flex,
844
- {
845
- direction: "column",
846
- justifyContent: "space-between",
847
- padding: 4,
848
- hasRadius: true,
849
- background: "neutral0",
850
- shadow: "tableShadow",
851
- height: "100%",
852
- width: "100%",
853
- alignItems: "start",
854
- gap: 2,
855
- children: [
856
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
857
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", children: formatMessage(
858
- {
859
- id: "content-releases.page.Releases.release-item.entries",
860
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
861
- },
862
- { number: actions.meta.count }
863
- ) })
864
- ]
865
- }
866
- ) }) }, id)) });
867
- };
868
- const StyledAlert = styled__default.default(designSystem.Alert)`
869
- button {
870
- display: none;
871
- }
872
- p + div {
873
- margin-left: auto;
874
- }
875
- `;
876
- const INITIAL_FORM_VALUES = {
877
- name: ""
878
- };
879
- const ReleasesPage = () => {
880
- const tabRef = React__namespace.useRef(null);
881
- const location = reactRouterDom.useLocation();
882
- const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
883
- const toggleNotification = helperPlugin.useNotification();
884
- const { formatMessage } = reactIntl.useIntl();
885
- const { push, replace } = reactRouterDom.useHistory();
886
- const { formatAPIError } = helperPlugin.useAPIErrorHandler();
887
- const [{ query }, setQuery] = helperPlugin.useQueryParams();
888
- const response = index.useGetReleasesQuery(query);
889
- const [createRelease, { isLoading: isSubmittingForm }] = index.useCreateReleaseMutation();
890
- const { getFeature } = strapiAdmin.useLicenseLimits();
891
- const { maximumReleases = 3 } = getFeature("cms-content-releases");
892
- const { trackUsage } = helperPlugin.useTracking();
893
- const { isLoading, isSuccess, isError } = response;
894
- const activeTab = response?.currentData?.meta?.activeTab || "pending";
895
- const activeTabIndex = ["pending", "done"].indexOf(activeTab);
896
- React__namespace.useEffect(() => {
897
- if (location?.state?.errors) {
898
- toggleNotification({
899
- type: "warning",
900
- title: formatMessage({
901
- id: "content-releases.pages.Releases.notification.error.title",
902
- defaultMessage: "Your request could not be processed."
903
- }),
904
- message: formatMessage({
905
- id: "content-releases.pages.Releases.notification.error.message",
906
- defaultMessage: "Please try again or open another release."
907
- })
908
- });
909
- replace({ state: null });
910
- }
911
- }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
912
- React__namespace.useEffect(() => {
913
- if (tabRef.current) {
914
- tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
915
- }
916
- }, [activeTabIndex]);
917
- const toggleAddReleaseModal = () => {
918
- setReleaseModalShown((prev) => !prev);
919
- };
920
- if (isLoading) {
921
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
922
- }
923
- const totalReleases = isSuccess && response.currentData?.meta?.pagination?.total || 0;
924
- const hasReachedMaximumPendingReleases = totalReleases >= maximumReleases;
925
- const handleTabChange = (index2) => {
926
- setQuery({
927
- ...query,
928
- page: 1,
929
- pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
930
- filters: {
931
- releasedAt: {
932
- $notNull: index2 === 0 ? false : true
933
- }
934
- }
935
- });
936
- };
937
- const handleAddRelease = async (values) => {
938
- const response2 = await createRelease({
939
- name: values.name
940
- });
941
- if ("data" in response2) {
942
- toggleNotification({
943
- type: "success",
944
- message: formatMessage({
945
- id: "content-releases.modal.release-created-notification-success",
946
- defaultMessage: "Release created."
947
- })
948
- });
949
- trackUsage("didCreateRelease");
950
- push(`/plugins/content-releases/${response2.data.data.id}`);
951
- } else if (index.isAxiosError(response2.error)) {
952
- toggleNotification({
953
- type: "warning",
954
- message: formatAPIError(response2.error)
955
- });
956
- } else {
957
- toggleNotification({
958
- type: "warning",
959
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
960
- });
961
- }
962
- };
963
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
964
- /* @__PURE__ */ jsxRuntime.jsx(
965
- designSystem.HeaderLayout,
966
- {
967
- title: formatMessage({
968
- id: "content-releases.pages.Releases.title",
969
- defaultMessage: "Releases"
970
- }),
971
- subtitle: formatMessage(
972
- {
973
- id: "content-releases.pages.Releases.header-subtitle",
974
- defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
975
- },
976
- { number: totalReleases }
977
- ),
978
- primaryAction: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.create, children: /* @__PURE__ */ jsxRuntime.jsx(
979
- designSystem.Button,
980
- {
981
- startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
982
- onClick: toggleAddReleaseModal,
983
- disabled: hasReachedMaximumPendingReleases,
984
- children: formatMessage({
985
- id: "content-releases.header.actions.add-release",
986
- defaultMessage: "New release"
987
- })
988
- }
989
- ) })
990
- }
991
- ),
992
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
993
- activeTab === "pending" && hasReachedMaximumPendingReleases && /* @__PURE__ */ jsxRuntime.jsx(
994
- StyledAlert,
995
- {
996
- marginBottom: 6,
997
- action: /* @__PURE__ */ jsxRuntime.jsx(v2.Link, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
998
- id: "content-releases.pages.Releases.max-limit-reached.action",
999
- defaultMessage: "Explore plans"
1000
- }) }),
1001
- title: formatMessage(
1002
- {
1003
- id: "content-releases.pages.Releases.max-limit-reached.title",
1004
- defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
1005
- },
1006
- { number: maximumReleases }
1007
- ),
1008
- onClose: () => {
1009
- },
1010
- closeLabel: "",
1011
- children: formatMessage({
1012
- id: "content-releases.pages.Releases.max-limit-reached.message",
1013
- defaultMessage: "Upgrade to manage an unlimited number of releases."
1014
- })
1015
- }
1016
- ),
1017
- /* @__PURE__ */ jsxRuntime.jsxs(
1018
- designSystem.TabGroup,
1019
- {
1020
- label: formatMessage({
1021
- id: "content-releases.pages.Releases.tab-group.label",
1022
- defaultMessage: "Releases list"
1023
- }),
1024
- variant: "simple",
1025
- initialSelectedTabIndex: activeTabIndex,
1026
- onTabChange: handleTabChange,
1027
- ref: tabRef,
1028
- children: [
1029
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingBottom: 8, children: [
1030
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs, { children: [
1031
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage({
1032
- id: "content-releases.pages.Releases.tab.pending",
1033
- defaultMessage: "Pending"
1034
- }) }),
1035
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage({
1036
- id: "content-releases.pages.Releases.tab.done",
1037
- defaultMessage: "Done"
1038
- }) })
1039
- ] }),
1040
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {})
1041
- ] }),
1042
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.TabPanels, { children: [
1043
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
1044
- ReleasesGrid,
1045
- {
1046
- sectionTitle: "pending",
1047
- releases: response?.currentData?.data,
1048
- isError
1049
- }
1050
- ) }),
1051
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
1052
- ReleasesGrid,
1053
- {
1054
- sectionTitle: "done",
1055
- releases: response?.currentData?.data,
1056
- isError
1057
- }
1058
- ) })
1059
- ] })
1060
- ]
1061
- }
1062
- ),
1063
- totalReleases > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
1064
- /* @__PURE__ */ jsxRuntime.jsx(
1065
- helperPlugin.PageSizeURLQuery,
1066
- {
1067
- options: ["8", "16", "32", "64"],
1068
- defaultValue: response?.currentData?.meta?.pagination?.pageSize.toString()
1069
- }
1070
- ),
1071
- /* @__PURE__ */ jsxRuntime.jsx(
1072
- helperPlugin.PaginationURLQuery,
1073
- {
1074
- pagination: {
1075
- pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
1076
- }
1077
- }
1078
- )
1079
- ] })
1080
- ] }) }),
1081
- releaseModalShown && /* @__PURE__ */ jsxRuntime.jsx(
1082
- ReleaseModal,
1083
- {
1084
- handleClose: toggleAddReleaseModal,
1085
- handleSubmit: handleAddRelease,
1086
- isLoading: isSubmittingForm,
1087
- initialValues: INITIAL_FORM_VALUES
1088
- }
1089
- )
1090
- ] });
1091
- };
1092
1337
  const App = () => {
1093
1338
  return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPagePermissions, { permissions: index.PERMISSIONS.main, children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Switch, { children: [
1094
1339
  /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { exact: true, path: `/plugins/${index.pluginId}`, component: ReleasesPage }),
@@ -1096,4 +1341,4 @@ const App = () => {
1096
1341
  ] }) });
1097
1342
  };
1098
1343
  exports.App = App;
1099
- //# sourceMappingURL=App-1hHIqUoZ.js.map
1344
+ //# sourceMappingURL=App-P1kyM3gT.js.map