@strapi/content-releases 0.0.0-next.d10040847b91742ccb8083938399b63ffa289c7a → 0.0.0-next.e09d30edcbd16960a838997778a31d50e9c60bc4

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,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const helperPlugin = require("@strapi/helper-plugin");
5
5
  const reactRouterDom = require("react-router-dom");
6
- const index = require("./index-ItlgrLcr.js");
6
+ const index = require("./index-mrnUzPlo.js");
7
7
  const React = require("react");
8
8
  const strapiAdmin = require("@strapi/admin/strapi-admin");
9
9
  const designSystem = require("@strapi/design-system");
@@ -267,6 +267,7 @@ const TimezoneComponent = ({ timezoneOptions }) => {
267
267
  id: "content-releases.modal.form.input.label.timezone",
268
268
  defaultMessage: "Timezone"
269
269
  }),
270
+ autocomplete: { type: "list", filter: "contains" },
270
271
  name: "timezone",
271
272
  value: values.timezone || void 0,
272
273
  textValue: values.timezone ? values.timezone.replace("_", " ") : void 0,
@@ -285,126 +286,187 @@ const TimezoneComponent = ({ timezoneOptions }) => {
285
286
  }
286
287
  );
287
288
  };
288
- const ReleaseInfoWrapper = styled__default.default(designSystem.Flex)`
289
- align-self: stretch;
290
- border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
291
- border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
292
- border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
289
+ const LinkCard = styled__default.default(v2.Link)`
290
+ display: block;
293
291
  `;
294
- const StyledMenuItem = styled__default.default(v2.Menu.Item)`
295
- svg path {
296
- fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
292
+ const CapitalizeRelativeTime = styled__default.default(helperPlugin.RelativeTime)`
293
+ text-transform: capitalize;
294
+ `;
295
+ const getBadgeProps = (status) => {
296
+ let color;
297
+ switch (status) {
298
+ case "ready":
299
+ color = "success";
300
+ break;
301
+ case "blocked":
302
+ color = "warning";
303
+ break;
304
+ case "failed":
305
+ color = "danger";
306
+ break;
307
+ case "done":
308
+ color = "primary";
309
+ break;
310
+ case "empty":
311
+ default:
312
+ color = "neutral";
297
313
  }
298
- span {
299
- color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
314
+ return {
315
+ textColor: `${color}600`,
316
+ backgroundColor: `${color}100`,
317
+ borderColor: `${color}200`
318
+ };
319
+ };
320
+ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
321
+ const { formatMessage } = reactIntl.useIntl();
322
+ const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
323
+ if (isError) {
324
+ return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
300
325
  }
301
-
302
- &:hover {
303
- background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
326
+ if (releases?.length === 0) {
327
+ return /* @__PURE__ */ jsxRuntime.jsx(
328
+ designSystem.EmptyStateLayout,
329
+ {
330
+ content: formatMessage(
331
+ {
332
+ id: "content-releases.page.Releases.tab.emptyEntries",
333
+ defaultMessage: "No releases"
334
+ },
335
+ {
336
+ target: sectionTitle
337
+ }
338
+ ),
339
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.EmptyDocuments, { width: "10rem" })
340
+ }
341
+ );
304
342
  }
305
- `;
306
- const PencilIcon = styled__default.default(icons.Pencil)`
307
- width: ${({ theme }) => theme.spaces[3]};
308
- height: ${({ theme }) => theme.spaces[3]};
309
- path {
310
- fill: ${({ theme }) => theme.colors.neutral600};
343
+ 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(
344
+ designSystem.Flex,
345
+ {
346
+ direction: "column",
347
+ justifyContent: "space-between",
348
+ padding: 4,
349
+ hasRadius: true,
350
+ background: "neutral0",
351
+ shadow: "tableShadow",
352
+ height: "100%",
353
+ width: "100%",
354
+ alignItems: "start",
355
+ gap: 4,
356
+ children: [
357
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "start", gap: 1, children: [
358
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
359
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: IsSchedulingEnabled ? scheduledAt ? /* @__PURE__ */ jsxRuntime.jsx(CapitalizeRelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
360
+ id: "content-releases.pages.Releases.not-scheduled",
361
+ defaultMessage: "Not scheduled"
362
+ }) : formatMessage(
363
+ {
364
+ id: "content-releases.page.Releases.release-item.entries",
365
+ defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
366
+ },
367
+ { number: actions.meta.count }
368
+ ) })
369
+ ] }),
370
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { ...getBadgeProps(status), children: status })
371
+ ]
372
+ }
373
+ ) }) }, id)) });
374
+ };
375
+ const StyledAlert = styled__default.default(designSystem.Alert)`
376
+ button {
377
+ display: none;
311
378
  }
312
- `;
313
- const TrashIcon = styled__default.default(icons.Trash)`
314
- width: ${({ theme }) => theme.spaces[3]};
315
- height: ${({ theme }) => theme.spaces[3]};
316
- path {
317
- fill: ${({ theme }) => theme.colors.danger600};
379
+ p + div {
380
+ margin-left: auto;
318
381
  }
319
382
  `;
