@strapi/content-releases 4.17.0 → 4.18.1-beta.0

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.
@@ -1,11 +1,11 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { useParams, useHistory, Redirect, Link as Link$1, useLocation, Switch, Route } from "react-router-dom";
3
- import { P as PERMISSIONS, u as useGetReleaseQuery, a as useUpdateReleaseMutation, b as useDeleteReleaseMutation, c as usePublishReleaseMutation, d as useGetReleaseActionsQuery, e as useUpdateReleaseActionMutation, R as ReleaseActionOptions, i as isAxiosError, f as useGetReleasesQuery, g as useCreateReleaseMutation, p as pluginId } from "./index-937f8179.mjs";
2
+ import { useNotification, useAPIErrorHandler, LoadingIndicatorPage, ConfirmDialog, useRBAC, RelativeTime, CheckPermissions, useQueryParams, NoContent, Table, PageSizeURLQuery, PaginationURLQuery, AnErrorOccurred, CheckPagePermissions } from "@strapi/helper-plugin";
3
+ import { useLocation, useParams, useHistory, Redirect, Link as Link$1, Switch, Route } from "react-router-dom";
4
+ import { p as pluginId, u as useGetReleaseQuery, a as useUpdateReleaseMutation, b as useDeleteReleaseMutation, c as usePublishReleaseMutation, P as PERMISSIONS, d as useGetReleaseActionsQuery, e as useUpdateReleaseActionMutation, R as ReleaseActionOptions, f as ReleaseActionMenu, i as isAxiosError, g as useGetReleasesQuery, h as useCreateReleaseMutation } from "./index-XAQOX_IB.mjs";
4
5
  import * as React from "react";
5
- import { ModalLayout, ModalHeader, Typography, ModalBody, TextInput, ModalFooter, Button, Flex, ContentLayout, Main, HeaderLayout, Link, IconButton, Popover, Tr, Td, TabGroup, Box, Tabs, Tab, Divider, TabPanels, TabPanel, EmptyStateLayout, Grid, GridItem } from "@strapi/design-system";
6
+ import { ModalLayout, ModalHeader, Typography, ModalBody, TextInput, ModalFooter, Button, Flex, ContentLayout, Main, HeaderLayout, Link, IconButton, Popover, SingleSelect, SingleSelectOption, Badge, Tr, Td, Icon, TabGroup, Box, Tabs, Tab, Divider, TabPanels, TabPanel, EmptyStateLayout, Grid, GridItem } from "@strapi/design-system";
6
7
  import { LinkButton, Link as Link$2 } from "@strapi/design-system/v2";
7
- import { CheckPermissions, useNotification, useAPIErrorHandler, LoadingIndicatorPage, ConfirmDialog, useRBAC, RelativeTime, useQueryParams, NoContent, Table, PageSizeURLQuery, PaginationURLQuery, AnErrorOccurred } from "@strapi/helper-plugin";
8
- import { Pencil, Trash, ArrowLeft, More, Plus, EmptyDocuments } from "@strapi/icons";
8
+ import { Pencil, Trash, ArrowLeft, More, CheckCircle, Plus, EmptyDocuments } from "@strapi/icons";
9
9
  import { useIntl } from "react-intl";
10
10
  import styled from "styled-components";
11
11
  import { Formik, Form } from "formik";
@@ -23,11 +23,16 @@ const ReleaseModal = ({
23
23
  isLoading = false
24
24
  }) => {
25
25
  const { formatMessage } = useIntl();
26
+ const { pathname } = useLocation();
27
+ const isCreatingRelease = pathname === `/plugins/${pluginId}`;
26
28
  return /* @__PURE__ */ jsxs(ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
27
- /* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage({
28
- id: "content-releases.modal.add-release-title",
29
- defaultMessage: "New release"
30
- }) }) }),
29
+ /* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage(
30
+ {
31
+ id: "content-releases.modal.title",
32
+ defaultMessage: "{isCreatingRelease, select, true {New release} other {Edit release}}"
33
+ },
34
+ { isCreatingRelease }
35
+ ) }) }),
31
36
  /* @__PURE__ */ jsx(
32
37
  Formik,
33
38
  {
@@ -54,10 +59,22 @@ const ReleaseModal = ({
54
59
  ModalFooter,
55
60
  {
56
61
  startActions: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }),
57
- endActions: /* @__PURE__ */ jsx(Button, { name: "submit", loading: isLoading, disabled: !values.name, type: "submit", children: formatMessage({
58
- id: "content-releases.modal.form.button.submit",
59
- defaultMessage: "Continue"
60
- }) })
62
+ endActions: /* @__PURE__ */ jsx(
63
+ Button,
64
+ {
65
+ name: "submit",
66
+ loading: isLoading,
67
+ disabled: !values.name || values.name === initialValues.name,
68
+ type: "submit",
69
+ children: formatMessage(
70
+ {
71
+ id: "content-releases.modal.form.button.submit",
72
+ defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
73
+ },
74
+ { isCreatingRelease }
75
+ )
76
+ }
77
+ )
61
78
  }
62
79
  )
63
80
  ] })
@@ -114,6 +131,31 @@ const PopoverButton = ({ onClick, disabled, children }) => {
114
131
  }
115
132
  );
116
133
  };
