@strapi/content-releases 0.0.0-experimental.950b677f6614f483cde77801d941607d6847a6e3 → 0.0.0-experimental.cae3a5a17d131a6f59673b62d01cfac869ea9cc2

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 (89) hide show
  1. package/dist/_chunks/{App-3f94ba77.mjs → App-_Jj3tWts.mjs} +350 -154
  2. package/dist/_chunks/App-_Jj3tWts.mjs.map +1 -0
  3. package/dist/_chunks/{App-ae9b2380.js → App-iqqoPnBO.js} +347 -151
  4. package/dist/_chunks/App-iqqoPnBO.js.map +1 -0
  5. package/dist/_chunks/{en-13576ce2.js → en-2DuPv5k0.js} +17 -4
  6. package/dist/_chunks/en-2DuPv5k0.js.map +1 -0
  7. package/dist/_chunks/{en-e98d8b57.mjs → en-SOqjCdyh.mjs} +17 -4
  8. package/dist/_chunks/en-SOqjCdyh.mjs.map +1 -0
  9. package/dist/_chunks/{index-40da7f6d.js → index-_lT-gI3M.js} +126 -37
  10. package/dist/_chunks/index-_lT-gI3M.js.map +1 -0
  11. package/dist/_chunks/{index-6ddf4a38.mjs → index-bsuc8ZwZ.mjs} +137 -48
  12. package/dist/_chunks/index-bsuc8ZwZ.mjs.map +1 -0
  13. package/dist/admin/index.js +2 -1
  14. package/dist/admin/index.js.map +1 -1
  15. package/dist/admin/index.mjs +3 -2
  16. package/dist/admin/index.mjs.map +1 -1
  17. package/dist/server/index.js +359 -102
  18. package/dist/server/index.js.map +1 -1
  19. package/dist/server/index.mjs +357 -103
  20. package/dist/server/index.mjs.map +1 -1
  21. package/package.json +13 -11
  22. package/dist/_chunks/App-3f94ba77.mjs.map +0 -1
  23. package/dist/_chunks/App-ae9b2380.js.map +0 -1
  24. package/dist/_chunks/en-13576ce2.js.map +0 -1
  25. package/dist/_chunks/en-e98d8b57.mjs.map +0 -1
  26. package/dist/_chunks/index-40da7f6d.js.map +0 -1
  27. package/dist/_chunks/index-6ddf4a38.mjs.map +0 -1
  28. package/dist/admin/src/components/CMReleasesContainer.d.ts +0 -1
  29. package/dist/admin/src/components/ReleaseActionMenu.d.ts +0 -7
  30. package/dist/admin/src/components/ReleaseActionOptions.d.ts +0 -8
  31. package/dist/admin/src/components/ReleaseModal.d.ts +0 -11
  32. package/dist/admin/src/constants.d.ts +0 -58
  33. package/dist/admin/src/index.d.ts +0 -3
  34. package/dist/admin/src/pages/App.d.ts +0 -1
  35. package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +0 -10
  36. package/dist/admin/src/pages/ReleasesPage.d.ts +0 -11
  37. package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +0 -104
  38. package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +0 -38
  39. package/dist/admin/src/pluginId.d.ts +0 -1
  40. package/dist/admin/src/services/axios.d.ts +0 -29
  41. package/dist/admin/src/services/release.d.ts +0 -348
  42. package/dist/server/src/constants.d.ts +0 -9
  43. package/dist/server/src/constants.d.ts.map +0 -1
  44. package/dist/server/src/content-types/index.d.ts +0 -82
  45. package/dist/server/src/content-types/index.d.ts.map +0 -1
  46. package/dist/server/src/content-types/release/index.d.ts +0 -37
  47. package/dist/server/src/content-types/release/index.d.ts.map +0 -1
  48. package/dist/server/src/content-types/release/schema.d.ts +0 -36
  49. package/dist/server/src/content-types/release/schema.d.ts.map +0 -1
  50. package/dist/server/src/content-types/release-action/index.d.ts +0 -44
  51. package/dist/server/src/content-types/release-action/index.d.ts.map +0 -1
  52. package/dist/server/src/content-types/release-action/schema.d.ts +0 -43
  53. package/dist/server/src/content-types/release-action/schema.d.ts.map +0 -1
  54. package/dist/server/src/controllers/index.d.ts +0 -18
  55. package/dist/server/src/controllers/index.d.ts.map +0 -1
  56. package/dist/server/src/controllers/release-action.d.ts +0 -9
  57. package/dist/server/src/controllers/release-action.d.ts.map +0 -1
  58. package/dist/server/src/controllers/release.d.ts +0 -11
  59. package/dist/server/src/controllers/release.d.ts.map +0 -1
  60. package/dist/server/src/controllers/validation/release-action.d.ts +0 -3
  61. package/dist/server/src/controllers/validation/release-action.d.ts.map +0 -1
  62. package/dist/server/src/controllers/validation/release.d.ts +0 -2
  63. package/dist/server/src/controllers/validation/release.d.ts.map +0 -1
  64. package/dist/server/src/index.d.ts +0 -3749
  65. package/dist/server/src/index.d.ts.map +0 -1
  66. package/dist/server/src/register.d.ts +0 -5
  67. package/dist/server/src/register.d.ts.map +0 -1
  68. package/dist/server/src/routes/index.d.ts +0 -35
  69. package/dist/server/src/routes/index.d.ts.map +0 -1
  70. package/dist/server/src/routes/release-action.d.ts +0 -18
  71. package/dist/server/src/routes/release-action.d.ts.map +0 -1
  72. package/dist/server/src/routes/release.d.ts +0 -18
  73. package/dist/server/src/routes/release.d.ts.map +0 -1
  74. package/dist/server/src/services/index.d.ts +0 -3525
  75. package/dist/server/src/services/index.d.ts.map +0 -1
  76. package/dist/server/src/services/release.d.ts +0 -1779
  77. package/dist/server/src/services/release.d.ts.map +0 -1
  78. package/dist/server/src/services/validation.d.ts +0 -10
  79. package/dist/server/src/services/validation.d.ts.map +0 -1
  80. package/dist/server/src/utils/index.d.ts +0 -4
  81. package/dist/server/src/utils/index.d.ts.map +0 -1
  82. package/dist/shared/contracts/release-actions.d.ts +0 -95
  83. package/dist/shared/contracts/release-actions.d.ts.map +0 -1
  84. package/dist/shared/contracts/releases.d.ts +0 -153
  85. package/dist/shared/contracts/releases.d.ts.map +0 -1
  86. package/dist/shared/types.d.ts +0 -24
  87. package/dist/shared/types.d.ts.map +0 -1
  88. package/dist/shared/validation-schemas.d.ts +0 -2
  89. package/dist/shared/validation-schemas.d.ts.map +0 -1
