@strapi/content-releases 4.16.2 → 4.17.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.
Files changed (85) hide show
  1. package/dist/_chunks/{App-b83f4a97.mjs → App-a4843fda.mjs} +143 -63
  2. package/dist/_chunks/App-a4843fda.mjs.map +1 -0
  3. package/dist/_chunks/{App-b6df6b60.js → App-f2cafd81.js} +138 -58
  4. package/dist/_chunks/App-f2cafd81.js.map +1 -0
  5. package/dist/_chunks/{en-b5dfabe6.js → en-13576ce2.js} +8 -2
  6. package/dist/_chunks/en-13576ce2.js.map +1 -0
  7. package/dist/_chunks/{en-d837b82d.mjs → en-e98d8b57.mjs} +8 -2
  8. package/dist/_chunks/en-e98d8b57.mjs.map +1 -0
  9. package/dist/_chunks/{index-28e99164.js → index-66d129ac.js} +66 -12
  10. package/dist/_chunks/index-66d129ac.js.map +1 -0
  11. package/dist/_chunks/{index-c39292e3.mjs → index-937f8179.mjs} +68 -14
  12. package/dist/_chunks/index-937f8179.mjs.map +1 -0
  13. package/dist/admin/index.js +2 -2
  14. package/dist/admin/index.mjs +2 -2
  15. package/dist/server/index.js.map +1 -1
  16. package/dist/server/index.mjs.map +1 -1
  17. package/package.json +10 -10
  18. package/dist/_chunks/App-b6df6b60.js.map +0 -1
  19. package/dist/_chunks/App-b83f4a97.mjs.map +0 -1
  20. package/dist/_chunks/en-b5dfabe6.js.map +0 -1
  21. package/dist/_chunks/en-d837b82d.mjs.map +0 -1
  22. package/dist/_chunks/index-28e99164.js.map +0 -1
  23. package/dist/_chunks/index-c39292e3.mjs.map +0 -1
  24. package/dist/admin/src/components/CMReleasesContainer.d.ts +0 -1
  25. package/dist/admin/src/components/ReleaseActionMenu.d.ts +0 -7
  26. package/dist/admin/src/components/ReleaseActionOptions.d.ts +0 -8
  27. package/dist/admin/src/components/ReleaseModal.d.ts +0 -11
  28. package/dist/admin/src/constants.d.ts +0 -13
  29. package/dist/admin/src/index.d.ts +0 -3
  30. package/dist/admin/src/pages/App.d.ts +0 -1
  31. package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +0 -10
  32. package/dist/admin/src/pages/ReleasesPage.d.ts +0 -11
  33. package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +0 -104
  34. package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +0 -38
  35. package/dist/admin/src/pluginId.d.ts +0 -1
  36. package/dist/admin/src/services/axios.d.ts +0 -29
  37. package/dist/admin/src/services/release.d.ts +0 -348
  38. package/dist/server/src/constants.d.ts +0 -9
  39. package/dist/server/src/constants.d.ts.map +0 -1
  40. package/dist/server/src/content-types/index.d.ts +0 -82
  41. package/dist/server/src/content-types/index.d.ts.map +0 -1
  42. package/dist/server/src/content-types/release/index.d.ts +0 -37
  43. package/dist/server/src/content-types/release/index.d.ts.map +0 -1
  44. package/dist/server/src/content-types/release/schema.d.ts +0 -36
  45. package/dist/server/src/content-types/release/schema.d.ts.map +0 -1
  46. package/dist/server/src/content-types/release-action/index.d.ts +0 -44
  47. package/dist/server/src/content-types/release-action/index.d.ts.map +0 -1
  48. package/dist/server/src/content-types/release-action/schema.d.ts +0 -43
  49. package/dist/server/src/content-types/release-action/schema.d.ts.map +0 -1
  50. package/dist/server/src/controllers/index.d.ts +0 -18
  51. package/dist/server/src/controllers/index.d.ts.map +0 -1
  52. package/dist/server/src/controllers/release-action.d.ts +0 -9
  53. package/dist/server/src/controllers/release-action.d.ts.map +0 -1
  54. package/dist/server/src/controllers/release.d.ts +0 -11
  55. package/dist/server/src/controllers/release.d.ts.map +0 -1
  56. package/dist/server/src/controllers/validation/release-action.d.ts +0 -3
  57. package/dist/server/src/controllers/validation/release-action.d.ts.map +0 -1
  58. package/dist/server/src/controllers/validation/release.d.ts +0 -2
  59. package/dist/server/src/controllers/validation/release.d.ts.map +0 -1
  60. package/dist/server/src/index.d.ts +0 -301
  61. package/dist/server/src/index.d.ts.map +0 -1
  62. package/dist/server/src/register.d.ts +0 -5
  63. package/dist/server/src/register.d.ts.map +0 -1
  64. package/dist/server/src/routes/index.d.ts +0 -35
  65. package/dist/server/src/routes/index.d.ts.map +0 -1
  66. package/dist/server/src/routes/release-action.d.ts +0 -18
  67. package/dist/server/src/routes/release-action.d.ts.map +0 -1
  68. package/dist/server/src/routes/release.d.ts +0 -18
  69. package/dist/server/src/routes/release.d.ts.map +0 -1
  70. package/dist/server/src/services/index.d.ts +0 -77
  71. package/dist/server/src/services/index.d.ts.map +0 -1
  72. package/dist/server/src/services/release.d.ts +0 -55
  73. package/dist/server/src/services/release.d.ts.map +0 -1
  74. package/dist/server/src/services/validation.d.ts +0 -10
  75. package/dist/server/src/services/validation.d.ts.map +0 -1
  76. package/dist/server/src/utils/index.d.ts +0 -4
  77. package/dist/server/src/utils/index.d.ts.map +0 -1
  78. package/dist/shared/contracts/release-actions.d.ts +0 -95
  79. package/dist/shared/contracts/release-actions.d.ts.map +0 -1
  80. package/dist/shared/contracts/releases.d.ts +0 -153
  81. package/dist/shared/contracts/releases.d.ts.map +0 -1
  82. package/dist/shared/types.d.ts +0 -24
  83. package/dist/shared/types.d.ts.map +0 -1
  84. package/dist/shared/validation-schemas.d.ts +0 -2
  85. package/dist/shared/validation-schemas.d.ts.map +0 -1