134
+ const EntryValidationText = ({ status, action }) => {
135
+ const { formatMessage } = useIntl();
136
+ if (action == "publish") {
137
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
138
+ /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
139
+ status === "published" ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
140
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
141
+ defaultMessage: "Already published"
142
+ }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
143
+ id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
144
+ defaultMessage: "Ready to publish"
145
+ }) })
146
+ ] });
147
+ }
148
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
149
+ /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
150
+ status === "draft" ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
151
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
152
+ defaultMessage: "Already unpublished"
153
+ }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
154
+ id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish",
155
+ defaultMessage: "Ready to unpublish"
156
+ }) })
157
+ ] });
158
+ };
117
159
  const ReleaseDetailsLayout = ({
118
160
  toggleEditReleaseModal,
119
161
  toggleWarningSubmit,
@@ -190,7 +232,7 @@ const ReleaseDetailsLayout = ({
190
232
  );
191
233
  }
192
234
  const totalEntries = release.actions.meta.count || 0;
193
- const createdBy = `${release.createdBy.firstname} ${release.createdBy.lastname}`;
235
+ const createdBy = release.createdBy.lastname ? `${release.createdBy.firstname} ${release.createdBy.lastname}` : `${release.createdBy.firstname}`;
194
236
  return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
195
237
  /* @__PURE__ */ jsx(
196
238
  HeaderLayout,
@@ -294,10 +336,29 @@ const ReleaseDetailsLayout = ({
294
336
  children
295
337
  ] });
296
338
  };
339
+ const GROUP_BY_OPTIONS = ["contentType", "locale", "action"];
340
+ const getGroupByOptionLabel = (value) => {
341
+ if (value === "locale") {
342
+ return {
343
+ id: "content-releases.pages.ReleaseDetails.groupBy.option.locales",
344
+ defaultMessage: "Locales"
345
+ };
346
+ }
347
+ if (value === "action") {
348
+ return {
349
+ id: "content-releases.pages.ReleaseDetails.groupBy.option.actions",
350
+ defaultMessage: "Actions"
351
+ };
352
+ }
353
+ return {
354
+ id: "content-releases.pages.ReleaseDetails.groupBy.option.content-type",
355
+ defaultMessage: "Content-Types"
356
+ };
357
+ };
297
358
  const ReleaseDetailsBody = () => {
298
359
  const { formatMessage } = useIntl();
299
360
  const { releaseId } = useParams();
300
- const [{ query }] = useQueryParams();
361
+ const [{ query }, setQuery] = useQueryParams();
301
362
  const toggleNotification = useNotification();
302
363
  const { formatAPIError } = useAPIErrorHandler();
303
364
  const {
@@ -307,6 +368,7 @@ const ReleaseDetailsBody = () => {
307
368
  error: releaseError
308
369
  } = useGetReleaseQuery({ id: releaseId });
309
370
  const release = releaseData?.data;
371
+ const selectedGroupBy = query?.groupBy || "contentType";
310
372
  const {
311
373
  isLoading,
312
374
  isFetching,
@@ -345,7 +407,9 @@ const ReleaseDetailsBody = () => {
345
407
  if (isLoading || isReleaseLoading) {
346
408
  return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
347
409
  }
348
- if (isError || isReleaseError || !release) {
410
+ const releaseActions = data?.data;
411
+ const releaseMeta = data?.meta;
412
+ if (isError || isReleaseError || !release || !releaseActions) {
349
413
  const errorsArray = [];
350
414
  if (releaseError) {
351
415
  errorsArray.push({
@@ -369,9 +433,7 @@ const ReleaseDetailsBody = () => {
369
433
  }
370
434
  );
371
435
  }
372
- const releaseActions = data?.data;
373
- const releaseMeta = data?.meta;
374
- if (!releaseActions || !releaseActions.length) {
436
+ if (Object.keys(releaseActions).length === 0) {
375
437
  return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(
376
438
  NoContent,
377
439
  {
@@ -397,90 +459,127 @@ const ReleaseDetailsBody = () => {
397
459
  }
398
460
  ) });
399
461
  }
400
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
401
- /* @__PURE__ */ jsx(
402
- Table.Root,
462
+ return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
463
+ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
464
+ SingleSelect,
403
465
  {
404
- rows: releaseActions.map((item) => ({
405
- ...item,
406
- id: Number(item.entry.id)
407
- })),
408
- colCount: releaseActions.length,
409
- isLoading,
410
- isFetching,
411
- children: /* @__PURE__ */ jsxs(Table.Content, { children: [
412
- /* @__PURE__ */ jsxs(Table.Head, { children: [
413
- /* @__PURE__ */ jsx(
414
- Table.HeaderCell,
415
- {
416
- fieldSchemaType: "string",
417
- label: formatMessage({
418
- id: "content-releases.page.ReleaseDetails.table.header.label.name",
419
- defaultMessage: "name"
420
- }),
421
- name: "name"
422
- }
423
- ),
424
- /* @__PURE__ */ jsx(
425
- Table.HeaderCell,
426
- {
427
- fieldSchemaType: "string",
428
- label: formatMessage({
429
- id: "content-releases.page.ReleaseDetails.table.header.label.locale",
430
- defaultMessage: "locale"
431
- }),
432
- name: "locale"
433
- }
434
- ),
435
- /* @__PURE__ */ jsx(
436
- Table.HeaderCell,
437
- {
438
- fieldSchemaType: "string",
439
- label: formatMessage({
440
- id: "content-releases.page.ReleaseDetails.table.header.label.content-type",
441
- defaultMessage: "content-type"
442
- }),
443
- name: "content-type"
444
- }
445
- ),
446
- /* @__PURE__ */ jsx(
447
- Table.HeaderCell,
448
- {
449
- fieldSchemaType: "string",
450
- label: formatMessage({
451
- id: "content-releases.page.ReleaseDetails.table.header.label.action",
452
- defaultMessage: "action"
453
- }),
454
- name: "action"
455
- }
456
- )
457
- ] }),
458
- /* @__PURE__ */ jsx(Table.LoadingBody, {}),
459
- /* @__PURE__ */ jsx(Table.Body, { children: releaseActions.map(({ id, type, entry }) => /* @__PURE__ */ jsxs(Tr, { children: [
460
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: `${entry.contentType.mainFieldValue || entry.id}` }) }),
461
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: `${entry?.locale?.name ? entry.locale.name : "-"}` }) }),
462
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: entry.contentType.displayName || "" }) }),
463
- /* @__PURE__ */ jsx(Td, { children: release.releasedAt ? /* @__PURE__ */ jsx(Typography, { children: formatMessage(
464
- {
465
- id: "content-releases.page.ReleaseDetails.table.action-published",
466
- defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
467
- },
468
- {
469
- isPublish: type === "publish",
470
- b: (children) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children })
471
- }
472
- ) }) : /* @__PURE__ */ jsx(
473
- ReleaseActionOptions,
474
- {
475
- selected: type,
476
- handleChange: (e) => handleChangeType(e, id),
477
- name: `release-action-${id}-type`
478
- }
479
- ) })
480
- ] }, id)) })
481
- ] })
466
+ "aria-label": formatMessage({
467
+ id: "content-releases.pages.ReleaseDetails.groupBy.label",
468
+ defaultMessage: "Group by"
469
+ }),
470
+ customizeContent: (value) => formatMessage(
471
+ {
472
+ id: `content-releases.pages.ReleaseDetails.groupBy.label`,
473
+ defaultMessage: `Group by {groupBy}`
474
+ },
475
+ {
476
+ groupBy: value
477
+ }
478
+ ),
479
+ value: formatMessage(getGroupByOptionLabel(selectedGroupBy)),
480
+ onChange: (value) => setQuery({ groupBy: value }),
481
+ children: GROUP_BY_OPTIONS.map((option) => /* @__PURE__ */ jsx(SingleSelectOption, { value: option, children: formatMessage(getGroupByOptionLabel(option)) }, option))
482
482
  }