@@ -1,11 +1,12 @@
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, f as ReleaseActionMenu, i as isAxiosError, g as useGetReleasesQuery, h as useCreateReleaseMutation, p as pluginId } from "./index-6ddf4a38.mjs";
2
+ import { useNotification, useAPIErrorHandler, LoadingIndicatorPage, ConfirmDialog, useRBAC, RelativeTime, CheckPermissions, useQueryParams, AnErrorOccurred, NoContent, Table, PageSizeURLQuery, PaginationURLQuery, 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 useTypedDispatch, e as useGetReleaseActionsQuery, f as useUpdateReleaseActionMutation, R as ReleaseActionOptions, g as ReleaseActionMenu, i as isAxiosError, r as releaseApi, h as useGetReleasesQuery, j as useCreateReleaseMutation } from "./index-bsuc8ZwZ.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 { unstable_useDocument, useLicenseLimits } from "@strapi/admin/strapi-admin";
7
+ import { ModalLayout, ModalHeader, Typography, ModalBody, TextInput, ModalFooter, Button, Flex, ContentLayout, Main, HeaderLayout, Link, IconButton, Popover, SingleSelect, SingleSelectOption, Badge, Tr, Td, Icon, Tooltip, Alert, TabGroup, Box, Tabs, Tab, Divider, TabPanels, TabPanel, EmptyStateLayout, Grid, GridItem } from "@strapi/design-system";
6
8
  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";