320
- const TypographyMaxWidth = styled__default.default(designSystem.Typography)`
321
- max-width: 300px;
322
- `;
323
- const EntryValidationText = ({ action, schema, components, entry }) => {
324
- const { formatMessage } = reactIntl.useIntl();
325
- const { validate } = strapiAdmin.unstable_useDocument();
326
- const { errors } = validate(entry, {
327
- contentType: schema,
328
- components,
329
- isCreatingEntry: false
330
- });
331
- if (Object.keys(errors).length > 0) {
332
- const validationErrorsMessages = Object.entries(errors).map(
333
- ([key, value]) => formatMessage(
334
- { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
335
- { field: key }
336
- )
337
- ).join(" ");
338
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
339
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "danger600", as: icons.CrossCircle }),
340
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
341
- ] });
342
- }
343
- if (action == "publish") {
344
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
345
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "success600", as: icons.CheckCircle }),
346
- entry.publishedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
347
- id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
348
- defaultMessage: "Already published"
349
- }) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
350
- id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
351
- defaultMessage: "Ready to publish"
352
- }) })
353
- ] });
354
- }
355
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
356
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "success600", as: icons.CheckCircle }),
357
- !entry.publishedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
358
- id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
359
- defaultMessage: "Already unpublished"
360
- }) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
361
- id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish",
362
- defaultMessage: "Ready to unpublish"
363
- }) })
364
- ] });
383
+ const INITIAL_FORM_VALUES = {
384
+ name: "",
385
+ date: null,
386
+ time: "",
387
+ // Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
388
+ isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
389
+ scheduledAt: null,
390
+ timezone: null
365
391
  };