483
- ),
483
+ ) }),
484
+ Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
485
+ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(Badge, { children: key }) }),
486
+ /* @__PURE__ */ jsx(
487
+ Table.Root,
488
+ {
489
+ rows: releaseActions[key].map((item) => ({
490
+ ...item,
491
+ id: Number(item.entry.id)
492
+ })),
493
+ colCount: releaseActions[key].length,
494
+ isLoading,
495
+ isFetching,
496
+ children: /* @__PURE__ */ jsxs(Table.Content, { children: [
497
+ /* @__PURE__ */ jsxs(Table.Head, { children: [
498
+ /* @__PURE__ */ jsx(
499
+ Table.HeaderCell,
500
+ {
501
+ fieldSchemaType: "string",
502
+ label: formatMessage({
503
+ id: "content-releases.page.ReleaseDetails.table.header.label.name",
504
+ defaultMessage: "name"
505
+ }),
506
+ name: "name"
507
+ }
508
+ ),
509
+ /* @__PURE__ */ jsx(
510
+ Table.HeaderCell,
511
+ {
512
+ fieldSchemaType: "string",
513
+ label: formatMessage({
514
+ id: "content-releases.page.ReleaseDetails.table.header.label.locale",
515
+ defaultMessage: "locale"
516
+ }),
517
+ name: "locale"
518
+ }
519
+ ),
520
+ /* @__PURE__ */ jsx(
521
+ Table.HeaderCell,
522
+ {
523
+ fieldSchemaType: "string",
524
+ label: formatMessage({
525
+ id: "content-releases.page.ReleaseDetails.table.header.label.content-type",
526
+ defaultMessage: "content-type"
527
+ }),
528
+ name: "content-type"
529
+ }
530
+ ),
531
+ /* @__PURE__ */ jsx(
532
+ Table.HeaderCell,
533
+ {
534
+ fieldSchemaType: "string",
535
+ label: formatMessage({
536
+ id: "content-releases.page.ReleaseDetails.table.header.label.action",
537
+ defaultMessage: "action"
538
+ }),
539
+ name: "action"
540
+ }
541
+ ),
542
+ !release.releasedAt && /* @__PURE__ */ jsx(
543
+ Table.HeaderCell,
544
+ {
545
+ fieldSchemaType: "string",
546
+ label: formatMessage({
547
+ id: "content-releases.page.ReleaseDetails.table.header.label.status",
548
+ defaultMessage: "status"
549
+ }),
550
+ name: "status"
551
+ }
552
+ )
553
+ ] }),
554
+ /* @__PURE__ */ jsx(Table.LoadingBody, {}),
555
+ /* @__PURE__ */ jsx(Table.Body, { children: releaseActions[key].map(({ id, type, entry }) => /* @__PURE__ */ jsxs(Tr, { children: [
556
+ /* @__PURE__ */ jsx(Td, { width: "25%", children: /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: `${entry.contentType.mainFieldValue || entry.id}` }) }),
557
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: `${entry?.locale?.name ? entry.locale.name : "-"}` }) }),
558
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: entry.contentType.displayName || "" }) }),
559
+ /* @__PURE__ */ jsx(Td, { children: release.releasedAt ? /* @__PURE__ */ jsx(Typography, { children: formatMessage(
560
+ {
561
+ id: "content-releases.page.ReleaseDetails.table.action-published",
562
+ defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
563
+ },
564
+ {
565
+ isPublish: type === "publish",
566
+ b: (children) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children })
567
+ }
568
+ ) }) : /* @__PURE__ */ jsx(
569
+ ReleaseActionOptions,
570
+ {
571
+ selected: type,
572
+ handleChange: (e) => handleChangeType(e, id),
573
+ name: `release-action-${id}-type`
574
+ }
575
+ ) }),
576
+ !release.releasedAt && /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(EntryValidationText, { status: entry.status, action: type }) }),
577
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(ReleaseActionMenu, { releaseId, actionId: id }) }) })
578
+ ] }, id)) })
579
+ ] })
580
+ }
581
+ )
582
+ ] }, `releases-group-${key}`)),
484
583
  /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
485
584
  /* @__PURE__ */ jsx(PageSizeURLQuery, { defaultValue: releaseMeta?.pagination?.pageSize.toString() }),
486
585
  /* @__PURE__ */ jsx(
@@ -601,7 +700,6 @@ const ReleaseDetailsPage = () => {
601
700
  }
602
701
  );
603
702
  };
604
- const ProtectedReleaseDetailsPage = () => /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsx(ReleaseDetailsPage, {}) });
605
703
  const ReleasesLayout = ({
606
704
  isLoading,
607
705
  totalReleases,
@@ -835,21 +933,13 @@ const ReleasesPage = () => {
835
933
  )
836
934
  ] });
837
935
  };