9
+ import { Pencil, Trash, ArrowLeft, More, CrossCircle, CheckCircle, Plus, EmptyDocuments } from "@strapi/icons";
9
10
  import { useIntl } from "react-intl";
10
11
  import styled from "styled-components";
11
12
  import { Formik, Form } from "formik";
@@ -13,6 +14,7 @@ import * as yup from "yup";
13
14
  import "@reduxjs/toolkit/query";
14
15
  import "axios";
15
16
  import "@reduxjs/toolkit/query/react";
17
+ import "react-redux";
16
18
  const RELEASE_SCHEMA = yup.object().shape({
17
19
  name: yup.string().trim().required()
18
20
  }).required().noUnknown();
@@ -23,11 +25,16 @@ const ReleaseModal = ({
23
25
  isLoading = false
24
26
  }) => {
25
27
  const { formatMessage } = useIntl();
28
+ const { pathname } = useLocation();
29
+ const isCreatingRelease = pathname === `/plugins/${pluginId}`;
26
30
  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
- }) }) }),
31
+ /* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage(
32
+ {
33
+ id: "content-releases.modal.title",
34
+ defaultMessage: "{isCreatingRelease, select, true {New release} other {Edit release}}"
35
+ },
36
+ { isCreatingRelease }
37
+ ) }) }),
31
38
  /* @__PURE__ */ jsx(
32
39
  Formik,
33
40
  {
@@ -54,10 +61,22 @@ const ReleaseModal = ({
54
61
  ModalFooter,
55
62
  {
56
63
  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
- }) })
64
+ endActions: /* @__PURE__ */ jsx(
65
+ Button,
66
+ {
67
+ name: "submit",
68
+ loading: isLoading,
69
+ disabled: !values.name || values.name === initialValues.name,
70
+ type: "submit",
71
+ children: formatMessage(
72
+ {
73
+ id: "content-releases.modal.form.button.submit",
74
+ defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
75
+ },
76
+ { isCreatingRelease }
77
+ )
78
+ }
79
+ )
61
80
  }
62
81
  )
63
82
  ] })
@@ -96,6 +115,9 @@ const TrashIcon = styled(Trash)`
96
115
  fill: ${({ theme }) => theme.colors.danger600};
97
116
  }
98
117
  `;
118
+ const TypographyMaxWidth = styled(Typography)`
119
+ max-width: 300px;
120
+ `;
99
121
  const PopoverButton = ({ onClick, disabled, children }) => {
100
122
  return /* @__PURE__ */ jsx(
101
123
  StyledFlex,
@@ -114,6 +136,49 @@ const PopoverButton = ({ onClick, disabled, children }) => {
114
136
  }
115
137
  );
116
138
  };