366
- const ReleaseDetailsLayout = ({
367
- toggleEditReleaseModal,
368
- toggleWarningSubmit,
369
- children
370
- }) => {
371
- const { formatMessage, formatDate, formatTime } = reactIntl.useIntl();
372
- const { releaseId } = reactRouterDom.useParams();
373
- const {
374
- data,
375
- isLoading: isLoadingDetails,
376
- isError,
377
- error
378
- } = index.useGetReleaseQuery({ id: releaseId });
379
- const [publishRelease, { isLoading: isPublishing }] = index.usePublishReleaseMutation();
392
+ const ReleasesPage = () => {
393
+ const tabRef = React__namespace.useRef(null);
394
+ const location = reactRouterDom.useLocation();
395
+ const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
380
396
  const toggleNotification = helperPlugin.useNotification();
397
+ const { formatMessage } = reactIntl.useIntl();
398
+ const { push, replace } = reactRouterDom.useHistory();
381
399
  const { formatAPIError } = helperPlugin.useAPIErrorHandler();
382
- const {
383
- allowedActions: { canUpdate, canDelete }
384
- } = helperPlugin.useRBAC(index.PERMISSIONS);
385
- const dispatch = index.useTypedDispatch();
400
+ const [{ query }, setQuery] = helperPlugin.useQueryParams();
401
+ const response = index.useGetReleasesQuery(query);
402
+ const [createRelease, { isLoading: isSubmittingForm }] = index.useCreateReleaseMutation();
403
+ const { getFeature } = strapiAdmin.useLicenseLimits();
404
+ const { maximumReleases = 3 } = getFeature("cms-content-releases");
386
405
  const { trackUsage } = helperPlugin.useTracking();
387
- const release = data?.data;
388
- const handlePublishRelease = async () => {
389
- const response = await publishRelease({ id: releaseId });
390
- if ("data" in response) {
406
+ const { isLoading, isSuccess, isError } = response;
407
+ const activeTab = response?.currentData?.meta?.activeTab || "pending";
408
+ const activeTabIndex = ["pending", "done"].indexOf(activeTab);
409
+ React__namespace.useEffect(() => {
410
+ if (location?.state?.errors) {
391
411
  toggleNotification({
392
- type: "success",
412
+ type: "warning",
413
+ title: formatMessage({
414
+ id: "content-releases.pages.Releases.notification.error.title",
415
+ defaultMessage: "Your request could not be processed."
416
+ }),
393
417
  message: formatMessage({
394
- id: "content-releases.pages.ReleaseDetails.publish-notification-success",
395
- defaultMessage: "Release was published successfully."
418
+ id: "content-releases.pages.Releases.notification.error.message",
419
+ defaultMessage: "Please try again or open another release."
396
420
  })
397
421
  });
398
- const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
399
- trackUsage("didPublishRelease", {
400
- totalEntries: totalEntries2,
401
- totalPublishedEntries,
402
- totalUnpublishedEntries
422
+ replace({ state: null });
423
+ }
424
+ }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
425
+ React__namespace.useEffect(() => {
426
+ if (tabRef.current) {
427
+ tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
428
+ }
429
+ }, [activeTabIndex]);
430
+ const toggleAddReleaseModal = () => {
431
+ setReleaseModalShown((prev) => !prev);
432
+ };
433
+ if (isLoading) {
434
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
435
+ }
436
+ const totalPendingReleases = isSuccess && response.currentData?.meta?.pendingReleasesCount || 0;
437
+ const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
438
+ const handleTabChange = (index2) => {
439
+ setQuery({
440
+ ...query,
441
+ page: 1,
442
+ pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
443
+ filters: {
444
+ releasedAt: {
445
+ $notNull: index2 === 0 ? false : true
446
+ }
447
+ }
448
+ });
449
+ };
450
+ const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
451
+ const response2 = await createRelease({
452
+ name,
453
+ scheduledAt,
454
+ timezone
455
+ });
456
+ if ("data" in response2) {
457
+ toggleNotification({
458
+ type: "success",
459
+ message: formatMessage({
460
+ id: "content-releases.modal.release-created-notification-success",
461
+ defaultMessage: "Release created."
462
+ })
403
463
  });
404
- } else if (index.isAxiosError(response.error)) {
464
+ trackUsage("didCreateRelease");
465
+ push(`/plugins/content-releases/${response2.data.data.id}`);
466
+ } else if (index.isAxiosError(response2.error)) {
405
467
  toggleNotification({
406
468
  type: "warning",
407
- message: formatAPIError(response.error)
469
+ message: formatAPIError(response2.error)
408
470
  });
409
471
  } else {
410
472
  toggleNotification({
@@ -413,31 +475,290 @@ const ReleaseDetailsLayout = ({
413
475
  });
414
476
  }
415
477
  };
416
- const handleRefresh = () => {
417
- dispatch(index.releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
418
- };
419
- const getCreatedByUser = () => {
420
- if (!release?.createdBy) {
421
- return null;
422
- }
423
- if (release.createdBy.username) {
424
- return release.createdBy.username;
425
- }
426
- if (release.createdBy.firstname) {
427
- return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
428
- }
429
- return release.createdBy.email;
430
- };
431
- if (isLoadingDetails) {
432
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
433
- }
434
- if (isError || !release) {
435
- return /* @__PURE__ */ jsxRuntime.jsx(
436
- reactRouterDom.Redirect,
478
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
479
+ /* @__PURE__ */ jsxRuntime.jsx(
480
+ designSystem.HeaderLayout,
437
481
  {
438
- to: {
439
- pathname: "/plugins/content-releases",
440
- state: {
482
+ title: formatMessage({
483
+ id: "content-releases.pages.Releases.title",
484
+ defaultMessage: "Releases"
485
+ }),
486
+ subtitle: formatMessage({
487
+ id: "content-releases.pages.Releases.header-subtitle",
488
+ defaultMessage: "Create and manage content updates"
489
+ }),
490
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.create, children: /* @__PURE__ */ jsxRuntime.jsx(
491
+ designSystem.Button,
492
+ {
493
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
494
+ onClick: toggleAddReleaseModal,
495
+ disabled: hasReachedMaximumPendingReleases,
496
+ children: formatMessage({
497
+ id: "content-releases.header.actions.add-release",
498
+ defaultMessage: "New release"
499
+ })
500
+ }
501
+ ) })
502
+ }
503
+ ),
504
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
505
+ hasReachedMaximumPendingReleases && /* @__PURE__ */ jsxRuntime.jsx(
506
+ StyledAlert,
507
+ {
508
+ marginBottom: 6,
509
+ action: /* @__PURE__ */ jsxRuntime.jsx(v2.Link, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
510
+ id: "content-releases.pages.Releases.max-limit-reached.action",
511
+ defaultMessage: "Explore plans"
512
+ }) }),
513
+ title: formatMessage(
514
+ {
515
+ id: "content-releases.pages.Releases.max-limit-reached.title",
516
+ defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
517
+ },
518
+ { number: maximumReleases }
519
+ ),
520
+ onClose: () => {
521
+ },
522
+ closeLabel: "",
523
+ children: formatMessage({
524
+ id: "content-releases.pages.Releases.max-limit-reached.message",
525
+ defaultMessage: "Upgrade to manage an unlimited number of releases."
526
+ })
527
+ }
528
+ ),
529
+ /* @__PURE__ */ jsxRuntime.jsxs(
530
+ designSystem.TabGroup,
531
+ {
532
+ label: formatMessage({
533
+ id: "content-releases.pages.Releases.tab-group.label",
534
+ defaultMessage: "Releases list"
535
+ }),
536
+ variant: "simple",
537
+ initialSelectedTabIndex: activeTabIndex,
538
+ onTabChange: handleTabChange,
539
+ ref: tabRef,
540
+ children: [
541
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingBottom: 8, children: [
542
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs, { children: [
543
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage(
544
+ {
545
+ id: "content-releases.pages.Releases.tab.pending",
546
+ defaultMessage: "Pending ({count})"
547
+ },
548
+ {
549
+ count: totalPendingReleases
550
+ }
551
+ ) }),
552
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage({
553
+ id: "content-releases.pages.Releases.tab.done",
554
+ defaultMessage: "Done"
555
+ }) })
556
+ ] }),
557
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {})
558
+ ] }),
559
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.TabPanels, { children: [
560
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
561
+ ReleasesGrid,
562
+ {
563
+ sectionTitle: "pending",
564
+ releases: response?.currentData?.data,
565
+ isError
566
+ }
567
+ ) }),
568
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
569
+ ReleasesGrid,
570
+ {
571
+ sectionTitle: "done",
572
+ releases: response?.currentData?.data,
573
+ isError
574
+ }
575
+ ) })
576
+ ] })
577
+ ]
578
+ }
579
+ ),
580
+ response.currentData?.meta?.pagination?.total ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
581
+ /* @__PURE__ */ jsxRuntime.jsx(
582
+ helperPlugin.PageSizeURLQuery,
583
+ {
584
+ options: ["8", "16", "32", "64"],
585
+ defaultValue: response?.currentData?.meta?.pagination?.pageSize.toString()
586
+ }
587
+ ),
588
+ /* @__PURE__ */ jsxRuntime.jsx(
589
+ helperPlugin.PaginationURLQuery,
590
+ {
591
+ pagination: {
592
+ pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
593
+ }
594
+ }
595
+ )
596
+ ] }) : null
597
+ ] }) }),
598
+ releaseModalShown && /* @__PURE__ */ jsxRuntime.jsx(
599
+ ReleaseModal,
600
+ {
601
+ handleClose: toggleAddReleaseModal,
602
+ handleSubmit: handleAddRelease,
603
+ isLoading: isSubmittingForm,
604
+ initialValues: INITIAL_FORM_VALUES
605
+ }
606
+ )
607
+ ] });
608
+ };
609
+ const ReleaseInfoWrapper = styled__default.default(designSystem.Flex)`
610
+ align-self: stretch;
611
+ border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
612
+ border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
613
+ border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
614
+ `;
615
+ const StyledMenuItem = styled__default.default(v2.Menu.Item)`
616
+ svg path {
617
+ fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
618
+ }
619
+ span {
620
+ color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
621
+ }
622
+
623
+ &:hover {
624
+ background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
625
+ }
626
+ `;
627
+ const PencilIcon = styled__default.default(icons.Pencil)`
628
+ width: ${({ theme }) => theme.spaces[3]};
629
+ height: ${({ theme }) => theme.spaces[3]};
630
+ path {
631
+ fill: ${({ theme }) => theme.colors.neutral600};
632
+ }
633
+ `;
634
+ const TrashIcon = styled__default.default(icons.Trash)`
635
+ width: ${({ theme }) => theme.spaces[3]};
636
+ height: ${({ theme }) => theme.spaces[3]};
637
+ path {
638
+ fill: ${({ theme }) => theme.colors.danger600};
639
+ }
640
+ `;
641
+ const TypographyMaxWidth = styled__default.default(designSystem.Typography)`
642
+ max-width: 300px;
643
+ `;
644
+ const EntryValidationText = ({ action, schema, components, entry }) => {
645
+ const { formatMessage } = reactIntl.useIntl();
646
+ const { validate } = strapiAdmin.unstable_useDocument();
647
+ const { errors } = validate(entry, {
648
+ contentType: schema,
649
+ components,
650
+ isCreatingEntry: false
651
+ });
652
+ if (Object.keys(errors).length > 0) {
653
+ const validationErrorsMessages = Object.entries(errors).map(
654
+ ([key, value]) => formatMessage(
655
+ { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
656
+ { field: key }
657
+ )
658
+ ).join(" ");
659
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
660
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "danger600", as: icons.CrossCircle }),
661
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
662
+ ] });
663
+ }
664
+ if (action == "publish") {
665
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
666
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "success600", as: icons.CheckCircle }),
667
+ entry.publishedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
668
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
669
+ defaultMessage: "Already published"
670
+ }) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
671
+ id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
672
+ defaultMessage: "Ready to publish"
673
+ }) })
674
+ ] });
675
+ }
676
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
677
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "success600", as: icons.CheckCircle }),
678
+ !entry.publishedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
679
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
680
+ defaultMessage: "Already unpublished"
681
+ }) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
682
+ id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish",
683
+ defaultMessage: "Ready to unpublish"
684
+ }) })
685
+ ] });
686
+ };
687
+ const ReleaseDetailsLayout = ({
688
+ toggleEditReleaseModal,
689
+ toggleWarningSubmit,
690
+ children
691
+ }) => {
692
+ const { formatMessage, formatDate, formatTime } = reactIntl.useIntl();
693
+ const { releaseId } = reactRouterDom.useParams();
694
+ const {
695
+ data,
696
+ isLoading: isLoadingDetails,
697
+ isError,
698
+ error
699
+ } = index.useGetReleaseQuery({ id: releaseId });
700
+ const [publishRelease, { isLoading: isPublishing }] = index.usePublishReleaseMutation();
701
+ const toggleNotification = helperPlugin.useNotification();
702
+ const { formatAPIError } = helperPlugin.useAPIErrorHandler();
703
+ const {
704
+ allowedActions: { canUpdate, canDelete }
705
+ } = helperPlugin.useRBAC(index.PERMISSIONS);
706
+ const dispatch = index.useTypedDispatch();
707
+ const { trackUsage } = helperPlugin.useTracking();
708
+ const release = data?.data;
709
+ const handlePublishRelease = async () => {
710
+ const response = await publishRelease({ id: releaseId });
711
+ if ("data" in response) {
712
+ toggleNotification({
713
+ type: "success",
714
+ message: formatMessage({
715
+ id: "content-releases.pages.ReleaseDetails.publish-notification-success",
716
+ defaultMessage: "Release was published successfully."
717
+ })
718
+ });
719
+ const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
720
+ trackUsage("didPublishRelease", {
721
+ totalEntries: totalEntries2,
722
+ totalPublishedEntries,
723
+ totalUnpublishedEntries
724
+ });
725
+ } else if (index.isAxiosError(response.error)) {
726
+ toggleNotification({
727
+ type: "warning",
728
+ message: formatAPIError(response.error)
729
+ });
730
+ } else {
731
+ toggleNotification({
732
+ type: "warning",
733
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
734
+ });
735
+ }
736
+ };
737
+ const handleRefresh = () => {
738
+ dispatch(index.releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
739
+ };
740
+ const getCreatedByUser = () => {
741
+ if (!release?.createdBy) {
742
+ return null;
743
+ }
744
+ if (release.createdBy.username) {
745
+ return release.createdBy.username;
746
+ }
747
+ if (release.createdBy.firstname) {
748
+ return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
749
+ }
750
+ return release.createdBy.email;
751
+ };
752
+ if (isLoadingDetails) {
753
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
754
+ }
755
+ if (isError || !release) {
756
+ return /* @__PURE__ */ jsxRuntime.jsx(
757
+ reactRouterDom.Redirect,
758
+ {
759
+ to: {
760
+ pathname: "/plugins/content-releases",
761
+ state: {
441
762
  errors: [
442
763
  {
443
764
  code: error?.code
@@ -484,7 +805,10 @@ const ReleaseDetailsLayout = ({
484
805
  designSystem.HeaderLayout,
485
806
  {
486
807
  title: release.name,
487
- subtitle: numberOfEntriesText + (IsSchedulingEnabled && isScheduled ? ` - ${scheduledText}` : ""),
808
+ subtitle: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, lineHeight: 6, children: [
809
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", variant: "epsilon", children: numberOfEntriesText + (IsSchedulingEnabled && isScheduled ? ` - ${scheduledText}` : "") }),
810
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { ...getBadgeProps(release.status), children: release.status })
811
+ ] }),
488
812
  navigationAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
489
813
  id: "global.back",
490
814
  defaultMessage: "Back"
@@ -879,288 +1203,71 @@ const ReleaseDetailsBody = () => {
879
1203
  ] }, `releases-group-${key}`)),
880
1204
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
881
1205
  /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.PageSizeURLQuery, { defaultValue: releaseMeta?.pagination?.pageSize.toString() }),
882
- /* @__PURE__ */ jsxRuntime.jsx(
883
- helperPlugin.PaginationURLQuery,
884
- {
885
- pagination: {
886
- pageCount: releaseMeta?.pagination?.pageCount || 0
887
- }
888
- }
889
- )
890
- ] })
891
- ] }) });
892
- };
893
- const ReleaseDetailsPage = () => {
894
- const { formatMessage } = reactIntl.useIntl();
895
- const { releaseId } = reactRouterDom.useParams();
896
- const toggleNotification = helperPlugin.useNotification();
897
- const { formatAPIError } = helperPlugin.useAPIErrorHandler();
898
- const { push } = reactRouterDom.useHistory();
899
- const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
900
- const [showWarningSubmit, setWarningSubmit] = React__namespace.useState(false);
901
- const {
902
- isLoading: isLoadingDetails,
903
- data,
904
- isSuccess: isSuccessDetails
905
- } = index.useGetReleaseQuery({ id: releaseId });
906
- const [updateRelease, { isLoading: isSubmittingForm }] = index.useUpdateReleaseMutation();
907
- const [deleteRelease, { isLoading: isDeletingRelease }] = index.useDeleteReleaseMutation();
908
- const toggleEditReleaseModal = () => {
909
- setReleaseModalShown((prev) => !prev);
910
- };
911
- const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);
912
- if (isLoadingDetails) {
913
- return /* @__PURE__ */ jsxRuntime.jsx(
914
- ReleaseDetailsLayout,
915
- {
916
- toggleEditReleaseModal,
917
- toggleWarningSubmit,
918
- children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) })
919
- }
920
- );
921
- }
922
- const releaseData = isSuccessDetails && data?.data || null;
923
- const title = releaseData?.name || "";
924
- const timezone = releaseData?.timezone ?? null;
925
- const scheduledAt = releaseData?.scheduledAt && timezone ? dateFnsTz.utcToZonedTime(releaseData.scheduledAt, timezone) : null;
926
- const date = scheduledAt ? new Date(format__default.default(scheduledAt, "yyyy-MM-dd")) : null;
927
- const time = scheduledAt ? format__default.default(scheduledAt, "HH:mm") : "";
928
- const handleEditRelease = async (values) => {
929
- const response = await updateRelease({
930
- id: releaseId,
931
- name: values.name,
932
- scheduledAt: values.scheduledAt,
933
- timezone: values.timezone
934
- });
935
- if ("data" in response) {
936
- toggleNotification({
937
- type: "success",
938
- message: formatMessage({
939
- id: "content-releases.modal.release-updated-notification-success",
940
- defaultMessage: "Release updated."
941
- })
942
- });
943
- } else if (index.isAxiosError(response.error)) {
944
- toggleNotification({
945
- type: "warning",
946
- message: formatAPIError(response.error)
947
- });
948
- } else {
949
- toggleNotification({
950
- type: "warning",
951
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
952
- });
953
- }
954
- toggleEditReleaseModal();
955
- };
956
- const handleDeleteRelease = async () => {
957
- const response = await deleteRelease({
958
- id: releaseId
959
- });
960
- if ("data" in response) {
961
- push("/plugins/content-releases");
962
- } else if (index.isAxiosError(response.error)) {
963
- toggleNotification({
964
- type: "warning",
965
- message: formatAPIError(response.error)
966
- });
967
- } else {
968
- toggleNotification({
969
- type: "warning",
970
- message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
971
- });
972
- }
973
- };
974
- return /* @__PURE__ */ jsxRuntime.jsxs(
975
- ReleaseDetailsLayout,
976
- {
977
- toggleEditReleaseModal,
978
- toggleWarningSubmit,
979
- children: [
980
- /* @__PURE__ */ jsxRuntime.jsx(ReleaseDetailsBody, {}),
981
- releaseModalShown && /* @__PURE__ */ jsxRuntime.jsx(
982
- ReleaseModal,
983
- {
984
- handleClose: toggleEditReleaseModal,
985
- handleSubmit: handleEditRelease,
986
- isLoading: isLoadingDetails || isSubmittingForm,
987
- initialValues: {
988
- name: title || "",
989
- scheduledAt,
990
- date,
991
- time,
992
- isScheduled: Boolean(scheduledAt),
993
- timezone
994
- }
995
- }
996
- ),
997
- /* @__PURE__ */ jsxRuntime.jsx(
998
- helperPlugin.ConfirmDialog,
999
- {
1000
- bodyText: {
1001
- id: "content-releases.dialog.confirmation-message",
1002
- defaultMessage: "Are you sure you want to delete this release?"
1003
- },
1004
- isOpen: showWarningSubmit,
1005
- isConfirmButtonLoading: isDeletingRelease,
1006
- onToggleDialog: toggleWarningSubmit,
1007
- onConfirm: handleDeleteRelease
1008
- }
1009
- )
1010
- ]
1011
- }
1012
- );
1013
- };
1014
- const LinkCard = styled__default.default(v2.Link)`
1015
- display: block;
1016
- `;
1017
- const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
1018
- const { formatMessage } = reactIntl.useIntl();
1019
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
1020
- if (isError) {
1021
- return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
1022
- }
1023
- if (releases?.length === 0) {
1024
- return /* @__PURE__ */ jsxRuntime.jsx(
1025
- designSystem.EmptyStateLayout,
1026
- {
1027
- content: formatMessage(
1028
- {
1029
- id: "content-releases.page.Releases.tab.emptyEntries",
1030
- defaultMessage: "No releases"
1031
- },
1032
- {
1033
- target: sectionTitle
1034
- }
1035
- ),
1036
- icon: /* @__PURE__ */ jsxRuntime.jsx(icons.EmptyDocuments, { width: "10rem" })
1037
- }
1038
- );
1039
- }
1040
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid, { gap: 4, children: releases.map(({ id, name, actions, scheduledAt }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.GridItem, { col: 3, s: 6, xs: 12, children: /* @__PURE__ */ jsxRuntime.jsx(LinkCard, { href: `content-releases/${id}`, isExternal: false, children: /* @__PURE__ */ jsxRuntime.jsxs(
1041
- designSystem.Flex,
1042
- {
1043
- direction: "column",
1044
- justifyContent: "space-between",
1045
- padding: 4,
1046
- hasRadius: true,
1047
- background: "neutral0",
1048
- shadow: "tableShadow",
1049
- height: "100%",
1050
- width: "100%",
1051
- alignItems: "start",
1052
- gap: 2,
1053
- children: [
1054
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
1055
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: IsSchedulingEnabled ? scheduledAt ? /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
1056
- id: "content-releases.pages.Releases.not-scheduled",
1057
- defaultMessage: "Not scheduled"
1058
- }) : formatMessage(
1059
- {
1060
- id: "content-releases.page.Releases.release-item.entries",
1061
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
1062
- },
1063
- { number: actions.meta.count }
1064
- ) })
1065
- ]
1066
- }
1067
- ) }) }, id)) });
1068
- };
1069
- const StyledAlert = styled__default.default(designSystem.Alert)`
1070
- button {
1071
- display: none;
1072
- }
1073
- p + div {
1074
- margin-left: auto;
1075
- }
1076
- `;
1077
- const INITIAL_FORM_VALUES = {
1078
- name: "",
1079
- date: null,
1080
- time: "",
1081
- // Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
1082
- isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
1083
- scheduledAt: null,
1084
- timezone: null
1085
- };
1086
- const ReleasesPage = () => {
1087
- const tabRef = React__namespace.useRef(null);
1088
- const location = reactRouterDom.useLocation();
1089
- const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
1090
- const toggleNotification = helperPlugin.useNotification();
1091
- const { formatMessage } = reactIntl.useIntl();
1092
- const { push, replace } = reactRouterDom.useHistory();
1093
- const { formatAPIError } = helperPlugin.useAPIErrorHandler();
1094
- const [{ query }, setQuery] = helperPlugin.useQueryParams();
1095
- const response = index.useGetReleasesQuery(query);
1096
- const [createRelease, { isLoading: isSubmittingForm }] = index.useCreateReleaseMutation();
1097
- const { getFeature } = strapiAdmin.useLicenseLimits();
1098
- const { maximumReleases = 3 } = getFeature("cms-content-releases");
1099
- const { trackUsage } = helperPlugin.useTracking();
1100
- const { isLoading, isSuccess, isError } = response;
1101
- const activeTab = response?.currentData?.meta?.activeTab || "pending";
1102
- const activeTabIndex = ["pending", "done"].indexOf(activeTab);
1103
- React__namespace.useEffect(() => {
1104
- if (location?.state?.errors) {
1105
- toggleNotification({
1106
- type: "warning",
1107
- title: formatMessage({
1108
- id: "content-releases.pages.Releases.notification.error.title",
1109
- defaultMessage: "Your request could not be processed."
1110
- }),
1111
- message: formatMessage({
1112
- id: "content-releases.pages.Releases.notification.error.message",
1113
- defaultMessage: "Please try again or open another release."
1114
- })
1115
- });
1116
- replace({ state: null });
1117
- }
1118
- }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
1119
- React__namespace.useEffect(() => {
1120
- if (tabRef.current) {
1121
- tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
1122
- }
1123
- }, [activeTabIndex]);
1124
- const toggleAddReleaseModal = () => {
1206
+ /* @__PURE__ */ jsxRuntime.jsx(
1207
+ helperPlugin.PaginationURLQuery,
1208
+ {
1209
+ pagination: {
1210
+ pageCount: releaseMeta?.pagination?.pageCount || 0
1211
+ }
1212
+ }
1213
+ )
1214
+ ] })
1215
+ ] }) });
1216
+ };
1217
+ const ReleaseDetailsPage = () => {
1218
+ const { formatMessage } = reactIntl.useIntl();
1219
+ const { releaseId } = reactRouterDom.useParams();
1220
+ const toggleNotification = helperPlugin.useNotification();
1221
+ const { formatAPIError } = helperPlugin.useAPIErrorHandler();
1222
+ const { push } = reactRouterDom.useHistory();
1223
+ const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
1224
+ const [showWarningSubmit, setWarningSubmit] = React__namespace.useState(false);
1225
+ const {
1226
+ isLoading: isLoadingDetails,
1227
+ data,
1228
+ isSuccess: isSuccessDetails
1229
+ } = index.useGetReleaseQuery({ id: releaseId });
1230
+ const [updateRelease, { isLoading: isSubmittingForm }] = index.useUpdateReleaseMutation();
1231
+ const [deleteRelease, { isLoading: isDeletingRelease }] = index.useDeleteReleaseMutation();
1232
+ const toggleEditReleaseModal = () => {
1125
1233
  setReleaseModalShown((prev) => !prev);
1126
1234
  };
1127
- if (isLoading) {
1128
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
1129
- }
1130
- const totalPendingReleases = isSuccess && response.currentData?.meta?.pendingReleasesCount || 0;
1131
- const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
1132
- const handleTabChange = (index2) => {
1133
- setQuery({
1134
- ...query,
1135
- page: 1,
1136
- pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
1137
- filters: {
1138
- releasedAt: {
1139
- $notNull: index2 === 0 ? false : true
1140
- }
1235
+ const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);
1236
+ if (isLoadingDetails) {
1237
+ return /* @__PURE__ */ jsxRuntime.jsx(
1238
+ ReleaseDetailsLayout,
1239
+ {
1240
+ toggleEditReleaseModal,
1241
+ toggleWarningSubmit,
1242
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) })
1141
1243
  }
1244
+ );
1245
+ }
1246
+ const releaseData = isSuccessDetails && data?.data || null;
1247
+ const title = releaseData?.name || "";
1248
+ const timezone = releaseData?.timezone ?? null;
1249
+ const scheduledAt = releaseData?.scheduledAt && timezone ? dateFnsTz.utcToZonedTime(releaseData.scheduledAt, timezone) : null;
1250
+ const date = scheduledAt ? new Date(format__default.default(scheduledAt, "yyyy-MM-dd")) : null;
1251
+ const time = scheduledAt ? format__default.default(scheduledAt, "HH:mm") : "";
1252
+ const handleEditRelease = async (values) => {
1253
+ const response = await updateRelease({
1254
+ id: releaseId,
1255
+ name: values.name,
1256
+ scheduledAt: values.scheduledAt,
1257
+ timezone: values.timezone
1142
1258
  });
1143
- };
1144
- const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
1145
- const response2 = await createRelease({
1146
- name,
1147
- scheduledAt,
1148
- timezone
1149
- });
1150
- if ("data" in response2) {
1259
+ if ("data" in response) {
1151
1260
  toggleNotification({
1152
1261
  type: "success",
1153
1262
  message: formatMessage({
1154
- id: "content-releases.modal.release-created-notification-success",
1155
- defaultMessage: "Release created."
1263
+ id: "content-releases.modal.release-updated-notification-success",
1264
+ defaultMessage: "Release updated."
1156
1265
  })
1157
1266
  });
1158
- trackUsage("didCreateRelease");
1159
- push(`/plugins/content-releases/${response2.data.data.id}`);
1160
- } else if (index.isAxiosError(response2.error)) {
1267
+ } else if (index.isAxiosError(response.error)) {
1161
1268
  toggleNotification({
1162
1269
  type: "warning",
1163
- message: formatAPIError(response2.error)
1270
+ message: formatAPIError(response.error)
1164
1271
  });
1165
1272
  } else {
1166
1273
  toggleNotification({
@@ -1168,137 +1275,65 @@ const ReleasesPage = () => {
1168
1275
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1169
1276
  });
1170
1277
  }
1278
+ toggleEditReleaseModal();
1171
1279
  };
1172
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
1173
- /* @__PURE__ */ jsxRuntime.jsx(
1174
- designSystem.HeaderLayout,
1175
- {
1176
- title: formatMessage({
1177
- id: "content-releases.pages.Releases.title",
1178
- defaultMessage: "Releases"
1179
- }),
1180
- subtitle: formatMessage({
1181
- id: "content-releases.pages.Releases.header-subtitle",
1182
- defaultMessage: "Create and manage content updates"
1183
- }),
1184
- primaryAction: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.create, children: /* @__PURE__ */ jsxRuntime.jsx(
1185
- designSystem.Button,
1186
- {
1187
- startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
1188
- onClick: toggleAddReleaseModal,
1189
- disabled: hasReachedMaximumPendingReleases,
1190
- children: formatMessage({
1191
- id: "content-releases.header.actions.add-release",
1192
- defaultMessage: "New release"
1193
- })
1194
- }
1195
- ) })
1196
- }
1197
- ),
1198
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1199
- hasReachedMaximumPendingReleases && /* @__PURE__ */ jsxRuntime.jsx(
1200
- StyledAlert,
1201
- {
1202
- marginBottom: 6,
1203
- action: /* @__PURE__ */ jsxRuntime.jsx(v2.Link, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
1204
- id: "content-releases.pages.Releases.max-limit-reached.action",
1205
- defaultMessage: "Explore plans"
1206
- }) }),
1207
- title: formatMessage(
1208
- {
1209
- id: "content-releases.pages.Releases.max-limit-reached.title",
1210
- defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
1211
- },
1212
- { number: maximumReleases }
1213
- ),
1214
- onClose: () => {
1215
- },
1216
- closeLabel: "",
1217
- children: formatMessage({
1218
- id: "content-releases.pages.Releases.max-limit-reached.message",
1219
- defaultMessage: "Upgrade to manage an unlimited number of releases."
1220
- })
1221
- }
1222
- ),
1223
- /* @__PURE__ */ jsxRuntime.jsxs(
1224
- designSystem.TabGroup,
1225
- {
1226
- label: formatMessage({
1227
- id: "content-releases.pages.Releases.tab-group.label",
1228
- defaultMessage: "Releases list"
1229
- }),
1230
- variant: "simple",
1231
- initialSelectedTabIndex: activeTabIndex,
1232
- onTabChange: handleTabChange,
1233
- ref: tabRef,
1234
- children: [
1235
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingBottom: 8, children: [
1236
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs, { children: [
1237
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage(
1238
- {
1239
- id: "content-releases.pages.Releases.tab.pending",
1240
- defaultMessage: "Pending ({count})"
1241
- },
1242
- {
1243
- count: totalPendingReleases
1244
- }
1245
- ) }),
1246
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage({
1247
- id: "content-releases.pages.Releases.tab.done",
1248
- defaultMessage: "Done"
1249
- }) })
1250
- ] }),
1251
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {})
1252
- ] }),
1253
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.TabPanels, { children: [
1254
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
1255
- ReleasesGrid,
1256
- {
1257
- sectionTitle: "pending",
1258
- releases: response?.currentData?.data,
1259
- isError
1260
- }
1261
- ) }),
1262
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.TabPanel, { children: /* @__PURE__ */ jsxRuntime.jsx(
1263
- ReleasesGrid,
1264
- {
1265
- sectionTitle: "done",
1266
- releases: response?.currentData?.data,
1267
- isError
1268
- }
1269
- ) })
1270
- ] })
1271
- ]
1272
- }
1273
- ),
1274
- response.currentData?.meta?.pagination?.total ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
1275
- /* @__PURE__ */ jsxRuntime.jsx(
1276
- helperPlugin.PageSizeURLQuery,
1280
+ const handleDeleteRelease = async () => {
1281
+ const response = await deleteRelease({
1282
+ id: releaseId
1283
+ });
1284
+ if ("data" in response) {
1285
+ push("/plugins/content-releases");
1286
+ } else if (index.isAxiosError(response.error)) {
1287
+ toggleNotification({
1288
+ type: "warning",
1289
+ message: formatAPIError(response.error)
1290
+ });
1291
+ } else {
1292
+ toggleNotification({
1293
+ type: "warning",
1294
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1295
+ });
1296
+ }
1297
+ };
1298
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1299
+ ReleaseDetailsLayout,
1300
+ {
1301
+ toggleEditReleaseModal,
1302
+ toggleWarningSubmit,
1303
+ children: [
1304
+ /* @__PURE__ */ jsxRuntime.jsx(ReleaseDetailsBody, {}),
1305
+ releaseModalShown && /* @__PURE__ */ jsxRuntime.jsx(
1306
+ ReleaseModal,
1277
1307
  {
1278
- options: ["8", "16", "32", "64"],
1279
- defaultValue: response?.currentData?.meta?.pagination?.pageSize.toString()
1308
+ handleClose: toggleEditReleaseModal,
1309
+ handleSubmit: handleEditRelease,
1310
+ isLoading: isLoadingDetails || isSubmittingForm,
1311
+ initialValues: {
1312
+ name: title || "",
1313
+ scheduledAt,
1314
+ date,
1315
+ time,
1316
+ isScheduled: Boolean(scheduledAt),
1317
+ timezone
1318
+ }
1280
1319
  }
1281
1320
  ),
1282
1321
  /* @__PURE__ */ jsxRuntime.jsx(
1283
- helperPlugin.PaginationURLQuery,
1322
+ helperPlugin.ConfirmDialog,
1284
1323
  {
1285
- pagination: {
1286
- pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
1287
- }
1324
+ bodyText: {
1325
+ id: "content-releases.dialog.confirmation-message",
1326
+ defaultMessage: "Are you sure you want to delete this release?"
1327
+ },
1328
+ isOpen: showWarningSubmit,
1329
+ isConfirmButtonLoading: isDeletingRelease,
1330
+ onToggleDialog: toggleWarningSubmit,
1331
+ onConfirm: handleDeleteRelease
1288
1332
  }
1289
1333
  )
1290
- ] }) : null
1291
- ] }) }),
1292
- releaseModalShown && /* @__PURE__ */ jsxRuntime.jsx(
1293
- ReleaseModal,
1294
- {
1295
- handleClose: toggleAddReleaseModal,
1296
- handleSubmit: handleAddRelease,
1297
- isLoading: isSubmittingForm,
1298
- initialValues: INITIAL_FORM_VALUES
1299
- }
1300
- )
1301
- ] });
1334
+ ]
1335
+ }
1336
+ );
1302
1337
  };
1303
1338
  const App = () => {
1304
1339
  return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPagePermissions, { permissions: index.PERMISSIONS.main, children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Switch, { children: [
@@ -1307,4 +1342,4 @@ const App = () => {
1307
1342
  ] }) });
1308
1343
  };
1309
1344
  exports.App = App;
1310
- //# sourceMappingURL=App-lnXbSPgp.js.map
1345
+ //# sourceMappingURL=App-ODHUuKJ5.js.map