838
- const ProtectedReleasesPage = () => /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsx(ReleasesPage, {}) });
839
936
  const App = () => {
840
- return /* @__PURE__ */ jsxs(Switch, { children: [
841
- /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}`, component: ProtectedReleasesPage }),
842
- /* @__PURE__ */ jsx(
843
- Route,
844
- {
845
- exact: true,
846
- path: `/plugins/${pluginId}/:releaseId`,
847
- component: ProtectedReleaseDetailsPage
848
- }
849
- )
850
- ] });
937
+ return /* @__PURE__ */ jsx(CheckPagePermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(Switch, { children: [
938
+ /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}`, component: ReleasesPage }),
939
+ /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}/:releaseId`, component: ReleaseDetailsPage })
940
+ ] }) });
851
941
  };
852
942
  export {
853
943
  App
854
944
  };
855
- //# sourceMappingURL=App-a4843fda.mjs.map
945
+ //# sourceMappingURL=App-g2P5kbSm.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App-g2P5kbSm.mjs","sources":["../../shared/validation-schemas.ts","../../admin/src/components/ReleaseModal.tsx","../../admin/src/pages/ReleaseDetailsPage.tsx","../../admin/src/pages/ReleasesPage.tsx","../../admin/src/pages/App.tsx"],"sourcesContent":["import * as yup from 'yup';\n\nexport const RELEASE_SCHEMA = yup\n .object()\n .shape({\n name: yup.string().trim().required(),\n })\n .required()\n .noUnknown();\n","import {\n Button,\n ModalBody,\n ModalFooter,\n ModalLayout,\n ModalHeader,\n TextInput,\n Typography,\n} from '@strapi/design-system';\nimport { Formik, Form } from 'formik';\nimport { useIntl } from 'react-intl';\nimport { useLocation } from 'react-router-dom';\n\nimport { RELEASE_SCHEMA } from '../../../shared/validation-schemas';\nimport { pluginId } from '../pluginId';\n\nexport interface FormValues {\n name: string;\n}\n\ninterface ReleaseModalProps {\n handleClose: () => void;\n handleSubmit: (values: FormValues) => void;\n isLoading?: boolean;\n initialValues: FormValues;\n}\n\nexport const ReleaseModal = ({\n handleClose,\n handleSubmit,\n initialValues,\n isLoading = false,\n}: ReleaseModalProps) => {\n const { formatMessage } = useIntl();\n const { pathname } = useLocation();\n const isCreatingRelease = pathname === `/plugins/${pluginId}`;\n\n return (\n <ModalLayout onClose={handleClose} labelledBy=\"title\">\n <ModalHeader>\n <Typography id=\"title\" fontWeight=\"bold\" textColor=\"neutral800\">\n {formatMessage(\n {\n id: 'content-releases.modal.title',\n defaultMessage:\n '{isCreatingRelease, select, true {New release} other {Edit release}}',\n },\n { isCreatingRelease: isCreatingRelease }\n )}\n </Typography>\n </ModalHeader>\n <Formik\n validateOnChange={false}\n onSubmit={handleSubmit}\n initialValues={initialValues}\n validationSchema={RELEASE_SCHEMA}\n >\n {({ values, errors, handleChange }) => (\n <Form>\n <ModalBody>\n <TextInput\n label={formatMessage({\n id: 'content-releases.modal.form.input.label.release-name',\n defaultMessage: 'Name',\n })}\n name=\"name\"\n value={values.name}\n error={errors.name}\n onChange={handleChange}\n required\n />\n </ModalBody>\n <ModalFooter\n startActions={\n <Button onClick={handleClose} variant=\"tertiary\" name=\"cancel\">\n {formatMessage({ id: 'cancel', defaultMessage: 'Cancel' })}\n </Button>\n }\n endActions={\n <Button\n name=\"submit\"\n loading={isLoading}\n disabled={!values.name || values.name === initialValues.name}\n type=\"submit\"\n >\n {formatMessage(\n {\n id: 'content-releases.modal.form.button.submit',\n defaultMessage: '{isCreatingRelease, select, true {Continue} other {Save}}',\n },\n { isCreatingRelease: isCreatingRelease }\n )}\n </Button>\n }\n />\n </Form>\n )}\n </Formik>\n </ModalLayout>\n );\n};\n","import * as React from 'react';\n\nimport {\n Button,\n ContentLayout,\n Flex,\n HeaderLayout,\n IconButton,\n Link,\n Main,\n Popover,\n Tr,\n Td,\n Typography,\n Badge,\n SingleSelect,\n SingleSelectOption,\n Icon,\n} from '@strapi/design-system';\nimport { LinkButton } from '@strapi/design-system/v2';\nimport {\n CheckPermissions,\n LoadingIndicatorPage,\n NoContent,\n PageSizeURLQuery,\n PaginationURLQuery,\n RelativeTime,\n Table,\n useAPIErrorHandler,\n useNotification,\n useQueryParams,\n ConfirmDialog,\n useRBAC,\n} from '@strapi/helper-plugin';\nimport { ArrowLeft, CheckCircle, More, Pencil, Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { useParams, useHistory, Link as ReactRouterLink, Redirect } from 'react-router-dom';\nimport styled from 'styled-components';\n\nimport { ReleaseActionMenu } from '../components/ReleaseActionMenu';\nimport { ReleaseActionOptions } from '../components/ReleaseActionOptions';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport { isAxiosError } from '../services/axios';\nimport {\n GetReleaseActionsQueryParams,\n useGetReleaseActionsQuery,\n useGetReleaseQuery,\n useUpdateReleaseMutation,\n useUpdateReleaseActionMutation,\n usePublishReleaseMutation,\n useDeleteReleaseMutation,\n} from '../services/release';\n\nimport type {\n ReleaseAction,\n ReleaseActionGroupBy,\n} from '../../../shared/contracts/release-actions';\n\n/* -------------------------------------------------------------------------------------------------\n * ReleaseDetailsLayout\n * -----------------------------------------------------------------------------------------------*/\n// @ts-expect-error – issue with styled-components types.\nconst ReleaseInfoWrapper = styled(Flex)`\n align-self: stretch;\n border-bottom-right-radius: ${({ theme }) => theme.borderRadius};\n border-bottom-left-radius: ${({ theme }) => theme.borderRadius};\n border-top: 1px solid ${({ theme }) => theme.colors.neutral150};\n`;\n\nconst StyledFlex = styled(Flex)<{ disabled?: boolean }>`\n align-self: stretch;\n cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};\n\n svg path {\n fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};\n }\n span {\n color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};\n }\n`;\n\nconst PencilIcon = styled(Pencil)`\n width: ${({ theme }) => theme.spaces[4]};\n height: ${({ theme }) => theme.spaces[4]};\n path {\n fill: ${({ theme }) => theme.colors.neutral600};\n }\n`;\n\nconst TrashIcon = styled(Trash)`\n width: ${({ theme }) => theme.spaces[4]};\n height: ${({ theme }) => theme.spaces[4]};\n path {\n fill: ${({ theme }) => theme.colors.danger600};\n }\n`;\n\ninterface PopoverButtonProps {\n onClick?: (event: React.MouseEvent<HTMLElement>) => void;\n disabled?: boolean;\n children: React.ReactNode;\n}\n\nconst PopoverButton = ({ onClick, disabled, children }: PopoverButtonProps) => {\n return (\n <StyledFlex\n paddingTop={2}\n paddingBottom={2}\n paddingLeft={4}\n paddingRight={4}\n alignItems=\"center\"\n gap={2}\n as=\"button\"\n hasRadius\n onClick={onClick}\n disabled={disabled}\n >\n {children}\n </StyledFlex>\n );\n};\n\ninterface EntryValidationTextProps {\n status: ReleaseAction['entry']['status'];\n action: ReleaseAction['type'];\n}\n\nconst EntryValidationText = ({ status, action }: EntryValidationTextProps) => {\n const { formatMessage } = useIntl();\n\n if (action == 'publish') {\n return (\n <Flex gap={2}>\n <Icon color=\"success600\" as={CheckCircle} />\n {status === 'published' ? (\n <Typography textColor=\"success600\" fontWeight=\"bold\">\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.already-published',\n defaultMessage: 'Already published',\n })}\n </Typography>\n ) : (\n <Typography>\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish',\n defaultMessage: 'Ready to publish',\n })}\n </Typography>\n )}\n </Flex>\n );\n }\n\n return (\n <Flex gap={2}>\n <Icon color=\"success600\" as={CheckCircle} />\n {status === 'draft' ? (\n <Typography textColor=\"success600\" fontWeight=\"bold\">\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.already-unpublished',\n defaultMessage: 'Already unpublished',\n })}\n </Typography>\n ) : (\n <Typography>\n {formatMessage({\n id: 'content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish',\n defaultMessage: 'Ready to unpublish',\n })}\n </Typography>\n )}\n </Flex>\n );\n};\ninterface ReleaseDetailsLayoutProps {\n toggleEditReleaseModal: () => void;\n toggleWarningSubmit: () => void;\n children: React.ReactNode;\n}\n\nexport const ReleaseDetailsLayout = ({\n toggleEditReleaseModal,\n toggleWarningSubmit,\n children,\n}: ReleaseDetailsLayoutProps) => {\n const { formatMessage } = useIntl();\n const { releaseId } = useParams<{ releaseId: string }>();\n const [isPopoverVisible, setIsPopoverVisible] = React.useState(false);\n const moreButtonRef = React.useRef<HTMLButtonElement>(null!);\n const {\n data,\n isLoading: isLoadingDetails,\n isError,\n error,\n } = useGetReleaseQuery({ id: releaseId });\n const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();\n const toggleNotification = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const {\n allowedActions: { canUpdate, canDelete },\n } = useRBAC(PERMISSIONS);\n\n const release = data?.data;\n\n const handleTogglePopover = () => {\n setIsPopoverVisible((prev) => !prev);\n };\n\n const openReleaseModal = () => {\n toggleEditReleaseModal();\n handleTogglePopover();\n };\n\n const handlePublishRelease = async () => {\n const response = await publishRelease({ id: releaseId });\n\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.pages.ReleaseDetails.publish-notification-success',\n defaultMessage: 'Release was published successfully.',\n }),\n });\n } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n const openWarningConfirmDialog = () => {\n toggleWarningSubmit();\n handleTogglePopover();\n };\n\n if (isLoadingDetails) {\n return (\n <Main aria-busy={isLoadingDetails}>\n <LoadingIndicatorPage />\n </Main>\n );\n }\n\n if (isError || !release) {\n return (\n <Redirect\n to={{\n pathname: '/plugins/content-releases',\n state: {\n errors: [\n {\n code: error?.code,\n },\n ],\n },\n }}\n />\n );\n }\n\n const totalEntries = release.actions.meta.count || 0;\n const createdBy = release.createdBy.lastname\n ? `${release.createdBy.firstname} ${release.createdBy.lastname}`\n : `${release.createdBy.firstname}`;\n\n return (\n <Main aria-busy={isLoadingDetails}>\n <HeaderLayout\n title={release.name}\n subtitle={formatMessage(\n {\n id: 'content-releases.pages.Details.header-subtitle',\n defaultMessage: '{number, plural, =0 {No entries} one {# entry} other {# entries}}',\n },\n { number: totalEntries }\n )}\n navigationAction={\n <Link startIcon={<ArrowLeft />} to=\"/plugins/content-releases\">\n {formatMessage({\n id: 'global.back',\n defaultMessage: 'Back',\n })}\n </Link>\n }\n primaryAction={\n !release.releasedAt && (\n <Flex gap={2}>\n <IconButton\n label={formatMessage({\n id: 'content-releases.header.actions.open-release-actions',\n defaultMessage: 'Release actions',\n })}\n ref={moreButtonRef}\n onClick={handleTogglePopover}\n >\n <More />\n </IconButton>\n {isPopoverVisible && (\n <Popover\n source={moreButtonRef}\n placement=\"bottom-end\"\n onDismiss={handleTogglePopover}\n spacing={4}\n minWidth=\"242px\"\n >\n <Flex alignItems=\"center\" justifyContent=\"center\" direction=\"column\" padding={1}>\n <PopoverButton disabled={!canUpdate} onClick={openReleaseModal}>\n <PencilIcon />\n <Typography ellipsis>\n {formatMessage({\n id: 'content-releases.header.actions.edit',\n defaultMessage: 'Edit',\n })}\n </Typography>\n </PopoverButton>\n <PopoverButton disabled={!canDelete} onClick={openWarningConfirmDialog}>\n <TrashIcon />\n <Typography ellipsis textColor=\"danger600\">\n {formatMessage({\n id: 'content-releases.header.actions.delete',\n defaultMessage: 'Delete',\n })}\n </Typography>\n </PopoverButton>\n </Flex>\n <ReleaseInfoWrapper\n direction=\"column\"\n justifyContent=\"center\"\n alignItems=\"flex-start\"\n gap={1}\n padding={5}\n >\n <Typography variant=\"pi\" fontWeight=\"bold\">\n {formatMessage({\n id: 'content-releases.header.actions.created',\n defaultMessage: 'Created',\n })}\n </Typography>\n <Typography variant=\"pi\" color=\"neutral300\">\n <RelativeTime timestamp={new Date(release.createdAt)} />\n {formatMessage(\n {\n id: 'content-releases.header.actions.created.description',\n defaultMessage: ' by {createdBy}',\n },\n { createdBy }\n )}\n </Typography>\n </ReleaseInfoWrapper>\n </Popover>\n )}\n <CheckPermissions permissions={PERMISSIONS.publish}>\n <Button\n size=\"S\"\n variant=\"default\"\n onClick={handlePublishRelease}\n loading={isPublishing}\n disabled={release.actions.meta.count === 0}\n >\n {formatMessage({\n id: 'content-releases.header.actions.publish',\n defaultMessage: 'Publish',\n })}\n </Button>\n </CheckPermissions>\n </Flex>\n )\n }\n />\n {children}\n </Main>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleaseDetailsBody\n * -----------------------------------------------------------------------------------------------*/\nconst GROUP_BY_OPTIONS = ['contentType', 'locale', 'action'] as const;\nconst getGroupByOptionLabel = (value: (typeof GROUP_BY_OPTIONS)[number]) => {\n if (value === 'locale') {\n return {\n id: 'content-releases.pages.ReleaseDetails.groupBy.option.locales',\n defaultMessage: 'Locales',\n };\n }\n\n if (value === 'action') {\n return {\n id: 'content-releases.pages.ReleaseDetails.groupBy.option.actions',\n defaultMessage: 'Actions',\n };\n }\n\n return {\n id: 'content-releases.pages.ReleaseDetails.groupBy.option.content-type',\n defaultMessage: 'Content-Types',\n };\n};\n\nconst ReleaseDetailsBody = () => {\n const { formatMessage } = useIntl();\n const { releaseId } = useParams<{ releaseId: string }>();\n const [{ query }, setQuery] = useQueryParams<GetReleaseActionsQueryParams>();\n const toggleNotification = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const {\n data: releaseData,\n isLoading: isReleaseLoading,\n isError: isReleaseError,\n error: releaseError,\n } = useGetReleaseQuery({ id: releaseId });\n\n const release = releaseData?.data;\n const selectedGroupBy = query?.groupBy || 'contentType';\n\n const {\n isLoading,\n isFetching,\n isError,\n data,\n error: releaseActionsError,\n } = useGetReleaseActionsQuery({\n ...query,\n releaseId,\n });\n\n const [updateReleaseAction] = useUpdateReleaseActionMutation();\n\n const handleChangeType = async (\n e: React.ChangeEvent<HTMLInputElement>,\n actionId: ReleaseAction['id']\n ) => {\n const response = await updateReleaseAction({\n params: {\n releaseId,\n actionId,\n },\n body: {\n type: e.target.value as ReleaseAction['type'],\n },\n });\n\n if ('error' in response) {\n if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n }\n };\n\n if (isLoading || isReleaseLoading) {\n return (\n <ContentLayout>\n <LoadingIndicatorPage />\n </ContentLayout>\n );\n }\n\n const releaseActions = data?.data;\n const releaseMeta = data?.meta;\n\n if (isError || isReleaseError || !release || !releaseActions) {\n const errorsArray = [];\n if (releaseError) {\n errorsArray.push({\n code: releaseError.code,\n });\n }\n if (releaseActionsError) {\n errorsArray.push({\n code: releaseActionsError.code,\n });\n }\n return (\n <Redirect\n to={{\n pathname: '/plugins/content-releases',\n state: {\n errors: errorsArray,\n },\n }}\n />\n );\n }\n\n if (Object.keys(releaseActions).length === 0) {\n return (\n <ContentLayout>\n <NoContent\n content={{\n id: 'content-releases.pages.Details.tab.emptyEntries',\n defaultMessage:\n 'This release is empty. Open the Content Manager, select an entry and add it to the release.',\n }}\n action={\n <LinkButton\n as={ReactRouterLink}\n // @ts-expect-error - types are not inferred correctly through the as prop.\n to={{\n pathname: '/content-manager',\n }}\n style={{ textDecoration: 'none' }}\n variant=\"secondary\"\n >\n {formatMessage({\n id: 'content-releases.page.Details.button.openContentManager',\n defaultMessage: 'Open the Content Manager',\n })}\n </LinkButton>\n }\n />\n </ContentLayout>\n );\n }\n\n return (\n <ContentLayout>\n <Flex gap={8} direction=\"column\" alignItems=\"stretch\">\n <Flex>\n <SingleSelect\n aria-label={formatMessage({\n id: 'content-releases.pages.ReleaseDetails.groupBy.label',\n defaultMessage: 'Group by',\n })}\n customizeContent={(value) =>\n formatMessage(\n {\n id: `content-releases.pages.ReleaseDetails.groupBy.label`,\n defaultMessage: `Group by {groupBy}`,\n },\n {\n groupBy: value,\n }\n )\n }\n value={formatMessage(getGroupByOptionLabel(selectedGroupBy))}\n onChange={(value) => setQuery({ groupBy: value as ReleaseActionGroupBy })}\n >\n {GROUP_BY_OPTIONS.map((option) => (\n <SingleSelectOption key={option} value={option}>\n {formatMessage(getGroupByOptionLabel(option))}\n </SingleSelectOption>\n ))}\n </SingleSelect>\n </Flex>\n {Object.keys(releaseActions).map((key) => (\n <Flex key={`releases-group-${key}`} gap={4} direction=\"column\" alignItems=\"stretch\">\n <Flex>\n <Badge>{key}</Badge>\n </Flex>\n <Table.Root\n rows={releaseActions[key].map((item) => ({\n ...item,\n id: Number(item.entry.id),\n }))}\n colCount={releaseActions[key].length}\n isLoading={isLoading}\n isFetching={isFetching}\n >\n <Table.Content>\n <Table.Head>\n <Table.HeaderCell\n fieldSchemaType=\"string\"\n label={formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.name',\n defaultMessage: 'name',\n })}\n name=\"name\"\n />\n <Table.HeaderCell\n fieldSchemaType=\"string\"\n label={formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.locale',\n defaultMessage: 'locale',\n })}\n name=\"locale\"\n />\n <Table.HeaderCell\n fieldSchemaType=\"string\"\n label={formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.content-type',\n defaultMessage: 'content-type',\n })}\n name=\"content-type\"\n />\n <Table.HeaderCell\n fieldSchemaType=\"string\"\n label={formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.action',\n defaultMessage: 'action',\n })}\n name=\"action\"\n />\n {!release.releasedAt && (\n <Table.HeaderCell\n fieldSchemaType=\"string\"\n label={formatMessage({\n id: 'content-releases.page.ReleaseDetails.table.header.label.status',\n defaultMessage: 'status',\n })}\n name=\"status\"\n />\n )}\n </Table.Head>\n <Table.LoadingBody />\n <Table.Body>\n {releaseActions[key].map(({ id, type, entry }) => (\n <Tr key={id}>\n <Td width={'25%'}>\n <Typography ellipsis>{`${\n entry.contentType.mainFieldValue || entry.id\n }`}</Typography>\n </Td>\n <Td>\n <Typography>{`${\n entry?.locale?.name ? entry.locale.name : '-'\n }`}</Typography>\n </Td>\n <Td>\n <Typography>{entry.contentType.displayName || ''}</Typography>\n </Td>\n <Td>\n {release.releasedAt ? (\n <Typography>\n {formatMessage(\n {\n id: 'content-releases.page.ReleaseDetails.table.action-published',\n defaultMessage:\n 'This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>.',\n },\n {\n isPublish: type === 'publish',\n b: (children: React.ReactNode) => (\n <Typography fontWeight=\"bold\">{children}</Typography>\n ),\n }\n )}\n </Typography>\n ) : (\n <ReleaseActionOptions\n selected={type}\n handleChange={(e) => handleChangeType(e, id)}\n name={`release-action-${id}-type`}\n />\n )}\n </Td>\n {!release.releasedAt && (\n <Td>\n <EntryValidationText status={entry.status} action={type} />\n </Td>\n )}\n <Td>\n <Flex justifyContent=\"flex-end\">\n <ReleaseActionMenu releaseId={releaseId} actionId={id} />\n </Flex>\n </Td>\n </Tr>\n ))}\n </Table.Body>\n </Table.Content>\n </Table.Root>\n </Flex>\n ))}\n <Flex paddingTop={4} alignItems=\"flex-end\" justifyContent=\"space-between\">\n <PageSizeURLQuery defaultValue={releaseMeta?.pagination?.pageSize.toString()} />\n <PaginationURLQuery\n pagination={{\n pageCount: releaseMeta?.pagination?.pageCount || 0,\n }}\n />\n </Flex>\n </Flex>\n </ContentLayout>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleaseDetailsPage\n * -----------------------------------------------------------------------------------------------*/\nconst ReleaseDetailsPage = () => {\n const { formatMessage } = useIntl();\n const { releaseId } = useParams<{ releaseId: string }>();\n const toggleNotification = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const { push } = useHistory();\n const [releaseModalShown, setReleaseModalShown] = React.useState(false);\n const [showWarningSubmit, setWarningSubmit] = React.useState(false);\n\n const {\n isLoading: isLoadingDetails,\n data,\n isSuccess: isSuccessDetails,\n } = useGetReleaseQuery({ id: releaseId });\n const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();\n const [deleteRelease, { isLoading: isDeletingRelease }] = useDeleteReleaseMutation();\n\n const toggleEditReleaseModal = () => {\n setReleaseModalShown((prev) => !prev);\n };\n\n const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);\n\n if (isLoadingDetails) {\n return (\n <ReleaseDetailsLayout\n toggleEditReleaseModal={toggleEditReleaseModal}\n toggleWarningSubmit={toggleWarningSubmit}\n >\n <ContentLayout>\n <LoadingIndicatorPage />\n </ContentLayout>\n </ReleaseDetailsLayout>\n );\n }\n\n const title = (isSuccessDetails && data?.data?.name) || '';\n\n const handleEditRelease = async (values: FormValues) => {\n const response = await updateRelease({\n id: releaseId,\n name: values.name,\n });\n\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.modal.release-updated-notification-success',\n defaultMessage: 'Release updated.',\n }),\n });\n } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n\n toggleEditReleaseModal();\n };\n\n const handleDeleteRelease = async () => {\n const response = await deleteRelease({\n id: releaseId,\n });\n\n if ('data' in response) {\n push('/plugins/content-releases');\n } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n return (\n <ReleaseDetailsLayout\n toggleEditReleaseModal={toggleEditReleaseModal}\n toggleWarningSubmit={toggleWarningSubmit}\n >\n <ReleaseDetailsBody />\n {releaseModalShown && (\n <ReleaseModal\n handleClose={toggleEditReleaseModal}\n handleSubmit={handleEditRelease}\n isLoading={isLoadingDetails || isSubmittingForm}\n initialValues={{ name: title || '' }}\n />\n )}\n <ConfirmDialog\n bodyText={{\n id: 'content-releases.dialog.confirmation-message',\n defaultMessage: 'Are you sure you want to delete this release?',\n }}\n isOpen={showWarningSubmit}\n isConfirmButtonLoading={isDeletingRelease}\n onToggleDialog={toggleWarningSubmit}\n onConfirm={handleDeleteRelease}\n />\n </ReleaseDetailsLayout>\n );\n};\n\nexport { ReleaseDetailsPage };\n","import * as React from 'react';\n\nimport {\n Box,\n Button,\n ContentLayout,\n Divider,\n EmptyStateLayout,\n Flex,\n Grid,\n GridItem,\n HeaderLayout,\n Main,\n Tab,\n TabGroup,\n TabPanel,\n TabPanels,\n Tabs,\n Typography,\n} from '@strapi/design-system';\nimport { Link } from '@strapi/design-system/v2';\nimport {\n AnErrorOccurred,\n CheckPermissions,\n LoadingIndicatorPage,\n PageSizeURLQuery,\n PaginationURLQuery,\n useQueryParams,\n useAPIErrorHandler,\n useNotification,\n} from '@strapi/helper-plugin';\nimport { EmptyDocuments, Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { useHistory, useLocation } from 'react-router-dom';\nimport styled from 'styled-components';\n\nimport { GetReleases } from '../../../shared/contracts/releases';\nimport { ReleaseModal, FormValues } from '../components/ReleaseModal';\nimport { PERMISSIONS } from '../constants';\nimport { isAxiosError } from '../services/axios';\nimport {\n useGetReleasesQuery,\n GetReleasesQueryParams,\n useCreateReleaseMutation,\n} from '../services/release';\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesLayout\n * -----------------------------------------------------------------------------------------------*/\ninterface ReleasesLayoutProps {\n isLoading?: boolean;\n totalReleases?: number;\n onClickAddRelease: () => void;\n children: React.ReactNode;\n}\n\nexport const ReleasesLayout = ({\n isLoading,\n totalReleases,\n onClickAddRelease,\n children,\n}: ReleasesLayoutProps) => {\n const { formatMessage } = useIntl();\n return (\n <Main aria-busy={isLoading}>\n <HeaderLayout\n title={formatMessage({\n id: 'content-releases.pages.Releases.title',\n defaultMessage: 'Releases',\n })}\n subtitle={\n !isLoading &&\n formatMessage(\n {\n id: 'content-releases.pages.Releases.header-subtitle',\n defaultMessage:\n '{number, plural, =0 {No releases} one {# release} other {# releases}}',\n },\n { number: totalReleases }\n )\n }\n primaryAction={\n <CheckPermissions permissions={PERMISSIONS.create}>\n <Button startIcon={<Plus />} onClick={onClickAddRelease}>\n {formatMessage({\n id: 'content-releases.header.actions.add-release',\n defaultMessage: 'New release',\n })}\n </Button>\n </CheckPermissions>\n }\n />\n {children}\n </Main>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesGrid\n * -----------------------------------------------------------------------------------------------*/\ninterface ReleasesGridProps {\n sectionTitle: 'pending' | 'done';\n releases?: GetReleases.Response['data'];\n isError?: boolean;\n}\n\nconst LinkCard = styled(Link)`\n display: block;\n`;\n\nconst ReleasesGrid = ({ sectionTitle, releases = [], isError = false }: ReleasesGridProps) => {\n const { formatMessage } = useIntl();\n\n if (isError) {\n return <AnErrorOccurred />;\n }\n\n if (releases?.length === 0) {\n return (\n <EmptyStateLayout\n content={formatMessage(\n {\n id: 'content-releases.page.Releases.tab.emptyEntries',\n defaultMessage: 'No releases',\n },\n {\n target: sectionTitle,\n }\n )}\n icon={<EmptyDocuments width=\"10rem\" />}\n />\n );\n }\n\n return (\n <Grid gap={4}>\n {releases.map(({ id, name, actions }) => (\n <GridItem col={3} s={6} xs={12} key={id}>\n <LinkCard href={`content-releases/${id}`} isExternal={false}>\n <Flex\n direction=\"column\"\n justifyContent=\"space-between\"\n padding={4}\n hasRadius\n background=\"neutral0\"\n shadow=\"tableShadow\"\n height=\"100%\"\n width=\"100%\"\n alignItems=\"start\"\n gap={2}\n >\n <Typography as=\"h3\" variant=\"delta\" fontWeight=\"bold\">\n {name}\n </Typography>\n <Typography variant=\"pi\">\n {formatMessage(\n {\n id: 'content-releases.page.Releases.release-item.entries',\n defaultMessage:\n '{number, plural, =0 {No entries} one {# entry} other {# entries}}',\n },\n { number: actions.meta.count }\n )}\n </Typography>\n </Flex>\n </LinkCard>\n </GridItem>\n ))}\n </Grid>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * ReleasesPage\n * -----------------------------------------------------------------------------------------------*/\ninterface CustomLocationState {\n errors?: Record<'code', string>[];\n}\n\nconst INITIAL_FORM_VALUES = {\n name: '',\n} satisfies FormValues;\n\nconst ReleasesPage = () => {\n const location = useLocation<CustomLocationState>();\n const [releaseModalShown, setReleaseModalShown] = React.useState(false);\n const toggleNotification = useNotification();\n const { formatMessage } = useIntl();\n const { push, replace } = useHistory();\n const { formatAPIError } = useAPIErrorHandler();\n const [{ query }, setQuery] = useQueryParams<GetReleasesQueryParams>();\n const response = useGetReleasesQuery(query);\n const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();\n\n const { isLoading, isSuccess, isError } = response;\n\n // Check if we have some errors and show a notification to the user to explain the error\n React.useEffect(() => {\n if (location?.state?.errors) {\n toggleNotification({\n type: 'warning',\n title: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.title',\n defaultMessage: 'Your request could not be processed.',\n }),\n message: formatMessage({\n id: 'content-releases.pages.Releases.notification.error.message',\n defaultMessage: 'Please try again or open another release.',\n }),\n });\n replace({ state: null });\n }\n }, [formatMessage, location?.state?.errors, replace, toggleNotification]);\n\n const toggleAddReleaseModal = () => {\n setReleaseModalShown((prev) => !prev);\n };\n\n if (isLoading) {\n return (\n <ReleasesLayout onClickAddRelease={toggleAddReleaseModal} isLoading>\n <ContentLayout>\n <LoadingIndicatorPage />\n </ContentLayout>\n </ReleasesLayout>\n );\n }\n\n const totalReleases = (isSuccess && response.currentData?.meta?.pagination?.total) || 0;\n\n const handleTabChange = (index: number) => {\n setQuery({\n ...query,\n page: 1,\n pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,\n filters: {\n releasedAt: {\n $notNull: index === 0 ? false : true,\n },\n },\n });\n };\n\n const activeTab = response?.currentData?.meta?.activeTab || 'pending';\n\n const handleAddRelease = async (values: FormValues) => {\n const response = await createRelease({\n name: values.name,\n });\n if ('data' in response) {\n // When the response returns an object with 'data', handle success\n toggleNotification({\n type: 'success',\n message: formatMessage({\n id: 'content-releases.modal.release-created-notification-success',\n defaultMessage: 'Release created.',\n }),\n });\n\n push(`/plugins/content-releases/${response.data.data.id}`);\n } else if (isAxiosError(response.error)) {\n // When the response returns an object with 'error', handle axios error\n toggleNotification({\n type: 'warning',\n message: formatAPIError(response.error),\n });\n } else {\n // Otherwise, the response returns an object with 'error', handle a generic error\n toggleNotification({\n type: 'warning',\n message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),\n });\n }\n };\n\n return (\n <ReleasesLayout onClickAddRelease={toggleAddReleaseModal} totalReleases={totalReleases}>\n <ContentLayout>\n <>\n <TabGroup\n label={formatMessage({\n id: 'content-releases.pages.Releases.tab-group.label',\n defaultMessage: 'Releases list',\n })}\n variant=\"simple\"\n initialSelectedTabIndex={['pending', 'done'].indexOf(activeTab)}\n onTabChange={handleTabChange}\n >\n <Box paddingBottom={8}>\n <Tabs>\n <Tab>\n {formatMessage({\n id: 'content-releases.pages.Releases.tab.pending',\n defaultMessage: 'Pending',\n })}\n </Tab>\n <Tab>\n {formatMessage({\n id: 'content-releases.pages.Releases.tab.done',\n defaultMessage: 'Done',\n })}\n </Tab>\n </Tabs>\n <Divider />\n </Box>\n <TabPanels>\n {/* Pending releases */}\n <TabPanel>\n <ReleasesGrid\n sectionTitle=\"pending\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </TabPanel>\n {/* Done releases */}\n <TabPanel>\n <ReleasesGrid\n sectionTitle=\"done\"\n releases={response?.currentData?.data}\n isError={isError}\n />\n </TabPanel>\n </TabPanels>\n </TabGroup>\n {totalReleases > 0 && (\n <Flex paddingTop={4} alignItems=\"flex-end\" justifyContent=\"space-between\">\n <PageSizeURLQuery\n options={['8', '16', '32', '64']}\n defaultValue={response?.currentData?.meta?.pagination?.pageSize.toString()}\n />\n <PaginationURLQuery\n pagination={{\n pageCount: response?.currentData?.meta?.pagination?.pageCount || 0,\n }}\n />\n </Flex>\n )}\n </>\n </ContentLayout>\n {releaseModalShown && (\n <ReleaseModal\n handleClose={toggleAddReleaseModal}\n handleSubmit={handleAddRelease}\n isLoading={isSubmittingForm}\n initialValues={INITIAL_FORM_VALUES}\n />\n )}\n </ReleasesLayout>\n );\n};\n\nexport { ReleasesPage };\n","import { CheckPagePermissions } from '@strapi/helper-plugin';\nimport { Route, Switch } from 'react-router-dom';\n\nimport { PERMISSIONS } from '../constants';\nimport { pluginId } from '../pluginId';\n\nimport { ReleaseDetailsPage } from './ReleaseDetailsPage';\nimport { ReleasesPage } from './ReleasesPage';\n\nexport const App = () => {\n return (\n <CheckPagePermissions permissions={PERMISSIONS.main}>\n <Switch>\n <Route exact path={`/plugins/${pluginId}`} component={ReleasesPage} />\n <Route exact path={`/plugins/${pluginId}/:releaseId`} component={ReleaseDetailsPage} />\n </Switch>\n </CheckPagePermissions>\n );\n};\n"],"names":["ReactRouterLink","Link","response"],"mappings":"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"}