139
+ const EntryValidationText = ({ action, schema, components, entry }) => {
140
+ const { formatMessage } = useIntl();
141
+ const { validate } = unstable_useDocument();
142
+ const { errors } = validate(entry, {
143
+ contentType: schema,
144
+ components,
145
+ isCreatingEntry: false
146
+ });
147
+ if (Object.keys(errors).length > 0) {
148
+ const validationErrorsMessages = Object.entries(errors).map(
149
+ ([key, value]) => formatMessage(
150
+ { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
151
+ { field: key }
152
+ )
153
+ ).join(" ");
154
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
155
+ /* @__PURE__ */ jsx(Icon, { color: "danger600", as: CrossCircle }),
156
+ /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
157
+ ] });
158
+ }
159
+ if (action == "publish") {
160
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
161
+ /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
162
+ entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
163
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
164
+ defaultMessage: "Already published"
165
+ }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
166
+ id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
167
+ defaultMessage: "Ready to publish"
168
+ }) })
169
+ ] });
170
+ }
171
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
172
+ /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
173
+ !entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
174
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
175
+ defaultMessage: "Already unpublished"
176
+ }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
177
+ id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish",
178
+ defaultMessage: "Ready to unpublish"
179
+ }) })
180
+ ] });
181
+ };
117
182
  const ReleaseDetailsLayout = ({
118
183
  toggleEditReleaseModal,
119
184
  toggleWarningSubmit,
@@ -135,6 +200,7 @@ const ReleaseDetailsLayout = ({
135
200
  const {
136
201
  allowedActions: { canUpdate, canDelete }
137
202
  } = useRBAC(PERMISSIONS);
203
+ const dispatch = useTypedDispatch();
138
204
  const release = data?.data;
139
205
  const handleTogglePopover = () => {
140
206
  setIsPopoverVisible((prev) => !prev);
@@ -169,6 +235,9 @@ const ReleaseDetailsLayout = ({
169
235
  toggleWarningSubmit();
170
236
  handleTogglePopover();
171
237
  };
238
+ const handleRefresh = () => {
239
+ dispatch(releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
240
+ };
172
241
  if (isLoadingDetails) {
173
242
  return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
174
243
  }
@@ -190,7 +259,7 @@ const ReleaseDetailsLayout = ({
190
259
  );
191
260
  }
192
261
  const totalEntries = release.actions.meta.count || 0;
193
- const createdBy = `${release.createdBy.firstname} ${release.createdBy.lastname}`;
262
+ const createdBy = release.createdBy.lastname ? `${release.createdBy.firstname} ${release.createdBy.lastname}` : `${release.createdBy.firstname}`;
194
263
  return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
195
264
  /* @__PURE__ */ jsx(
196
265
  HeaderLayout,
@@ -274,6 +343,10 @@ const ReleaseDetailsLayout = ({
274
343
  ]
275
344
  }
276
345
  ),
346
+ /* @__PURE__ */ jsx(Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
347
+ id: "content-releases.header.actions.refresh",
348
+ defaultMessage: "Refresh"
349
+ }) }),
277
350
  /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.publish, children: /* @__PURE__ */ jsx(
278
351
  Button,
279
352
  {
@@ -294,10 +367,29 @@ const ReleaseDetailsLayout = ({
294
367
  children
295
368
  ] });
296
369
  };
370
+ const GROUP_BY_OPTIONS = ["contentType", "locale", "action"];
371
+ const getGroupByOptionLabel = (value) => {
372
+ if (value === "locale") {
373
+ return {
374
+ id: "content-releases.pages.ReleaseDetails.groupBy.option.locales",
375
+ defaultMessage: "Locales"
376
+ };
377
+ }
378
+ if (value === "action") {
379
+ return {
380
+ id: "content-releases.pages.ReleaseDetails.groupBy.option.actions",
381
+ defaultMessage: "Actions"
382
+ };
383
+ }
384
+ return {
385
+ id: "content-releases.pages.ReleaseDetails.groupBy.option.content-type",
386
+ defaultMessage: "Content-Types"
387
+ };
388
+ };
297
389
  const ReleaseDetailsBody = () => {
298
390
  const { formatMessage } = useIntl();
299
391
  const { releaseId } = useParams();
300
- const [{ query }] = useQueryParams();
392
+ const [{ query }, setQuery] = useQueryParams();
301
393
  const toggleNotification = useNotification();
302
394
  const { formatAPIError } = useAPIErrorHandler();
303
395
  const {
@@ -307,6 +399,7 @@ const ReleaseDetailsBody = () => {
307
399
  error: releaseError
308
400
  } = useGetReleaseQuery({ id: releaseId });
309
401
  const release = releaseData?.data;
402
+ const selectedGroupBy = query?.groupBy || "contentType";
310
403
  const {
311
404
  isLoading,
312
405
  isFetching,
@@ -318,7 +411,7 @@ const ReleaseDetailsBody = () => {
318
411
  releaseId
319
412
  });
320
413
  const [updateReleaseAction] = useUpdateReleaseActionMutation();
321
- const handleChangeType = async (e, actionId) => {
414
+ const handleChangeType = async (e, actionId, actionPath) => {
322
415
  const response = await updateReleaseAction({
323
416
  params: {
324
417
  releaseId,
@@ -326,7 +419,11 @@ const ReleaseDetailsBody = () => {
326
419
  },
327
420
  body: {
328
421
  type: e.target.value
329
- }
422
+ },
423
+ query,
424
+ // We are passing the query params to make optimistic updates
425
+ actionPath
426
+ // We are passing the action path to found the position in the cache of the action for optimistic updates
330
427
  });
331
428
  if ("error" in response) {
332
429
  if (isAxiosError(response.error)) {
@@ -345,7 +442,11 @@ const ReleaseDetailsBody = () => {
345
442
  if (isLoading || isReleaseLoading) {
346
443
  return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
347
444
  }
348
- if (isError || isReleaseError || !release) {
445
+ const releaseActions = data?.data;
446
+ const releaseMeta = data?.meta;
447
+ const contentTypes = releaseMeta?.contentTypes || {};
448
+ const components = releaseMeta?.components || {};
449
+ if (isReleaseError || !release) {
349
450
  const errorsArray = [];
350
451
  if (releaseError) {
351
452
  errorsArray.push({
@@ -369,9 +470,10 @@ const ReleaseDetailsBody = () => {
369
470
  }
370
471
  );
371
472
  }
372
- const releaseActions = data?.data;
373
- const releaseMeta = data?.meta;
374
- if (!releaseActions || !releaseActions.length) {
473
+ if (isError || !releaseActions) {
474
+ return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(AnErrorOccurred, {}) });
475
+ }
476
+ if (Object.keys(releaseActions).length === 0) {
375
477
  return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(
376
478
  NoContent,
377
479
  {
@@ -397,92 +499,155 @@ const ReleaseDetailsBody = () => {
397
499
  }
398
500
  ) });
399
501
  }
400
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
401
- /* @__PURE__ */ jsx(
402
- Table.Root,
502
+ return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
503
+ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
504
+ SingleSelect,
403
505
  {
404
- rows: releaseActions.map((action) => ({
405
- ...action,
406
- id: Number(action.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
- /* @__PURE__ */ jsx(Table.HeaderHiddenActionsCell, {})
458
- ] }),
459
- /* @__PURE__ */ jsx(Table.LoadingBody, {}),
460
- /* @__PURE__ */ jsx(Table.Body, { children: releaseActions.map(({ id, type, entry }) => /* @__PURE__ */ jsxs(Tr, { children: [
461
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: `${entry.contentType.mainFieldValue || entry.id}` }) }),
462
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: `${entry?.locale?.name ? entry.locale.name : "-"}` }) }),
463
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: entry.contentType.displayName || "" }) }),
464
- /* @__PURE__ */ jsx(Td, { children: release.releasedAt ? /* @__PURE__ */ jsx(Typography, { children: formatMessage(
465
- {
466
- id: "content-releases.page.ReleaseDetails.table.action-published",
467
- defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
468
- },
469
- {
470
- isPublish: type === "publish",
471
- b: (children) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children })
472
- }
473
- ) }) : /* @__PURE__ */ jsx(
474
- ReleaseActionOptions,
475
- {
476
- selected: type,
477
- handleChange: (e) => handleChangeType(e, id),
478
- name: `release-action-${id}-type`
479
- }
480
- ) }),
481
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(ReleaseActionMenu, { releaseId, actionId: id }) }) })
482
- ] }, id)) })
483
- ] })
506
+ "aria-label": formatMessage({
507
+ id: "content-releases.pages.ReleaseDetails.groupBy.label",
508
+ defaultMessage: "Group by"
509
+ }),
510
+ customizeContent: (value) => formatMessage(
511
+ {
512
+ id: `content-releases.pages.ReleaseDetails.groupBy.label`,
513
+ defaultMessage: `Group by {groupBy}`
514
+ },
515
+ {
516
+ groupBy: value
517
+ }
518
+ ),
519
+ value: formatMessage(getGroupByOptionLabel(selectedGroupBy)),
520
+ onChange: (value) => setQuery({ groupBy: value }),
521
+ children: GROUP_BY_OPTIONS.map((option) => /* @__PURE__ */ jsx(SingleSelectOption, { value: option, children: formatMessage(getGroupByOptionLabel(option)) }, option))
484
522
  }