@@ -1,15 +1,15 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { useParams, useHistory, 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-c39292e3.mjs";
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";
4
4
  import * as React from "react";
5
- import { ModalLayout, ModalHeader, Typography, ModalBody, TextInput, ModalFooter, Button, Flex, ContentLayout, Main, Box, HeaderLayout, Link, IconButton, Popover, EmptyStateLayout, Tr, Td, TabGroup, Tabs, Tab, TabPanels, TabPanel, Grid, GridItem } from "@strapi/design-system";
6
- import { CheckPermissions, useNotification, useAPIErrorHandler, LoadingIndicatorPage, ConfirmDialog, AnErrorOccurred, RelativeTime, useQueryParams, Table, PageSizeURLQuery, PaginationURLQuery } from "@strapi/helper-plugin";
7
- import { Pencil, Trash, ArrowLeft, More, EmptyDocuments, Plus } from "@strapi/icons";
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 { 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
9
  import { useIntl } from "react-intl";
9
10
  import styled from "styled-components";
10
11
  import { Formik, Form } from "formik";
11
12
  import * as yup from "yup";
12
- import { Link as Link$1 } from "@strapi/design-system/v2";
13
13
  import "@reduxjs/toolkit/query";
14
14
  import "axios";
15
15
  import "@reduxjs/toolkit/query/react";
@@ -73,6 +73,14 @@ const ReleaseInfoWrapper = styled(Flex)`
73
73
  `;
74
74
  const StyledFlex = styled(Flex)`
75
75
  align-self: stretch;
76
+ cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
77
+
78
+ svg path {
79
+ fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
80
+ }
81
+ span {
82
+ color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
83
+ }
76
84
  `;
77
85
  const PencilIcon = styled(Pencil)`
78
86
  width: ${({ theme }) => theme.spaces[4]};
@@ -88,7 +96,7 @@ const TrashIcon = styled(Trash)`
88
96
  fill: ${({ theme }) => theme.colors.danger600};
89
97
  }
90
98
  `;
91
- const PopoverButton = ({ onClick, children }) => {
99
+ const PopoverButton = ({ onClick, disabled, children }) => {
92
100
  return /* @__PURE__ */ jsx(
93
101
  StyledFlex,
94
102
  {
@@ -101,6 +109,7 @@ const PopoverButton = ({ onClick, children }) => {
101
109
  as: "button",
102
110
  hasRadius: true,
103
111
  onClick,
112
+ disabled,
104
113
  children
105
114
  }
106
115
  );
@@ -114,10 +123,18 @@ const ReleaseDetailsLayout = ({
114
123
  const { releaseId } = useParams();
115
124
  const [isPopoverVisible, setIsPopoverVisible] = React.useState(false);
116
125
  const moreButtonRef = React.useRef(null);
117
- const { data, isLoading: isLoadingDetails, isError } = useGetReleaseQuery({ id: releaseId });
126
+ const {
127
+ data,
128
+ isLoading: isLoadingDetails,
129
+ isError,
130
+ error
131
+ } = useGetReleaseQuery({ id: releaseId });
118
132
  const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();
119
133
  const toggleNotification = useNotification();
120
134
  const { formatAPIError } = useAPIErrorHandler();
135
+ const {
136
+ allowedActions: { canUpdate, canDelete }
137
+ } = useRBAC(PERMISSIONS);
121
138
  const release = data?.data;
122
139
  const handleTogglePopover = () => {
123
140
  setIsPopoverVisible((prev) => !prev);
@@ -153,15 +170,29 @@ const ReleaseDetailsLayout = ({
153
170
  handleTogglePopover();
154
171
  };
155
172
  if (isLoadingDetails) {
156
- return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsx(Box, { paddingBottom: 8, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) }) });
173
+ return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
157
174
  }
158
175
  if (isError || !release) {
159
- return /* @__PURE__ */ jsx(Main, { children: /* @__PURE__ */ jsx(Box, { paddingBottom: 8, children: /* @__PURE__ */ jsx(AnErrorOccurred, {}) }) });
176
+ return /* @__PURE__ */ jsx(
177
+ Redirect,
178
+ {
179
+ to: {
180
+ pathname: "/plugins/content-releases",
181
+ state: {
182
+ errors: [
183
+ {
184
+ code: error?.code
185
+ }
186
+ ]
187
+ }
188
+ }
189
+ }
190
+ );
160
191
  }
161
192
  const totalEntries = release.actions.meta.count || 0;
162
193
  const createdBy = `${release.createdBy.firstname} ${release.createdBy.lastname}`;
163
194
  return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
164
- /* @__PURE__ */ jsx(Box, { paddingBottom: 8, children: /* @__PURE__ */ jsx(
195
+ /* @__PURE__ */ jsx(
165
196
  HeaderLayout,
166
197
  {
167
198
  title: release.name,
@@ -198,31 +229,22 @@ const ReleaseDetailsLayout = ({
198
229
  spacing: 4,
199
230
  minWidth: "242px",
200
231
  children: [
201
- /* @__PURE__ */ jsxs(
202
- Flex,
203
- {
204
- alignItems: "center",
205
- justifyContent: "center",
206
- direction: "column",
207
- padding: 1,
208
- children: [
209
- /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.update, children: /* @__PURE__ */ jsxs(PopoverButton, { onClick: openReleaseModal, children: [
210
- /* @__PURE__ */ jsx(PencilIcon, {}),
211
- /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
212
- id: "content-releases.header.actions.edit",
213
- defaultMessage: "Edit"
214
- }) })
215
- ] }) }),
216
- /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.delete, children: /* @__PURE__ */ jsxs(PopoverButton, { onClick: openWarningConfirmDialog, children: [
217
- /* @__PURE__ */ jsx(TrashIcon, {}),
218
- /* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
219
- id: "content-releases.header.actions.delete",
220
- defaultMessage: "Delete"
221
- }) })
222
- ] }) })
223
- ]
224
- }
225
- ),
232
+ /* @__PURE__ */ jsxs(Flex, { alignItems: "center", justifyContent: "center", direction: "column", padding: 1, children: [
233
+ /* @__PURE__ */ jsxs(PopoverButton, { disabled: !canUpdate, onClick: openReleaseModal, children: [
234
+ /* @__PURE__ */ jsx(PencilIcon, {}),
235
+ /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
236
+ id: "content-releases.header.actions.edit",
237
+ defaultMessage: "Edit"
238
+ }) })
239
+ ] }),
240
+ /* @__PURE__ */ jsxs(PopoverButton, { disabled: !canDelete, onClick: openWarningConfirmDialog, children: [
241
+ /* @__PURE__ */ jsx(TrashIcon, {}),
242
+ /* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
243
+ id: "content-releases.header.actions.delete",
244
+ defaultMessage: "Delete"
245
+ }) })
246
+ ] })
247
+ ] }),
226
248
  /* @__PURE__ */ jsxs(
227
249
  ReleaseInfoWrapper,
228
250
  {
@@ -252,10 +274,6 @@ const ReleaseDetailsLayout = ({
252
274
  ]
253
275
  }
254
276
  ),
255
- /* @__PURE__ */ jsx(Button, { size: "S", variant: "tertiary", children: formatMessage({
256
- id: "content-releases.header.actions.refresh",
257
- defaultMessage: "Refresh"
258
- }) }),
259
277
  /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.publish, children: /* @__PURE__ */ jsx(
260
278
  Button,
261
279
  {
@@ -272,7 +290,7 @@ const ReleaseDetailsLayout = ({
272
290
  ) })
273
291
  ] })
274
292
  }
275
- ) }),
293
+ ),
276
294
  children
277
295
  ] });
278
296
  };
@@ -285,10 +303,17 @@ const ReleaseDetailsBody = () => {
285
303
  const {
286
304
  data: releaseData,
287
305
  isLoading: isReleaseLoading,
288
- isError: isReleaseError
306
+ isError: isReleaseError,
307
+ error: releaseError
289
308
  } = useGetReleaseQuery({ id: releaseId });
290
309
  const release = releaseData?.data;
291
- const { isLoading, isFetching, isError, data } = useGetReleaseActionsQuery({
310
+ const {
311
+ isLoading,
312
+ isFetching,
313
+ isError,
314
+ data,
315
+ error: releaseActionsError
316
+ } = useGetReleaseActionsQuery({
292
317
  ...query,
293
318
  releaseId
294
319
  });
@@ -321,19 +346,54 @@ const ReleaseDetailsBody = () => {
321
346
  return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
322
347
  }
323
348
  if (isError || isReleaseError || !release) {
324
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(AnErrorOccurred, {}) });
349
+ const errorsArray = [];
350
+ if (releaseError) {
351
+ errorsArray.push({
352
+ code: releaseError.code
353
+ });
354
+ }
355
+ if (releaseActionsError) {
356
+ errorsArray.push({
357
+ code: releaseActionsError.code
358
+ });
359
+ }
360
+ return /* @__PURE__ */ jsx(
361
+ Redirect,
362
+ {
363
+ to: {
364
+ pathname: "/plugins/content-releases",
365
+ state: {
366
+ errors: errorsArray
367
+ }
368
+ }
369
+ }
370
+ );
325
371
  }
326
372
  const releaseActions = data?.data;
327
373
  const releaseMeta = data?.meta;
328
374
  if (!releaseActions || !releaseActions.length) {
329
375
  return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(
330
- EmptyStateLayout,
376
+ NoContent,
331
377
  {
332
- content: formatMessage({
333
- id: "content-releases.pages.Details.empty-state.content",
334
- defaultMessage: "This release is empty."
335
- }),
336
- icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem" })
378
+ content: {
379
+ id: "content-releases.pages.Details.tab.emptyEntries",
380
+ defaultMessage: "This release is empty. Open the Content Manager, select an entry and add it to the release."
381
+ },
382
+ action: /* @__PURE__ */ jsx(
383
+ LinkButton,
384
+ {
385
+ as: Link$1,
386
+ to: {
387
+ pathname: "/content-manager"
388
+ },
389
+ style: { textDecoration: "none" },
390
+ variant: "secondary",
391
+ children: formatMessage({
392
+ id: "content-releases.page.Details.button.openContentManager",
393
+ defaultMessage: "Open the Content Manager"
394
+ })
395
+ }
396
+ )
337
397
  }
338
398
  ) });
339
399
  }
@@ -573,7 +633,7 @@ const ReleasesLayout = ({
573
633
  children
574
634
  ] });
575
635
  };
576
- const LinkCard = styled(Link$1)`
636
+ const LinkCard = styled(Link$2)`
577
637
  display: block;
578
638
  `;
579
639
  const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
@@ -628,15 +688,32 @@ const INITIAL_FORM_VALUES = {
628
688
  name: ""
629
689
  };
630
690
  const ReleasesPage = () => {
691
+ const location = useLocation();
631
692
  const [releaseModalShown, setReleaseModalShown] = React.useState(false);
632
693
  const toggleNotification = useNotification();
633
694
  const { formatMessage } = useIntl();
634
- const { push } = useHistory();
695
+ const { push, replace } = useHistory();
635
696
  const { formatAPIError } = useAPIErrorHandler();
636
697
  const [{ query }, setQuery] = useQueryParams();
637
698
  const response = useGetReleasesQuery(query);
638
699
  const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();
639
700
  const { isLoading, isSuccess, isError } = response;
701
+ React.useEffect(() => {
702
+ if (location?.state?.errors) {
703
+ toggleNotification({
704
+ type: "warning",
705
+ title: formatMessage({
706
+ id: "content-releases.pages.Releases.notification.error.title",
707
+ defaultMessage: "Your request could not be processed."
708
+ }),
709
+ message: formatMessage({
710
+ id: "content-releases.pages.Releases.notification.error.message",
711
+ defaultMessage: "Please try again or open another release."
712
+ })
713
+ });
714
+ replace({ state: null });
715
+ }
716
+ }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
640
717
  const toggleAddReleaseModal = () => {
641
718
  setReleaseModalShown((prev) => !prev);
642
719
  };
@@ -695,16 +772,19 @@ const ReleasesPage = () => {
695
772
  initialSelectedTabIndex: ["pending", "done"].indexOf(activeTab),
696
773
  onTabChange: handleTabChange,
697
774
  children: [
698
- /* @__PURE__ */ jsx(Box, { paddingBottom: 8, children: /* @__PURE__ */ jsxs(Tabs, { children: [
699
- /* @__PURE__ */ jsx(Tab, { children: formatMessage({
700
- id: "content-releases.pages.Releases.tab.pending",
701
- defaultMessage: "Pending"
702
- }) }),
703
- /* @__PURE__ */ jsx(Tab, { children: formatMessage({
704
- id: "content-releases.pages.Releases.tab.done",
705
- defaultMessage: "Done"
706
- }) })
707
- ] }) }),
775
+ /* @__PURE__ */ jsxs(Box, { paddingBottom: 8, children: [
776
+ /* @__PURE__ */ jsxs(Tabs, { children: [
777
+ /* @__PURE__ */ jsx(Tab, { children: formatMessage({
778
+ id: "content-releases.pages.Releases.tab.pending",
779
+ defaultMessage: "Pending"
780
+ }) }),
781
+ /* @__PURE__ */ jsx(Tab, { children: formatMessage({
782
+ id: "content-releases.pages.Releases.tab.done",
783
+ defaultMessage: "Done"
784
+ }) })
785
+ ] }),
786
+ /* @__PURE__ */ jsx(Divider, {})
787
+ ] }),
708
788
  /* @__PURE__ */ jsxs(TabPanels, { children: [
709
789
  /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
710
790
  ReleasesGrid,
@@ -772,4 +852,4 @@ const App = () => {
772
852
  export {
773
853
  App
774
854
  };
775
- //# sourceMappingURL=App-b83f4a97.mjs.map
855
+ //# sourceMappingURL=App-a4843fda.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App-a4843fda.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';\n\nimport { RELEASE_SCHEMA } from '../../../shared/validation-schemas';\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\n return (\n <ModalLayout onClose={handleClose} labelledBy=\"title\">\n <ModalHeader>\n <Typography id=\"title\" fontWeight=\"bold\" textColor=\"neutral800\">\n {formatMessage({\n id: 'content-releases.modal.add-release-title',\n defaultMessage: 'New release',\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 name=\"submit\" loading={isLoading} disabled={!values.name} type=\"submit\">\n {formatMessage({\n id: 'content-releases.modal.form.button.submit',\n defaultMessage: 'Continue',\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} 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, 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 { 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 { ReleaseAction } 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 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.firstname} ${release.createdBy.lastname}`;\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 ReleaseDetailsBody = () => {\n const { formatMessage } = useIntl();\n const { releaseId } = useParams<{ releaseId: string }>();\n const [{ query }] = useQueryParams<GetReleaseActionsQueryParams>();\n const toggleNotification = useNotification();\n const { formatAPIError } = useAPIErrorHandler();\n const {\n data: releaseData,\n isLoading: isReleaseLoading,\n isError: isReleaseError,\n error: releaseError,\n } = useGetReleaseQuery({ id: releaseId });\n const release = releaseData?.data;\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 if (isError || isReleaseError || !release) {\n const errorsArray = [];\n if (releaseError) {\n errorsArray.push({\n code: releaseError.code,\n });\n }\n if (releaseActionsError) {\n errorsArray.push({\n code: releaseActionsError.code,\n });\n }\n return (\n <Redirect\n to={{\n pathname: '/plugins/content-releases',\n state: {\n errors: errorsArray,\n },\n }}\n />\n );\n }\n\n const releaseActions = data?.data;\n const releaseMeta = data?.meta;\n\n if (!releaseActions || !releaseActions.length) {\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={4} direction=\"column\" alignItems=\"stretch\">\n <Table.Root\n rows={releaseActions.map((item) => ({\n ...item,\n id: Number(item.entry.id),\n }))}\n colCount={releaseActions.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 </Table.Head>\n <Table.LoadingBody />\n <Table.Body>\n {releaseActions.map(({ id, type, entry }) => (\n <Tr key={id}>\n <Td>\n <Typography>{`${entry.contentType.mainFieldValue || entry.id}`}</Typography>\n </Td>\n <Td>\n <Typography>{`${entry?.locale?.name ? entry.locale.name : '-'}`}</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 </Tr>\n ))}\n </Table.Body>\n </Table.Content>\n </Table.Root>\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\nconst ProtectedReleaseDetailsPage = () => (\n <CheckPermissions permissions={PERMISSIONS.main}>\n <ReleaseDetailsPage />\n </CheckPermissions>\n);\n\nexport { ReleaseDetailsPage, ProtectedReleaseDetailsPage };\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\nconst ProtectedReleasesPage = () => (\n <CheckPermissions permissions={PERMISSIONS.main}>\n <ReleasesPage />\n </CheckPermissions>\n);\n\nexport { ReleasesPage, ProtectedReleasesPage };\n","import { Route, Switch } from 'react-router-dom';\n\nimport { pluginId } from '../pluginId';\n\nimport { ProtectedReleaseDetailsPage } from './ReleaseDetailsPage';\nimport { ProtectedReleasesPage } from './ReleasesPage';\n\nexport const App = () => {\n return (\n <Switch>\n <Route exact path={`/plugins/${pluginId}`} component={ProtectedReleasesPage} />\n <Route\n exact\n path={`/plugins/${pluginId}/:releaseId`}\n component={ProtectedReleaseDetailsPage}\n />\n </Switch>\n );\n};\n"],"names":["ReactRouterLink","Link","response"],"mappings":"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"}