485
- ),
523
+ ) }),
524
+ Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
525
+ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(Badge, { children: key }) }),
526
+ /* @__PURE__ */ jsx(
527
+ Table.Root,
528
+ {
529
+ rows: releaseActions[key].map((item) => ({
530
+ ...item,
531
+ id: Number(item.entry.id)
532
+ })),
533
+ colCount: releaseActions[key].length,
534
+ isLoading,
535
+ isFetching,
536
+ children: /* @__PURE__ */ jsxs(Table.Content, { children: [
537
+ /* @__PURE__ */ jsxs(Table.Head, { children: [
538
+ /* @__PURE__ */ jsx(
539
+ Table.HeaderCell,
540
+ {
541
+ fieldSchemaType: "string",
542
+ label: formatMessage({
543
+ id: "content-releases.page.ReleaseDetails.table.header.label.name",
544
+ defaultMessage: "name"
545
+ }),
546
+ name: "name"
547
+ }
548
+ ),
549
+ /* @__PURE__ */ jsx(
550
+ Table.HeaderCell,
551
+ {
552
+ fieldSchemaType: "string",
553
+ label: formatMessage({
554
+ id: "content-releases.page.ReleaseDetails.table.header.label.locale",
555
+ defaultMessage: "locale"
556
+ }),
557
+ name: "locale"
558
+ }
559
+ ),
560
+ /* @__PURE__ */ jsx(
561
+ Table.HeaderCell,
562
+ {
563
+ fieldSchemaType: "string",
564
+ label: formatMessage({
565
+ id: "content-releases.page.ReleaseDetails.table.header.label.content-type",
566
+ defaultMessage: "content-type"
567
+ }),
568
+ name: "content-type"
569
+ }
570
+ ),
571
+ /* @__PURE__ */ jsx(
572
+ Table.HeaderCell,
573
+ {
574
+ fieldSchemaType: "string",
575
+ label: formatMessage({
576
+ id: "content-releases.page.ReleaseDetails.table.header.label.action",
577
+ defaultMessage: "action"
578
+ }),
579
+ name: "action"
580
+ }
581
+ ),
582
+ !release.releasedAt && /* @__PURE__ */ jsx(
583
+ Table.HeaderCell,
584
+ {
585
+ fieldSchemaType: "string",
586
+ label: formatMessage({
587
+ id: "content-releases.page.ReleaseDetails.table.header.label.status",
588
+ defaultMessage: "status"
589
+ }),
590
+ name: "status"
591
+ }
592
+ )
593
+ ] }),
594
+ /* @__PURE__ */ jsx(Table.LoadingBody, {}),
595
+ /* @__PURE__ */ jsx(Table.Body, { children: releaseActions[key].map(
596
+ ({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxs(Tr, { children: [
597
+ /* @__PURE__ */ jsx(Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
598
+ /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
599
+ /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: contentType.displayName || "" }) }),
600
+ /* @__PURE__ */ jsx(Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsx(Typography, { children: formatMessage(
601
+ {
602
+ id: "content-releases.page.ReleaseDetails.table.action-published",
603
+ defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
604
+ },
605
+ {
606
+ isPublish: type === "publish",
607
+ b: (children) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children })
608
+ }
609
+ ) }) : /* @__PURE__ */ jsx(
610
+ ReleaseActionOptions,
611
+ {
612
+ selected: type,
613
+ handleChange: (e) => handleChangeType(e, id, [key, actionIndex]),
614
+ name: `release-action-${id}-type`
615
+ }
616
+ ) }),
617
+ !release.releasedAt && /* @__PURE__ */ jsxs(Fragment, { children: [
618
+ /* @__PURE__ */ jsx(Td, { width: "20%", minWidth: "200px", children: /* @__PURE__ */ jsx(
619
+ EntryValidationText,
620
+ {
621
+ action: type,
622
+ schema: contentTypes?.[contentType.uid],
623
+ components,
624
+ entry
625
+ }
626
+ ) }),
627
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { children: [
628
+ /* @__PURE__ */ jsx(
629
+ ReleaseActionMenu.ReleaseActionEntryLinkItem,
630
+ {
631
+ contentTypeUid: contentType.uid,
632
+ entryId: entry.id,
633
+ locale: locale?.code
634
+ }
635
+ ),
636
+ /* @__PURE__ */ jsx(
637
+ ReleaseActionMenu.DeleteReleaseActionItem,
638
+ {
639
+ releaseId: release.id,
640
+ actionId: id
641
+ }
642
+ )
643
+ ] }) }) })
644
+ ] })
645
+ ] }, id)
646
+ ) })
647
+ ] })
648
+ }
649
+ )
650
+ ] }, `releases-group-${key}`)),
486
651
  /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
487
652
  /* @__PURE__ */ jsx(PageSizeURLQuery, { defaultValue: releaseMeta?.pagination?.pageSize.toString() }),
488
653
  /* @__PURE__ */ jsx(
@@ -603,38 +768,6 @@ const ReleaseDetailsPage = () => {
603
768
  }
604
769
  );
605
770
  };
606
- const ProtectedReleaseDetailsPage = () => /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsx(ReleaseDetailsPage, {}) });
607
- const ReleasesLayout = ({
608
- isLoading,
609
- totalReleases,
610
- onClickAddRelease,
611
- children
612
- }) => {
613
- const { formatMessage } = useIntl();
614
- return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoading, children: [
615
- /* @__PURE__ */ jsx(
616
- HeaderLayout,
617
- {
618
- title: formatMessage({
619
- id: "content-releases.pages.Releases.title",
620
- defaultMessage: "Releases"
621
- }),
622
- subtitle: !isLoading && formatMessage(
623
- {
624
- id: "content-releases.pages.Releases.header-subtitle",
625
- defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
626
- },
627
- { number: totalReleases }
628
- ),
629
- primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(Button, { startIcon: /* @__PURE__ */ jsx(Plus, {}), onClick: onClickAddRelease, children: formatMessage({
630
- id: "content-releases.header.actions.add-release",
631
- defaultMessage: "New release"
632
- }) }) })
633
- }
634
- ),
635
- children
636
- ] });
637
- };
638
771
  const LinkCard = styled(Link$2)`
639
772
  display: block;
640
773
  `;
@@ -686,10 +819,19 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
686
819
  }
687
820
  ) }) }, id)) });
688
821
  };
822
+ const StyledAlert = styled(Alert)`
823
+ button {
824
+ display: none;
825
+ }
826
+ p + div {
827
+ margin-left: auto;
828
+ }
829
+ `;
689
830
  const INITIAL_FORM_VALUES = {
690
831
  name: ""
691
832
  };
692
833
  const ReleasesPage = () => {
834
+ const tabRef = React.useRef(null);
693
835
  const location = useLocation();
694
836
  const [releaseModalShown, setReleaseModalShown] = React.useState(false);
695
837
  const toggleNotification = useNotification();
@@ -699,7 +841,11 @@ const ReleasesPage = () => {
699
841
  const [{ query }, setQuery] = useQueryParams();
700
842
  const response = useGetReleasesQuery(query);
701
843
  const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();
844
+ const { getFeature } = useLicenseLimits();
845
+ const { maximumNumberOfPendingReleases = 3 } = getFeature("cms-content-releases");
702
846
  const { isLoading, isSuccess, isError } = response;
847
+ const activeTab = response?.currentData?.meta?.activeTab || "pending";
848
+ const activeTabIndex = ["pending", "done"].indexOf(activeTab);
703
849
  React.useEffect(() => {
704
850
  if (location?.state?.errors) {
705
851
  toggleNotification({
@@ -716,13 +862,19 @@ const ReleasesPage = () => {
716
862
  replace({ state: null });
717
863
  }
718
864
  }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
865
+ React.useEffect(() => {
866
+ if (tabRef.current) {
867
+ tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
868
+ }
869
+ }, [activeTabIndex]);
719
870
  const toggleAddReleaseModal = () => {
720
871
  setReleaseModalShown((prev) => !prev);
721
872
  };
722
873
  if (isLoading) {
723
- return /* @__PURE__ */ jsx(ReleasesLayout, { onClickAddRelease: toggleAddReleaseModal, isLoading: true, children: /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) }) });
874
+ return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
724
875
  }
725
876
  const totalReleases = isSuccess && response.currentData?.meta?.pagination?.total || 0;
877
+ const hasReachedMaximumPendingReleases = totalReleases >= maximumNumberOfPendingReleases;
726
878
  const handleTabChange = (index) => {
727
879
  setQuery({
728
880
  ...query,
@@ -735,7 +887,6 @@ const ReleasesPage = () => {
735
887
  }
736
888
  });
737
889
  };
738
- const activeTab = response?.currentData?.meta?.activeTab || "pending";
739
890
  const handleAddRelease = async (values) => {
740
891
  const response2 = await createRelease({
741
892
  name: values.name
@@ -761,8 +912,60 @@ const ReleasesPage = () => {
761
912
  });
762
913
  }
763
914
  };
764
- return /* @__PURE__ */ jsxs(ReleasesLayout, { onClickAddRelease: toggleAddReleaseModal, totalReleases, children: [
915
+ return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoading, children: [
916
+ /* @__PURE__ */ jsx(
917
+ HeaderLayout,
918
+ {
919
+ title: formatMessage({
920
+ id: "content-releases.pages.Releases.title",
921
+ defaultMessage: "Releases"
922
+ }),
923
+ subtitle: formatMessage(
924
+ {
925
+ id: "content-releases.pages.Releases.header-subtitle",
926
+ defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
927
+ },
928
+ { number: totalReleases }
929
+ ),
930
+ primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(
931
+ Button,
932
+ {
933
+ startIcon: /* @__PURE__ */ jsx(Plus, {}),
934
+ onClick: toggleAddReleaseModal,
935
+ disabled: hasReachedMaximumPendingReleases,
936
+ children: formatMessage({
937
+ id: "content-releases.header.actions.add-release",
938
+ defaultMessage: "New release"
939
+ })
940
+ }
941
+ ) })
942
+ }
943
+ ),
765
944
  /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
945
+ activeTab === "pending" && hasReachedMaximumPendingReleases && /* @__PURE__ */ jsx(
946
+ StyledAlert,
947
+ {
948
+ marginBottom: 6,
949
+ action: /* @__PURE__ */ jsx(Link$2, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
950
+ id: "content-releases.pages.Releases.max-limit-reached.action",
951
+ defaultMessage: "Explore plans"
952
+ }) }),
953
+ title: formatMessage(
954
+ {
955
+ id: "content-releases.pages.Releases.max-limit-reached.title",
956
+ defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
957
+ },
958
+ { number: maximumNumberOfPendingReleases }
959
+ ),
960
+ onClose: () => {
961
+ },
962
+ closeLabel: "",
963
+ children: formatMessage({
964
+ id: "content-releases.pages.Releases.max-limit-reached.message",
965
+ defaultMessage: "Upgrade to manage an unlimited number of releases."
966
+ })
967
+ }
968
+ ),
766
969
  /* @__PURE__ */ jsxs(
767
970
  TabGroup,
768
971
  {
@@ -771,8 +974,9 @@ const ReleasesPage = () => {
771
974
  defaultMessage: "Releases list"
772
975
  }),
773
976
  variant: "simple",
774
- initialSelectedTabIndex: ["pending", "done"].indexOf(activeTab),
977
+ initialSelectedTabIndex: activeTabIndex,
775
978
  onTabChange: handleTabChange,
979
+ ref: tabRef,
776
980
  children: [
777
981
  /* @__PURE__ */ jsxs(Box, { paddingBottom: 8, children: [
778
982
  /* @__PURE__ */ jsxs(Tabs, { children: [
@@ -837,21 +1041,13 @@ const ReleasesPage = () => {
837
1041
  )
838
1042
  ] });
839
1043
  };
840
- const ProtectedReleasesPage = () => /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsx(ReleasesPage, {}) });
841
1044
  const App = () => {
842
- return /* @__PURE__ */ jsxs(Switch, { children: [
843
- /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}`, component: ProtectedReleasesPage }),
844
- /* @__PURE__ */ jsx(
845
- Route,
846
- {
847
- exact: true,
848
- path: `/plugins/${pluginId}/:releaseId`,
849
- component: ProtectedReleaseDetailsPage
850
- }
851
- )
852
- ] });
1045
+ return /* @__PURE__ */ jsx(CheckPagePermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(Switch, { children: [
1046
+ /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}`, component: ReleasesPage }),
1047
+ /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}/:releaseId`, component: ReleaseDetailsPage })
1048
+ ] }) });
853
1049
  };
854
1050
  export {
855
1051
  App
856
1052
  };
857
- //# sourceMappingURL=App-3f94ba77.mjs.map
1053
+ //# sourceMappingURL=App-_Jj3tWts.mjs.map