@strapi/content-releases 5.12.1 → 5.12.2

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 (259) hide show
  1. package/dist/admin/assets/purchase-page-illustration-dark.svg.js +6 -0
  2. package/dist/admin/assets/purchase-page-illustration-dark.svg.js.map +1 -0
  3. package/dist/admin/assets/purchase-page-illustration-dark.svg.mjs +4 -0
  4. package/dist/admin/assets/purchase-page-illustration-dark.svg.mjs.map +1 -0
  5. package/dist/admin/assets/purchase-page-illustration-light.svg.js +6 -0
  6. package/dist/admin/assets/purchase-page-illustration-light.svg.js.map +1 -0
  7. package/dist/admin/assets/purchase-page-illustration-light.svg.mjs +4 -0
  8. package/dist/admin/assets/purchase-page-illustration-light.svg.mjs.map +1 -0
  9. package/dist/admin/components/EntryValidationPopover.js +344 -0
  10. package/dist/admin/components/EntryValidationPopover.js.map +1 -0
  11. package/dist/admin/components/EntryValidationPopover.mjs +342 -0
  12. package/dist/admin/components/EntryValidationPopover.mjs.map +1 -0
  13. package/dist/admin/components/RelativeTime.js +76 -0
  14. package/dist/admin/components/RelativeTime.js.map +1 -0
  15. package/dist/admin/components/RelativeTime.mjs +55 -0
  16. package/dist/admin/components/RelativeTime.mjs.map +1 -0
  17. package/dist/admin/components/ReleaseAction.js +201 -0
  18. package/dist/admin/components/ReleaseAction.js.map +1 -0
  19. package/dist/admin/components/ReleaseAction.mjs +199 -0
  20. package/dist/admin/components/ReleaseAction.mjs.map +1 -0
  21. package/dist/admin/components/ReleaseActionMenu.js +243 -0
  22. package/dist/admin/components/ReleaseActionMenu.js.map +1 -0
  23. package/dist/admin/components/ReleaseActionMenu.mjs +222 -0
  24. package/dist/admin/components/ReleaseActionMenu.mjs.map +1 -0
  25. package/dist/admin/components/ReleaseActionModal.js +268 -0
  26. package/dist/admin/components/ReleaseActionModal.js.map +1 -0
  27. package/dist/admin/components/ReleaseActionModal.mjs +244 -0
  28. package/dist/admin/components/ReleaseActionModal.mjs.map +1 -0
  29. package/dist/admin/components/ReleaseActionOptions.js +104 -0
  30. package/dist/admin/components/ReleaseActionOptions.js.map +1 -0
  31. package/dist/admin/components/ReleaseActionOptions.mjs +102 -0
  32. package/dist/admin/components/ReleaseActionOptions.mjs.map +1 -0
  33. package/dist/admin/components/ReleaseListCell.js +103 -0
  34. package/dist/admin/components/ReleaseListCell.js.map +1 -0
  35. package/dist/admin/components/ReleaseListCell.mjs +100 -0
  36. package/dist/admin/components/ReleaseListCell.mjs.map +1 -0
  37. package/dist/admin/components/ReleaseModal.js +323 -0
  38. package/dist/admin/components/ReleaseModal.js.map +1 -0
  39. package/dist/admin/components/ReleaseModal.mjs +302 -0
  40. package/dist/admin/components/ReleaseModal.mjs.map +1 -0
  41. package/dist/admin/components/ReleasesPanel.js +138 -0
  42. package/dist/admin/components/ReleasesPanel.js.map +1 -0
  43. package/dist/admin/components/ReleasesPanel.mjs +136 -0
  44. package/dist/admin/components/ReleasesPanel.mjs.map +1 -0
  45. package/dist/admin/constants.js +77 -0
  46. package/dist/admin/constants.js.map +1 -0
  47. package/dist/admin/constants.mjs +75 -0
  48. package/dist/admin/constants.mjs.map +1 -0
  49. package/dist/admin/index.js +120 -14
  50. package/dist/admin/index.js.map +1 -1
  51. package/dist/admin/index.mjs +121 -13
  52. package/dist/admin/index.mjs.map +1 -1
  53. package/dist/admin/{chunks/hooks-DA5VbUAp.js → modules/hooks.js} +1 -1
  54. package/dist/admin/modules/hooks.js.map +1 -0
  55. package/dist/admin/{chunks/hooks-CFk_8Q0b.mjs → modules/hooks.mjs} +2 -2
  56. package/dist/admin/modules/hooks.mjs.map +1 -0
  57. package/dist/admin/pages/App.js +29 -0
  58. package/dist/admin/pages/App.js.map +1 -0
  59. package/dist/admin/pages/App.mjs +27 -0
  60. package/dist/admin/pages/App.mjs.map +1 -0
  61. package/dist/admin/pages/PurchaseContentReleases.js +192 -0
  62. package/dist/admin/pages/PurchaseContentReleases.js.map +1 -0
  63. package/dist/admin/pages/PurchaseContentReleases.mjs +190 -0
  64. package/dist/admin/pages/PurchaseContentReleases.mjs.map +1 -0
  65. package/dist/admin/pages/ReleaseDetailsPage.js +821 -0
  66. package/dist/admin/pages/ReleaseDetailsPage.js.map +1 -0
  67. package/dist/admin/pages/ReleaseDetailsPage.mjs +800 -0
  68. package/dist/admin/pages/ReleaseDetailsPage.mjs.map +1 -0
  69. package/dist/admin/pages/ReleasesPage.js +397 -0
  70. package/dist/admin/pages/ReleasesPage.js.map +1 -0
  71. package/dist/admin/pages/ReleasesPage.mjs +375 -0
  72. package/dist/admin/pages/ReleasesPage.mjs.map +1 -0
  73. package/dist/admin/{chunks/ReleasesSettingsPage-KRcoI1bC.js → pages/ReleasesSettingsPage.js} +9 -17
  74. package/dist/admin/pages/ReleasesSettingsPage.js.map +1 -0
  75. package/dist/admin/{chunks/ReleasesSettingsPage-DUKdFdvx.mjs → pages/ReleasesSettingsPage.mjs} +5 -13
  76. package/dist/admin/pages/ReleasesSettingsPage.mjs.map +1 -0
  77. package/dist/admin/pluginId.js +6 -0
  78. package/dist/admin/pluginId.js.map +1 -0
  79. package/dist/admin/pluginId.mjs +4 -0
  80. package/dist/admin/pluginId.mjs.map +1 -0
  81. package/dist/admin/services/release.js +464 -0
  82. package/dist/admin/services/release.js.map +1 -0
  83. package/dist/admin/services/release.mjs +447 -0
  84. package/dist/admin/services/release.mjs.map +1 -0
  85. package/dist/admin/store/hooks.js +8 -0
  86. package/dist/admin/store/hooks.js.map +1 -0
  87. package/dist/admin/store/hooks.mjs +6 -0
  88. package/dist/admin/store/hooks.mjs.map +1 -0
  89. package/dist/admin/{chunks/en-BOpqX2t_.js → translations/en.json.js} +2 -2
  90. package/dist/admin/translations/en.json.js.map +1 -0
  91. package/dist/admin/{chunks/en-aQo8Bn_U.mjs → translations/en.json.mjs} +1 -1
  92. package/dist/admin/translations/en.json.mjs.map +1 -0
  93. package/dist/admin/{chunks/uk-9T9su-bj.js → translations/uk.json.js} +2 -2
  94. package/dist/admin/translations/uk.json.js.map +1 -0
  95. package/dist/admin/{chunks/uk-Bp9HotPq.mjs → translations/uk.json.mjs} +1 -1
  96. package/dist/admin/translations/uk.json.mjs.map +1 -0
  97. package/dist/admin/utils/api.js +8 -0
  98. package/dist/admin/utils/api.js.map +1 -0
  99. package/dist/admin/utils/api.mjs +6 -0
  100. package/dist/admin/utils/api.mjs.map +1 -0
  101. package/dist/admin/utils/prefixPluginTranslations.js +11 -0
  102. package/dist/admin/utils/prefixPluginTranslations.js.map +1 -0
  103. package/dist/admin/utils/prefixPluginTranslations.mjs +9 -0
  104. package/dist/admin/utils/prefixPluginTranslations.mjs.map +1 -0
  105. package/dist/admin/utils/time.js +42 -0
  106. package/dist/admin/utils/time.js.map +1 -0
  107. package/dist/admin/utils/time.mjs +39 -0
  108. package/dist/admin/utils/time.mjs.map +1 -0
  109. package/dist/admin/{chunks/schemas-DS7NeFDN.js → validation/schemas.js} +1 -1
  110. package/dist/admin/validation/schemas.js.map +1 -0
  111. package/dist/admin/{chunks/schemas-DMt8h1z-.mjs → validation/schemas.mjs} +2 -2
  112. package/dist/admin/validation/schemas.mjs.map +1 -0
  113. package/dist/server/bootstrap.js +68 -0
  114. package/dist/server/bootstrap.js.map +1 -0
  115. package/dist/server/bootstrap.mjs +66 -0
  116. package/dist/server/bootstrap.mjs.map +1 -0
  117. package/dist/server/constants.js +74 -0
  118. package/dist/server/constants.js.map +1 -0
  119. package/dist/server/constants.mjs +69 -0
  120. package/dist/server/constants.mjs.map +1 -0
  121. package/dist/server/content-types/index.js +12 -0
  122. package/dist/server/content-types/index.js.map +1 -0
  123. package/dist/server/content-types/index.mjs +10 -0
  124. package/dist/server/content-types/index.mjs.map +1 -0
  125. package/dist/server/content-types/release/index.js +10 -0
  126. package/dist/server/content-types/release/index.js.map +1 -0
  127. package/dist/server/content-types/release/index.mjs +8 -0
  128. package/dist/server/content-types/release/index.mjs.map +1 -0
  129. package/dist/server/content-types/release/schema.js +58 -0
  130. package/dist/server/content-types/release/schema.js.map +1 -0
  131. package/dist/server/content-types/release/schema.mjs +56 -0
  132. package/dist/server/content-types/release/schema.mjs.map +1 -0
  133. package/dist/server/content-types/release-action/index.js +10 -0
  134. package/dist/server/content-types/release-action/index.js.map +1 -0
  135. package/dist/server/content-types/release-action/index.mjs +8 -0
  136. package/dist/server/content-types/release-action/index.mjs.map +1 -0
  137. package/dist/server/content-types/release-action/schema.js +55 -0
  138. package/dist/server/content-types/release-action/schema.js.map +1 -0
  139. package/dist/server/content-types/release-action/schema.mjs +53 -0
  140. package/dist/server/content-types/release-action/schema.mjs.map +1 -0
  141. package/dist/server/controllers/index.js +14 -0
  142. package/dist/server/controllers/index.js.map +1 -0
  143. package/dist/server/controllers/index.mjs +12 -0
  144. package/dist/server/controllers/index.mjs.map +1 -0
  145. package/dist/server/controllers/release-action.js +150 -0
  146. package/dist/server/controllers/release-action.js.map +1 -0
  147. package/dist/server/controllers/release-action.mjs +148 -0
  148. package/dist/server/controllers/release-action.mjs.map +1 -0
  149. package/dist/server/controllers/release.js +302 -0
  150. package/dist/server/controllers/release.js.map +1 -0
  151. package/dist/server/controllers/release.mjs +300 -0
  152. package/dist/server/controllers/release.mjs.map +1 -0
  153. package/dist/server/controllers/settings.js +37 -0
  154. package/dist/server/controllers/settings.js.map +1 -0
  155. package/dist/server/controllers/settings.mjs +35 -0
  156. package/dist/server/controllers/settings.mjs.map +1 -0
  157. package/dist/server/controllers/validation/release-action.js +34 -0
  158. package/dist/server/controllers/validation/release-action.js.map +1 -0
  159. package/dist/server/controllers/validation/release-action.mjs +30 -0
  160. package/dist/server/controllers/validation/release-action.mjs.map +1 -0
  161. package/dist/server/controllers/validation/release.js +26 -0
  162. package/dist/server/controllers/validation/release.js.map +1 -0
  163. package/dist/server/controllers/validation/release.mjs +22 -0
  164. package/dist/server/controllers/validation/release.mjs.map +1 -0
  165. package/dist/server/controllers/validation/settings.js +32 -0
  166. package/dist/server/controllers/validation/settings.js.map +1 -0
  167. package/dist/server/controllers/validation/settings.mjs +10 -0
  168. package/dist/server/controllers/validation/settings.mjs.map +1 -0
  169. package/dist/server/destroy.js +15 -0
  170. package/dist/server/destroy.js.map +1 -0
  171. package/dist/server/destroy.mjs +13 -0
  172. package/dist/server/destroy.mjs.map +1 -0
  173. package/dist/server/index.js +16 -2336
  174. package/dist/server/index.js.map +1 -1
  175. package/dist/server/index.mjs +7 -2308
  176. package/dist/server/index.mjs.map +1 -1
  177. package/dist/server/middlewares/documents.js +104 -0
  178. package/dist/server/middlewares/documents.js.map +1 -0
  179. package/dist/server/middlewares/documents.mjs +101 -0
  180. package/dist/server/middlewares/documents.mjs.map +1 -0
  181. package/dist/server/migrations/database/5.0.0-document-id-in-actions.js +51 -0
  182. package/dist/server/migrations/database/5.0.0-document-id-in-actions.js.map +1 -0
  183. package/dist/server/migrations/database/5.0.0-document-id-in-actions.mjs +49 -0
  184. package/dist/server/migrations/database/5.0.0-document-id-in-actions.mjs.map +1 -0
  185. package/dist/server/migrations/index.js +205 -0
  186. package/dist/server/migrations/index.js.map +1 -0
  187. package/dist/server/migrations/index.mjs +198 -0
  188. package/dist/server/migrations/index.mjs.map +1 -0
  189. package/dist/server/register.js +23 -0
  190. package/dist/server/register.js.map +1 -0
  191. package/dist/server/register.mjs +21 -0
  192. package/dist/server/register.mjs.map +1 -0
  193. package/dist/server/routes/index.js +14 -0
  194. package/dist/server/routes/index.js.map +1 -0
  195. package/dist/server/routes/index.mjs +12 -0
  196. package/dist/server/routes/index.mjs.map +1 -0
  197. package/dist/server/routes/release-action.js +100 -0
  198. package/dist/server/routes/release-action.js.map +1 -0
  199. package/dist/server/routes/release-action.mjs +98 -0
  200. package/dist/server/routes/release-action.mjs.map +1 -0
  201. package/dist/server/routes/release.js +154 -0
  202. package/dist/server/routes/release.js.map +1 -0
  203. package/dist/server/routes/release.mjs +152 -0
  204. package/dist/server/routes/release.mjs.map +1 -0
  205. package/dist/server/routes/settings.js +46 -0
  206. package/dist/server/routes/settings.js.map +1 -0
  207. package/dist/server/routes/settings.mjs +44 -0
  208. package/dist/server/routes/settings.mjs.map +1 -0
  209. package/dist/server/services/index.js +18 -0
  210. package/dist/server/services/index.js.map +1 -0
  211. package/dist/server/services/index.mjs +16 -0
  212. package/dist/server/services/index.mjs.map +1 -0
  213. package/dist/server/services/release-action.js +323 -0
  214. package/dist/server/services/release-action.js.map +1 -0
  215. package/dist/server/services/release-action.mjs +321 -0
  216. package/dist/server/services/release-action.mjs.map +1 -0
  217. package/dist/server/services/release.js +324 -0
  218. package/dist/server/services/release.js.map +1 -0
  219. package/dist/server/services/release.mjs +322 -0
  220. package/dist/server/services/release.mjs.map +1 -0
  221. package/dist/server/services/scheduling.js +70 -0
  222. package/dist/server/services/scheduling.js.map +1 -0
  223. package/dist/server/services/scheduling.mjs +68 -0
  224. package/dist/server/services/scheduling.mjs.map +1 -0
  225. package/dist/server/services/settings.js +34 -0
  226. package/dist/server/services/settings.js.map +1 -0
  227. package/dist/server/services/settings.mjs +32 -0
  228. package/dist/server/services/settings.mjs.map +1 -0
  229. package/dist/server/services/validation.js +91 -0
  230. package/dist/server/services/validation.js.map +1 -0
  231. package/dist/server/services/validation.mjs +86 -0
  232. package/dist/server/services/validation.mjs.map +1 -0
  233. package/dist/server/utils/index.js +93 -0
  234. package/dist/server/utils/index.js.map +1 -0
  235. package/dist/server/utils/index.mjs +87 -0
  236. package/dist/server/utils/index.mjs.map +1 -0
  237. package/package.json +7 -7
  238. package/dist/admin/chunks/App-BkWgp5q_.mjs +0 -1845
  239. package/dist/admin/chunks/App-BkWgp5q_.mjs.map +0 -1
  240. package/dist/admin/chunks/App-CJiqPP7-.js +0 -1866
  241. package/dist/admin/chunks/App-CJiqPP7-.js.map +0 -1
  242. package/dist/admin/chunks/PurchaseContentReleases-CzayeVUD.mjs +0 -193
  243. package/dist/admin/chunks/PurchaseContentReleases-CzayeVUD.mjs.map +0 -1
  244. package/dist/admin/chunks/PurchaseContentReleases-Z9uEPb5b.js +0 -195
  245. package/dist/admin/chunks/PurchaseContentReleases-Z9uEPb5b.js.map +0 -1
  246. package/dist/admin/chunks/ReleasesSettingsPage-DUKdFdvx.mjs.map +0 -1
  247. package/dist/admin/chunks/ReleasesSettingsPage-KRcoI1bC.js.map +0 -1
  248. package/dist/admin/chunks/en-BOpqX2t_.js.map +0 -1
  249. package/dist/admin/chunks/en-aQo8Bn_U.mjs.map +0 -1
  250. package/dist/admin/chunks/hooks-CFk_8Q0b.mjs.map +0 -1
  251. package/dist/admin/chunks/hooks-DA5VbUAp.js.map +0 -1
  252. package/dist/admin/chunks/index-DBUaMD56.mjs +0 -1619
  253. package/dist/admin/chunks/index-DBUaMD56.mjs.map +0 -1
  254. package/dist/admin/chunks/index-vjWrvGN3.js +0 -1658
  255. package/dist/admin/chunks/index-vjWrvGN3.js.map +0 -1
  256. package/dist/admin/chunks/schemas-DMt8h1z-.mjs.map +0 -1
  257. package/dist/admin/chunks/schemas-DS7NeFDN.js.map +0 -1
  258. package/dist/admin/chunks/uk-9T9su-bj.js.map +0 -1
  259. package/dist/admin/chunks/uk-Bp9HotPq.mjs.map +0 -1
@@ -1,1845 +0,0 @@
1
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import { useNotification, useAPIErrorHandler, useQueryParams, useTracking, useRBAC, Page, Layouts, Pagination, isFetchError, ConfirmDialog, BackButton, useStrapiApp, Table } from '@strapi/admin/strapi-admin';
3
- import { Link, useLocation, useNavigate, NavLink, useParams, Navigate, Routes, Route } from 'react-router-dom';
4
- import { g as getTimezones, p as pluginId, u as useGetReleasesQuery, a as useGetReleaseSettingsQuery, b as useCreateReleaseMutation, P as PERMISSIONS, c as useGetReleaseQuery, d as useUpdateReleaseMutation, e as useDeleteReleaseMutation, f as usePublishReleaseMutation, h as getTimezoneOffset, i as useGetReleaseActionsQuery, j as useUpdateReleaseActionMutation, R as ReleaseActionOptions, k as ReleaseActionMenu, r as releaseApi } from './index-DBUaMD56.mjs';
5
- import * as React from 'react';
6
- import { Flex, Popover, Button, Typography, LinkButton, Modal, Field, TextInput, Box, Checkbox, DatePicker, TimePicker, Combobox, ComboboxOption, Link as Link$1, Alert, Main, Tabs, Divider, EmptyStateLayout, Grid, Badge, MenuItem, SimpleMenu, Dialog, SingleSelect, SingleSelectOption, Tr, Td } from '@strapi/design-system';
7
- import { CrossCircle, CaretDown, CheckCircle, ArrowsCounterClockwise, Plus, Pencil, Trash, More } from '@strapi/icons';
8
- import { EmptyDocuments } from '@strapi/icons/symbols';
9
- import format$1 from 'date-fns/format';
10
- import { utcToZonedTime, zonedTimeToUtc } from 'date-fns-tz';
11
- import { useIntl } from 'react-intl';
12
- import { styled } from 'styled-components';
13
- import { unstable_useDocument } from '@strapi/content-manager/strapi-admin';
14
- import { stringify } from 'qs';
15
- import { intervalToDuration, isPast, formatISO, format } from 'date-fns';
16
- import { Formik, Form, useFormikContext } from 'formik';
17
- import { R as RELEASE_SCHEMA } from './schemas-DMt8h1z-.mjs';
18
- import { useDispatch } from 'react-redux';
19
- import { useLicenseLimits } from '@strapi/admin/strapi-admin/ee';
20
- import 'yup';
21
-
22
- const StyledPopoverFlex = styled(Flex)`
23
- width: 100%;
24
- max-width: 256px;
25
-
26
- & > * {
27
- border-bottom: 1px solid ${({ theme })=>theme.colors.neutral150};
28
- }
29
-
30
- & > *:last-child {
31
- border-bottom: none;
32
- }
33
- `;
34
- const EntryStatusTrigger = ({ action, status, hasErrors, requiredStage, entryStage })=>{
35
- const { formatMessage } = useIntl();
36
- if (action === 'publish') {
37
- if (hasErrors || requiredStage && requiredStage.id !== entryStage?.id) {
38
- return /*#__PURE__*/ jsx(Popover.Trigger, {
39
- children: /*#__PURE__*/ jsx(Button, {
40
- variant: "ghost",
41
- startIcon: /*#__PURE__*/ jsx(CrossCircle, {
42
- fill: "danger600"
43
- }),
44
- endIcon: /*#__PURE__*/ jsx(CaretDown, {}),
45
- children: /*#__PURE__*/ jsx(Typography, {
46
- textColor: "danger600",
47
- variant: "omega",
48
- fontWeight: "bold",
49
- children: formatMessage({
50
- id: 'content-releases.pages.ReleaseDetails.entry-validation.not-ready',
51
- defaultMessage: 'Not ready to publish'
52
- })
53
- })
54
- })
55
- });
56
- }
57
- if (status === 'draft') {
58
- return /*#__PURE__*/ jsx(Popover.Trigger, {
59
- children: /*#__PURE__*/ jsx(Button, {
60
- variant: "ghost",
61
- startIcon: /*#__PURE__*/ jsx(CheckCircle, {
62
- fill: "success600"
63
- }),
64
- endIcon: /*#__PURE__*/ jsx(CaretDown, {}),
65
- children: /*#__PURE__*/ jsx(Typography, {
66
- textColor: "success600",
67
- variant: "omega",
68
- fontWeight: "bold",
69
- children: formatMessage({
70
- id: 'content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish',
71
- defaultMessage: 'Ready to publish'
72
- })
73
- })
74
- })
75
- });
76
- }
77
- if (status === 'modified') {
78
- return /*#__PURE__*/ jsx(Popover.Trigger, {
79
- children: /*#__PURE__*/ jsx(Button, {
80
- variant: "ghost",
81
- startIcon: /*#__PURE__*/ jsx(ArrowsCounterClockwise, {
82
- fill: "alternative600"
83
- }),
84
- endIcon: /*#__PURE__*/ jsx(CaretDown, {}),
85
- children: /*#__PURE__*/ jsx(Typography, {
86
- variant: "omega",
87
- fontWeight: "bold",
88
- textColor: "alternative600",
89
- children: formatMessage({
90
- id: 'content-releases.pages.ReleaseDetails.entry-validation.modified',
91
- defaultMessage: 'Ready to publish changes'
92
- })
93
- })
94
- })
95
- });
96
- }
97
- return /*#__PURE__*/ jsx(Popover.Trigger, {
98
- children: /*#__PURE__*/ jsx(Button, {
99
- variant: "ghost",
100
- startIcon: /*#__PURE__*/ jsx(CheckCircle, {
101
- fill: "success600"
102
- }),
103
- endIcon: /*#__PURE__*/ jsx(CaretDown, {}),
104
- children: /*#__PURE__*/ jsx(Typography, {
105
- textColor: "success600",
106
- variant: "omega",
107
- fontWeight: "bold",
108
- children: formatMessage({
109
- id: 'content-releases.pages.ReleaseDetails.entry-validation.already-published',
110
- defaultMessage: 'Already published'
111
- })
112
- })
113
- })
114
- });
115
- }
116
- if (status === 'published') {
117
- return /*#__PURE__*/ jsx(Popover.Trigger, {
118
- children: /*#__PURE__*/ jsx(Button, {
119
- variant: "ghost",
120
- startIcon: /*#__PURE__*/ jsx(CheckCircle, {
121
- fill: "success600"
122
- }),
123
- endIcon: /*#__PURE__*/ jsx(CaretDown, {}),
124
- children: /*#__PURE__*/ jsx(Typography, {
125
- textColor: "success600",
126
- variant: "omega",
127
- fontWeight: "bold",
128
- children: formatMessage({
129
- id: 'content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish',
130
- defaultMessage: 'Ready to unpublish'
131
- })
132
- })
133
- })
134
- });
135
- }
136
- return /*#__PURE__*/ jsx(Popover.Trigger, {
137
- children: /*#__PURE__*/ jsx(Button, {
138
- variant: "ghost",
139
- startIcon: /*#__PURE__*/ jsx(CheckCircle, {
140
- fill: "success600"
141
- }),
142
- endIcon: /*#__PURE__*/ jsx(CaretDown, {}),
143
- children: /*#__PURE__*/ jsx(Typography, {
144
- textColor: "success600",
145
- variant: "omega",
146
- fontWeight: "bold",
147
- children: formatMessage({
148
- id: 'content-releases.pages.ReleaseDetails.entry-validation.already-unpublished',
149
- defaultMessage: 'Already unpublished'
150
- })
151
- })
152
- })
153
- });
154
- };
155
- const FieldsValidation = ({ hasErrors, errors, kind, contentTypeUid, documentId, locale })=>{
156
- const { formatMessage } = useIntl();
157
- return /*#__PURE__*/ jsxs(Flex, {
158
- direction: "column",
159
- gap: 1,
160
- width: "100%",
161
- padding: 5,
162
- children: [
163
- /*#__PURE__*/ jsxs(Flex, {
164
- gap: 2,
165
- width: "100%",
166
- children: [
167
- /*#__PURE__*/ jsx(Typography, {
168
- fontWeight: "bold",
169
- children: formatMessage({
170
- id: 'content-releases.pages.ReleaseDetails.entry-validation.fields',
171
- defaultMessage: 'Fields'
172
- })
173
- }),
174
- hasErrors ? /*#__PURE__*/ jsx(CrossCircle, {
175
- fill: "danger600"
176
- }) : /*#__PURE__*/ jsx(CheckCircle, {
177
- fill: "success600"
178
- })
179
- ]
180
- }),
181
- /*#__PURE__*/ jsx(Typography, {
182
- width: "100%",
183
- textColor: "neutral600",
184
- children: hasErrors ? formatMessage({
185
- id: 'content-releases.pages.ReleaseDetails.entry-validation.fields.error',
186
- defaultMessage: '{errors} errors on fields.'
187
- }, {
188
- errors: errors ? Object.keys(errors).length : 0
189
- }) : formatMessage({
190
- id: 'content-releases.pages.ReleaseDetails.entry-validation.fields.success',
191
- defaultMessage: 'All fields are filled correctly.'
192
- })
193
- }),
194
- hasErrors && /*#__PURE__*/ jsx(LinkButton, {
195
- tag: Link,
196
- to: {
197
- pathname: `/content-manager/${kind === 'collectionType' ? 'collection-types' : 'single-types'}/${contentTypeUid}/${documentId}`,
198
- search: locale ? stringify({
199
- plugins: {
200
- i18n: {
201
- locale
202
- }
203
- }
204
- }) : ''
205
- },
206
- variant: "secondary",
207
- fullWidth: true,
208
- state: {
209
- forceValidation: true
210
- },
211
- children: formatMessage({
212
- id: 'content-releases.pages.ReleaseDetails.entry-validation.fields.see-errors',
213
- defaultMessage: 'See errors'
214
- })
215
- })
216
- ]
217
- });
218
- };
219
- const getReviewStageIcon = ({ contentTypeHasReviewWorkflow, requiredStage, entryStage })=>{
220
- if (!contentTypeHasReviewWorkflow) {
221
- return /*#__PURE__*/ jsx(CheckCircle, {
222
- fill: "neutral200"
223
- });
224
- }
225
- if (requiredStage && requiredStage.id !== entryStage?.id) {
226
- return /*#__PURE__*/ jsx(CrossCircle, {
227
- fill: "danger600"
228
- });
229
- }
230
- return /*#__PURE__*/ jsx(CheckCircle, {
231
- fill: "success600"
232
- });
233
- };
234
- const getReviewStageMessage = ({ contentTypeHasReviewWorkflow, requiredStage, entryStage, formatMessage })=>{
235
- if (!contentTypeHasReviewWorkflow) {
236
- return formatMessage({
237
- id: 'content-releases.pages.ReleaseDetails.entry-validation.review-stage.not-enabled',
238
- defaultMessage: 'This entry is not associated to any workflow.'
239
- });
240
- }
241
- if (requiredStage && requiredStage.id !== entryStage?.id) {
242
- return formatMessage({
243
- id: 'content-releases.pages.ReleaseDetails.entry-validation.review-stage.not-ready',
244
- defaultMessage: 'This entry is not at the required stage for publishing. ({stageName})'
245
- }, {
246
- stageName: requiredStage?.name ?? ''
247
- });
248
- }
249
- if (requiredStage && requiredStage.id === entryStage?.id) {
250
- return formatMessage({
251
- id: 'content-releases.pages.ReleaseDetails.entry-validation.review-stage.ready',
252
- defaultMessage: 'This entry is at the required stage for publishing. ({stageName})'
253
- }, {
254
- stageName: requiredStage?.name ?? ''
255
- });
256
- }
257
- return formatMessage({
258
- id: 'content-releases.pages.ReleaseDetails.entry-validation.review-stage.stage-not-required',
259
- defaultMessage: 'No required stage for publication'
260
- });
261
- };
262
- const ReviewStageValidation = ({ contentTypeHasReviewWorkflow, requiredStage, entryStage })=>{
263
- const { formatMessage } = useIntl();
264
- const Icon = getReviewStageIcon({
265
- contentTypeHasReviewWorkflow,
266
- requiredStage,
267
- entryStage
268
- });
269
- return /*#__PURE__*/ jsxs(Flex, {
270
- direction: "column",
271
- gap: 1,
272
- width: "100%",
273
- padding: 5,
274
- children: [
275
- /*#__PURE__*/ jsxs(Flex, {
276
- gap: 2,
277
- width: "100%",
278
- children: [
279
- /*#__PURE__*/ jsx(Typography, {
280
- fontWeight: "bold",
281
- children: formatMessage({
282
- id: 'content-releases.pages.ReleaseDetails.entry-validation.review-stage',
283
- defaultMessage: 'Review stage'
284
- })
285
- }),
286
- Icon
287
- ]
288
- }),
289
- /*#__PURE__*/ jsx(Typography, {
290
- textColor: "neutral600",
291
- children: getReviewStageMessage({
292
- contentTypeHasReviewWorkflow,
293
- requiredStage,
294
- entryStage,
295
- formatMessage
296
- })
297
- })
298
- ]
299
- });
300
- };
301
- const EntryValidationPopover = ({ schema, entry, status, action })=>{
302
- const { validate, isLoading } = unstable_useDocument({
303
- collectionType: schema?.kind ?? '',
304
- model: schema?.uid ?? ''
305
- }, {
306
- // useDocument makes a request to get more data about the entry, but we only want to have the validation function so we skip the request
307
- skip: true
308
- });
309
- // Validation errors
310
- const errors = isLoading ? null : validate(entry);
311
- const hasErrors = errors ? Object.keys(errors).length > 0 : false;
312
- // Entry stage
313
- const contentTypeHasReviewWorkflow = schema?.hasReviewWorkflow ?? false;
314
- const requiredStage = schema?.stageRequiredToPublish;
315
- const entryStage = entry.strapi_stage;
316
- if (isLoading) {
317
- return null;
318
- }
319
- return /*#__PURE__*/ jsxs(Popover.Root, {
320
- children: [
321
- /*#__PURE__*/ jsx(EntryStatusTrigger, {
322
- action: action,
323
- status: status,
324
- hasErrors: hasErrors,
325
- requiredStage: requiredStage,
326
- entryStage: entryStage
327
- }),
328
- /*#__PURE__*/ jsx(Popover.Content, {
329
- children: /*#__PURE__*/ jsxs(StyledPopoverFlex, {
330
- direction: "column",
331
- children: [
332
- /*#__PURE__*/ jsx(FieldsValidation, {
333
- hasErrors: hasErrors,
334
- errors: errors,
335
- contentTypeUid: schema?.uid,
336
- kind: schema?.kind,
337
- documentId: entry.documentId,
338
- locale: entry.locale
339
- }),
340
- /*#__PURE__*/ jsx(ReviewStageValidation, {
341
- contentTypeHasReviewWorkflow: contentTypeHasReviewWorkflow,
342
- requiredStage: requiredStage,
343
- entryStage: entryStage
344
- })
345
- ]
346
- })
347
- })
348
- ]
349
- });
350
- };
351
-
352
- const intervals = [
353
- 'years',
354
- 'months',
355
- 'days',
356
- 'hours',
357
- 'minutes',
358
- 'seconds'
359
- ];
360
- /**
361
- * Displays the relative time between a given timestamp and the current time.
362
- * You can display a custom message for given time intervals by passing an array of custom intervals.
363
- *
364
- * @example
365
- * ```jsx
366
- * <caption>Display "last hour" if the timestamp is less than an hour ago</caption>
367
- * <RelativeTime
368
- * timestamp={new Date('2021-01-01')}
369
- * customIntervals={[
370
- * { unit: 'hours', threshold: 1, text: 'last hour' },
371
- * ]}
372
- * ```
373
- */ const RelativeTime$1 = /*#__PURE__*/ React.forwardRef(({ timestamp, customIntervals = [], ...restProps }, forwardedRef)=>{
374
- const { formatRelativeTime, formatDate, formatTime } = useIntl();
375
- /**
376
- * TODO: make this auto-update, like a clock.
377
- */ const interval = intervalToDuration({
378
- start: timestamp,
379
- end: Date.now()
380
- });
381
- const unit = intervals.find((intervalUnit)=>{
382
- return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
383
- });
384
- const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
385
- // Display custom text if interval is less than the threshold
386
- const customInterval = customIntervals.find((custom)=>interval[custom.unit] < custom.threshold);
387
- const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, {
388
- numeric: 'auto'
389
- });
390
- return /*#__PURE__*/ jsx("time", {
391
- ref: forwardedRef,
392
- dateTime: timestamp.toISOString(),
393
- role: "time",
394
- title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
395
- ...restProps,
396
- children: displayText
397
- });
398
- });
399
-
400
- const ReleaseModal = ({ handleClose, open, handleSubmit, initialValues, isLoading = false })=>{
401
- const { formatMessage } = useIntl();
402
- const { pathname } = useLocation();
403
- const isCreatingRelease = pathname === `/plugins/${pluginId}`;
404
- // Set default first timezone from the list if no system timezone detected
405
- const { timezoneList, systemTimezone = {
406
- value: 'UTC+00:00-Africa/Abidjan '
407
- } } = getTimezones(initialValues.scheduledAt ? new Date(initialValues.scheduledAt) : new Date());
408
- /**
409
- * Generate scheduled time using selected date, time and timezone
410
- */ const getScheduledTimestamp = (values)=>{
411
- const { date, time, timezone } = values;
412
- if (!date || !time || !timezone) return null;
413
- const timezoneWithoutOffset = timezone.split('&')[1];
414
- return zonedTimeToUtc(`${date} ${time}`, timezoneWithoutOffset);
415
- };
416
- /**
417
- * Get timezone with offset to show the selected value in the dropdown
418
- */ const getTimezoneWithOffset = ()=>{
419
- const currentTimezone = timezoneList.find((timezone)=>timezone.value.split('&')[1] === initialValues.timezone);
420
- return currentTimezone?.value || systemTimezone.value;
421
- };
422
- return /*#__PURE__*/ jsx(Modal.Root, {
423
- open: open,
424
- onOpenChange: handleClose,
425
- children: /*#__PURE__*/ jsxs(Modal.Content, {
426
- children: [
427
- /*#__PURE__*/ jsx(Modal.Header, {
428
- children: /*#__PURE__*/ jsx(Modal.Title, {
429
- children: formatMessage({
430
- id: 'content-releases.modal.title',
431
- defaultMessage: '{isCreatingRelease, select, true {New release} other {Edit release}}'
432
- }, {
433
- isCreatingRelease: isCreatingRelease
434
- })
435
- })
436
- }),
437
- /*#__PURE__*/ jsx(Formik, {
438
- onSubmit: (values)=>{
439
- handleSubmit({
440
- ...values,
441
- timezone: values.timezone ? values.timezone.split('&')[1] : null,
442
- scheduledAt: values.isScheduled ? getScheduledTimestamp(values) : null
443
- });
444
- },
445
- initialValues: {
446
- ...initialValues,
447
- timezone: initialValues.timezone ? getTimezoneWithOffset() : systemTimezone.value
448
- },
449
- validationSchema: RELEASE_SCHEMA,
450
- validateOnChange: false,
451
- children: ({ values, errors, handleChange, setFieldValue })=>{
452
- return /*#__PURE__*/ jsxs(Form, {
453
- children: [
454
- /*#__PURE__*/ jsx(Modal.Body, {
455
- children: /*#__PURE__*/ jsxs(Flex, {
456
- direction: "column",
457
- alignItems: "stretch",
458
- gap: 6,
459
- children: [
460
- /*#__PURE__*/ jsxs(Field.Root, {
461
- name: "name",
462
- error: errors.name && formatMessage({
463
- id: errors.name,
464
- defaultMessage: errors.name
465
- }),
466
- required: true,
467
- children: [
468
- /*#__PURE__*/ jsx(Field.Label, {
469
- children: formatMessage({
470
- id: 'content-releases.modal.form.input.label.release-name',
471
- defaultMessage: 'Name'
472
- })
473
- }),
474
- /*#__PURE__*/ jsx(TextInput, {
475
- value: values.name,
476
- onChange: handleChange
477
- }),
478
- /*#__PURE__*/ jsx(Field.Error, {})
479
- ]
480
- }),
481
- /*#__PURE__*/ jsx(Box, {
482
- width: "max-content",
483
- children: /*#__PURE__*/ jsx(Checkbox, {
484
- name: "isScheduled",
485
- checked: values.isScheduled,
486
- onCheckedChange: (checked)=>{
487
- setFieldValue('isScheduled', checked);
488
- if (!checked) {
489
- // Clear scheduling info from a release on unchecking schedule release, which reset scheduling info in DB
490
- setFieldValue('date', null);
491
- setFieldValue('time', '');
492
- setFieldValue('timezone', null);
493
- } else {
494
- // On ticking back schedule release date, time and timezone should be restored to the initial state
495
- setFieldValue('date', initialValues.date);
496
- setFieldValue('time', initialValues.time);
497
- setFieldValue('timezone', initialValues.timezone ?? systemTimezone?.value);
498
- }
499
- },
500
- children: /*#__PURE__*/ jsx(Typography, {
501
- textColor: values.isScheduled ? 'primary600' : 'neutral800',
502
- fontWeight: values.isScheduled ? 'semiBold' : 'regular',
503
- children: formatMessage({
504
- id: 'modal.form.input.label.schedule-release',
505
- defaultMessage: 'Schedule release'
506
- })
507
- })
508
- })
509
- }),
510
- values.isScheduled && /*#__PURE__*/ jsxs(Fragment, {
511
- children: [
512
- /*#__PURE__*/ jsxs(Flex, {
513
- gap: 4,
514
- alignItems: "start",
515
- children: [
516
- /*#__PURE__*/ jsx(Box, {
517
- width: "100%",
518
- children: /*#__PURE__*/ jsxs(Field.Root, {
519
- name: "date",
520
- error: errors.date && formatMessage({
521
- id: errors.date,
522
- defaultMessage: errors.date
523
- }),
524
- required: true,
525
- children: [
526
- /*#__PURE__*/ jsx(Field.Label, {
527
- children: formatMessage({
528
- id: 'content-releases.modal.form.input.label.date',
529
- defaultMessage: 'Date'
530
- })
531
- }),
532
- /*#__PURE__*/ jsx(DatePicker, {
533
- onChange: (date)=>{
534
- const isoFormatDate = date ? formatISO(date, {
535
- representation: 'date'
536
- }) : null;
537
- setFieldValue('date', isoFormatDate);
538
- },
539
- clearLabel: formatMessage({
540
- id: 'content-releases.modal.form.input.clearLabel',
541
- defaultMessage: 'Clear'
542
- }),
543
- onClear: ()=>{
544
- setFieldValue('date', null);
545
- },
546
- value: values.date ? new Date(values.date) : new Date(),
547
- minDate: utcToZonedTime(new Date(), values.timezone.split('&')[1])
548
- }),
549
- /*#__PURE__*/ jsx(Field.Error, {})
550
- ]
551
- })
552
- }),
553
- /*#__PURE__*/ jsx(Box, {
554
- width: "100%",
555
- children: /*#__PURE__*/ jsxs(Field.Root, {
556
- name: "time",
557
- error: errors.time && formatMessage({
558
- id: errors.time,
559
- defaultMessage: errors.time
560
- }),
561
- required: true,
562
- children: [
563
- /*#__PURE__*/ jsx(Field.Label, {
564
- children: formatMessage({
565
- id: 'content-releases.modal.form.input.label.time',
566
- defaultMessage: 'Time'
567
- })
568
- }),
569
- /*#__PURE__*/ jsx(TimePicker, {
570
- onChange: (time)=>{
571
- setFieldValue('time', time);
572
- },
573
- clearLabel: formatMessage({
574
- id: 'content-releases.modal.form.input.clearLabel',
575
- defaultMessage: 'Clear'
576
- }),
577
- onClear: ()=>{
578
- setFieldValue('time', '');
579
- },
580
- value: values.time || undefined
581
- }),
582
- /*#__PURE__*/ jsx(Field.Error, {})
583
- ]
584
- })
585
- })
586
- ]
587
- }),
588
- /*#__PURE__*/ jsx(TimezoneComponent, {
589
- timezoneOptions: timezoneList
590
- })
591
- ]
592
- })
593
- ]
594
- })
595
- }),
596
- /*#__PURE__*/ jsxs(Modal.Footer, {
597
- children: [
598
- /*#__PURE__*/ jsx(Modal.Close, {
599
- children: /*#__PURE__*/ jsx(Button, {
600
- variant: "tertiary",
601
- name: "cancel",
602
- children: formatMessage({
603
- id: 'cancel',
604
- defaultMessage: 'Cancel'
605
- })
606
- })
607
- }),
608
- /*#__PURE__*/ jsx(Button, {
609
- name: "submit",
610
- loading: isLoading,
611
- type: "submit",
612
- children: formatMessage({
613
- id: 'content-releases.modal.form.button.submit',
614
- defaultMessage: '{isCreatingRelease, select, true {Continue} other {Save}}'
615
- }, {
616
- isCreatingRelease: isCreatingRelease
617
- })
618
- })
619
- ]
620
- })
621
- ]
622
- });
623
- }
624
- })
625
- ]
626
- })
627
- });
628
- };
629
- const TimezoneComponent = ({ timezoneOptions })=>{
630
- const { values, errors, setFieldValue } = useFormikContext();
631
- const { formatMessage } = useIntl();
632
- const [timezoneList, setTimezoneList] = React.useState(timezoneOptions);
633
- React.useEffect(()=>{
634
- if (values.date) {
635
- // Update the timezone offset which varies with DST based on the date selected
636
- const { timezoneList } = getTimezones(new Date(values.date));
637
- setTimezoneList(timezoneList);
638
- const updatedTimezone = values.timezone && timezoneList.find((tz)=>tz.value.split('&')[1] === values.timezone.split('&')[1]);
639
- if (updatedTimezone) {
640
- setFieldValue('timezone', updatedTimezone.value);
641
- }
642
- }
643
- }, [
644
- setFieldValue,
645
- values.date,
646
- values.timezone
647
- ]);
648
- return /*#__PURE__*/ jsxs(Field.Root, {
649
- name: "timezone",
650
- error: errors.timezone && formatMessage({
651
- id: errors.timezone,
652
- defaultMessage: errors.timezone
653
- }),
654
- required: true,
655
- children: [
656
- /*#__PURE__*/ jsx(Field.Label, {
657
- children: formatMessage({
658
- id: 'content-releases.modal.form.input.label.timezone',
659
- defaultMessage: 'Timezone'
660
- })
661
- }),
662
- /*#__PURE__*/ jsx(Combobox, {
663
- autocomplete: {
664
- type: 'list',
665
- filter: 'contains'
666
- },
667
- value: values.timezone || undefined,
668
- textValue: values.timezone ? values.timezone.replace(/&/, ' ') : undefined,
669
- onChange: (timezone)=>{
670
- setFieldValue('timezone', timezone);
671
- },
672
- onTextValueChange: (timezone)=>{
673
- setFieldValue('timezone', timezone);
674
- },
675
- onClear: ()=>{
676
- setFieldValue('timezone', '');
677
- },
678
- children: timezoneList.map((timezone)=>/*#__PURE__*/ jsx(ComboboxOption, {
679
- value: timezone.value,
680
- children: timezone.value.replace(/&/, ' ')
681
- }, timezone.value))
682
- }),
683
- /*#__PURE__*/ jsx(Field.Error, {})
684
- ]
685
- });
686
- };
687
-
688
- const useTypedDispatch = useDispatch;
689
-
690
- const isBaseQueryError = (error)=>{
691
- return typeof error !== 'undefined' && error.name !== undefined;
692
- };
693
-
694
- const LinkCard = styled(Link$1)`
695
- display: block;
696
- `;
697
- const RelativeTime = styled(RelativeTime$1)`
698
- display: inline-block;
699
- &::first-letter {
700
- text-transform: uppercase;
701
- }
702
- `;
703
- const getBadgeProps = (status)=>{
704
- let color;
705
- switch(status){
706
- case 'ready':
707
- color = 'success';
708
- break;
709
- case 'blocked':
710
- color = 'warning';
711
- break;
712
- case 'failed':
713
- color = 'danger';
714
- break;
715
- case 'done':
716
- color = 'primary';
717
- break;
718
- case 'empty':
719
- default:
720
- color = 'neutral';
721
- }
722
- return {
723
- textColor: `${color}600`,
724
- backgroundColor: `${color}100`,
725
- borderColor: `${color}200`
726
- };
727
- };
728
- const ReleasesGrid = ({ sectionTitle, releases = [], isError = false })=>{
729
- const { formatMessage } = useIntl();
730
- if (isError) {
731
- return /*#__PURE__*/ jsx(Page.Error, {});
732
- }
733
- if (releases?.length === 0) {
734
- return /*#__PURE__*/ jsx(EmptyStateLayout, {
735
- content: formatMessage({
736
- id: 'content-releases.page.Releases.tab.emptyEntries',
737
- defaultMessage: 'No releases'
738
- }, {
739
- target: sectionTitle
740
- }),
741
- icon: /*#__PURE__*/ jsx(EmptyDocuments, {
742
- width: "16rem"
743
- })
744
- });
745
- }
746
- return /*#__PURE__*/ jsx(Grid.Root, {
747
- gap: 4,
748
- children: releases.map(({ id, name, scheduledAt, status })=>/*#__PURE__*/ jsx(Grid.Item, {
749
- col: 3,
750
- s: 6,
751
- xs: 12,
752
- direction: "column",
753
- alignItems: "stretch",
754
- children: /*#__PURE__*/ jsx(LinkCard, {
755
- tag: NavLink,
756
- to: `${id}`,
757
- isExternal: false,
758
- children: /*#__PURE__*/ jsxs(Flex, {
759
- direction: "column",
760
- justifyContent: "space-between",
761
- padding: 4,
762
- hasRadius: true,
763
- background: "neutral0",
764
- shadow: "tableShadow",
765
- height: "100%",
766
- width: "100%",
767
- alignItems: "start",
768
- gap: 4,
769
- children: [
770
- /*#__PURE__*/ jsxs(Flex, {
771
- direction: "column",
772
- alignItems: "start",
773
- gap: 1,
774
- children: [
775
- /*#__PURE__*/ jsx(Typography, {
776
- textColor: "neutral800",
777
- tag: "h3",
778
- variant: "delta",
779
- fontWeight: "bold",
780
- children: name
781
- }),
782
- /*#__PURE__*/ jsx(Typography, {
783
- variant: "pi",
784
- textColor: "neutral600",
785
- children: scheduledAt ? /*#__PURE__*/ jsx(RelativeTime, {
786
- timestamp: new Date(scheduledAt)
787
- }) : formatMessage({
788
- id: 'content-releases.pages.Releases.not-scheduled',
789
- defaultMessage: 'Not scheduled'
790
- })
791
- })
792
- ]
793
- }),
794
- /*#__PURE__*/ jsx(Badge, {
795
- ...getBadgeProps(status),
796
- children: status
797
- })
798
- ]
799
- })
800
- })
801
- }, id))
802
- });
803
- };
804
- /* -------------------------------------------------------------------------------------------------
805
- * ReleasesPage
806
- * -----------------------------------------------------------------------------------------------*/ const StyledAlert = styled(Alert)`
807
- button {
808
- display: none;
809
- }
810
- p + div {
811
- margin-left: auto;
812
- }
813
- `;
814
- const INITIAL_FORM_VALUES = {
815
- name: '',
816
- date: format(new Date(), 'yyyy-MM-dd'),
817
- time: '',
818
- isScheduled: true,
819
- scheduledAt: null,
820
- timezone: null
821
- };
822
- const ReleasesPage = ()=>{
823
- const location = useLocation();
824
- const [releaseModalShown, setReleaseModalShown] = React.useState(false);
825
- const { toggleNotification } = useNotification();
826
- const { formatMessage } = useIntl();
827
- const navigate = useNavigate();
828
- const { formatAPIError } = useAPIErrorHandler();
829
- const [{ query }, setQuery] = useQueryParams();
830
- const response = useGetReleasesQuery(query);
831
- const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();
832
- const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();
833
- const { getFeature } = useLicenseLimits();
834
- const { maximumReleases = 3 } = getFeature('cms-content-releases');
835
- const { trackUsage } = useTracking();
836
- const { allowedActions: { canCreate } } = useRBAC(PERMISSIONS);
837
- const { isLoading: isLoadingReleases, isSuccess, isError } = response;
838
- const activeTab = response?.currentData?.meta?.activeTab || 'pending';
839
- // Check if we have some errors and show a notification to the user to explain the error
840
- React.useEffect(()=>{
841
- if (location?.state?.errors) {
842
- toggleNotification({
843
- type: 'danger',
844
- title: formatMessage({
845
- id: 'content-releases.pages.Releases.notification.error.title',
846
- defaultMessage: 'Your request could not be processed.'
847
- }),
848
- message: formatMessage({
849
- id: 'content-releases.pages.Releases.notification.error.message',
850
- defaultMessage: 'Please try again or open another release.'
851
- })
852
- });
853
- navigate('', {
854
- replace: true,
855
- state: null
856
- });
857
- }
858
- }, [
859
- formatMessage,
860
- location?.state?.errors,
861
- navigate,
862
- toggleNotification
863
- ]);
864
- const toggleAddReleaseModal = ()=>{
865
- setReleaseModalShown((prev)=>!prev);
866
- };
867
- if (isLoadingReleases || isLoadingSettings) {
868
- return /*#__PURE__*/ jsx(Page.Loading, {});
869
- }
870
- const totalPendingReleases = isSuccess && response.currentData?.meta?.pendingReleasesCount || 0;
871
- const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
872
- const handleTabChange = (tabValue)=>{
873
- setQuery({
874
- ...query,
875
- page: 1,
876
- pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
877
- filters: {
878
- releasedAt: {
879
- $notNull: tabValue !== 'pending'
880
- }
881
- }
882
- });
883
- };
884
- const handleAddRelease = async ({ name, scheduledAt, timezone })=>{
885
- const response = await createRelease({
886
- name,
887
- scheduledAt,
888
- timezone
889
- });
890
- if ('data' in response) {
891
- // When the response returns an object with 'data', handle success
892
- toggleNotification({
893
- type: 'success',
894
- message: formatMessage({
895
- id: 'content-releases.modal.release-created-notification-success',
896
- defaultMessage: 'Release created.'
897
- })
898
- });
899
- trackUsage('didCreateRelease');
900
- navigate(response.data.data.id.toString());
901
- } else if (isFetchError(response.error)) {
902
- // When the response returns an object with 'error', handle fetch error
903
- toggleNotification({
904
- type: 'danger',
905
- message: formatAPIError(response.error)
906
- });
907
- } else {
908
- // Otherwise, the response returns an object with 'error', handle a generic error
909
- toggleNotification({
910
- type: 'danger',
911
- message: formatMessage({
912
- id: 'notification.error',
913
- defaultMessage: 'An error occurred'
914
- })
915
- });
916
- }
917
- };
918
- return /*#__PURE__*/ jsxs(Main, {
919
- "aria-busy": isLoadingReleases || isLoadingSettings,
920
- children: [
921
- /*#__PURE__*/ jsx(Layouts.Header, {
922
- title: formatMessage({
923
- id: 'content-releases.pages.Releases.title',
924
- defaultMessage: 'Releases'
925
- }),
926
- subtitle: formatMessage({
927
- id: 'content-releases.pages.Releases.header-subtitle',
928
- defaultMessage: 'Create and manage content updates'
929
- }),
930
- primaryAction: canCreate ? /*#__PURE__*/ jsx(Button, {
931
- startIcon: /*#__PURE__*/ jsx(Plus, {}),
932
- onClick: toggleAddReleaseModal,
933
- disabled: hasReachedMaximumPendingReleases,
934
- children: formatMessage({
935
- id: 'content-releases.header.actions.add-release',
936
- defaultMessage: 'New release'
937
- })
938
- }) : null
939
- }),
940
- /*#__PURE__*/ jsx(Layouts.Content, {
941
- children: /*#__PURE__*/ jsxs(Fragment, {
942
- children: [
943
- hasReachedMaximumPendingReleases && /*#__PURE__*/ jsx(StyledAlert, {
944
- marginBottom: 6,
945
- action: /*#__PURE__*/ jsx(Link$1, {
946
- href: "https://strapi.io/pricing-cloud",
947
- isExternal: true,
948
- children: formatMessage({
949
- id: 'content-releases.pages.Releases.max-limit-reached.action',
950
- defaultMessage: 'Explore plans'
951
- })
952
- }),
953
- title: formatMessage({
954
- id: 'content-releases.pages.Releases.max-limit-reached.title',
955
- defaultMessage: 'You have reached the {number} pending {number, plural, one {release} other {releases}} limit.'
956
- }, {
957
- number: maximumReleases
958
- }),
959
- onClose: ()=>{},
960
- closeLabel: "",
961
- children: formatMessage({
962
- id: 'content-releases.pages.Releases.max-limit-reached.message',
963
- defaultMessage: 'Upgrade to manage an unlimited number of releases.'
964
- })
965
- }),
966
- /*#__PURE__*/ jsxs(Tabs.Root, {
967
- variant: "simple",
968
- onValueChange: handleTabChange,
969
- value: activeTab,
970
- children: [
971
- /*#__PURE__*/ jsxs(Box, {
972
- paddingBottom: 8,
973
- children: [
974
- /*#__PURE__*/ jsxs(Tabs.List, {
975
- "aria-label": formatMessage({
976
- id: 'content-releases.pages.Releases.tab-group.label',
977
- defaultMessage: 'Releases list'
978
- }),
979
- children: [
980
- /*#__PURE__*/ jsx(Tabs.Trigger, {
981
- value: "pending",
982
- children: formatMessage({
983
- id: 'content-releases.pages.Releases.tab.pending',
984
- defaultMessage: 'Pending ({count})'
985
- }, {
986
- count: totalPendingReleases
987
- })
988
- }),
989
- /*#__PURE__*/ jsx(Tabs.Trigger, {
990
- value: "done",
991
- children: formatMessage({
992
- id: 'content-releases.pages.Releases.tab.done',
993
- defaultMessage: 'Done'
994
- })
995
- })
996
- ]
997
- }),
998
- /*#__PURE__*/ jsx(Divider, {})
999
- ]
1000
- }),
1001
- /*#__PURE__*/ jsx(Tabs.Content, {
1002
- value: "pending",
1003
- children: /*#__PURE__*/ jsx(ReleasesGrid, {
1004
- sectionTitle: "pending",
1005
- releases: response?.currentData?.data,
1006
- isError: isError
1007
- })
1008
- }),
1009
- /*#__PURE__*/ jsx(Tabs.Content, {
1010
- value: "done",
1011
- children: /*#__PURE__*/ jsx(ReleasesGrid, {
1012
- sectionTitle: "done",
1013
- releases: response?.currentData?.data,
1014
- isError: isError
1015
- })
1016
- })
1017
- ]
1018
- }),
1019
- /*#__PURE__*/ jsxs(Pagination.Root, {
1020
- ...response?.currentData?.meta?.pagination,
1021
- defaultPageSize: response?.currentData?.meta?.pagination?.pageSize,
1022
- children: [
1023
- /*#__PURE__*/ jsx(Pagination.PageSize, {
1024
- options: [
1025
- '8',
1026
- '16',
1027
- '32',
1028
- '64'
1029
- ]
1030
- }),
1031
- /*#__PURE__*/ jsx(Pagination.Links, {})
1032
- ]
1033
- })
1034
- ]
1035
- })
1036
- }),
1037
- /*#__PURE__*/ jsx(ReleaseModal, {
1038
- open: releaseModalShown,
1039
- handleClose: toggleAddReleaseModal,
1040
- handleSubmit: handleAddRelease,
1041
- isLoading: isSubmittingForm,
1042
- initialValues: {
1043
- ...INITIAL_FORM_VALUES,
1044
- timezone: data?.data.defaultTimezone ? data.data.defaultTimezone.split('&')[1] : null
1045
- }
1046
- })
1047
- ]
1048
- });
1049
- };
1050
-
1051
- /* -------------------------------------------------------------------------------------------------
1052
- * ReleaseDetailsLayout
1053
- * -----------------------------------------------------------------------------------------------*/ const ReleaseInfoWrapper = styled(Flex)`
1054
- align-self: stretch;
1055
- border-bottom-right-radius: ${({ theme })=>theme.borderRadius};
1056
- border-bottom-left-radius: ${({ theme })=>theme.borderRadius};
1057
- border-top: 1px solid ${({ theme })=>theme.colors.neutral150};
1058
- `;
1059
- const StyledMenuItem = styled(MenuItem)`
1060
- svg path {
1061
- fill: ${({ theme, disabled })=>disabled && theme.colors.neutral500};
1062
- }
1063
- span {
1064
- color: ${({ theme, disabled })=>disabled && theme.colors.neutral500};
1065
- }
1066
-
1067
- &:hover {
1068
- background: ${({ theme, $variant = 'neutral' })=>theme.colors[`${$variant}100`]};
1069
- }
1070
- `;
1071
- const PencilIcon = styled(Pencil)`
1072
- width: ${({ theme })=>theme.spaces[4]};
1073
- height: ${({ theme })=>theme.spaces[4]};
1074
- path {
1075
- fill: ${({ theme })=>theme.colors.neutral600};
1076
- }
1077
- `;
1078
- const TrashIcon = styled(Trash)`
1079
- width: ${({ theme })=>theme.spaces[4]};
1080
- height: ${({ theme })=>theme.spaces[4]};
1081
- path {
1082
- fill: ${({ theme })=>theme.colors.danger600};
1083
- }
1084
- `;
1085
- const ReleaseDetailsLayout = ({ toggleEditReleaseModal, toggleWarningSubmit, children })=>{
1086
- const { formatMessage, formatDate, formatTime } = useIntl();
1087
- const { releaseId } = useParams();
1088
- const { data, isLoading: isLoadingDetails, error } = useGetReleaseQuery({
1089
- id: releaseId
1090
- }, {
1091
- skip: !releaseId
1092
- });
1093
- const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();
1094
- const { toggleNotification } = useNotification();
1095
- const { formatAPIError } = useAPIErrorHandler();
1096
- const { allowedActions } = useRBAC(PERMISSIONS);
1097
- const { canUpdate, canDelete, canPublish } = allowedActions;
1098
- const dispatch = useTypedDispatch();
1099
- const { trackUsage } = useTracking();
1100
- const release = data?.data;
1101
- const handlePublishRelease = (id)=>async ()=>{
1102
- const response = await publishRelease({
1103
- id
1104
- });
1105
- if ('data' in response) {
1106
- // When the response returns an object with 'data', handle success
1107
- toggleNotification({
1108
- type: 'success',
1109
- message: formatMessage({
1110
- id: 'content-releases.pages.ReleaseDetails.publish-notification-success',
1111
- defaultMessage: 'Release was published successfully.'
1112
- })
1113
- });
1114
- const { totalEntries, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
1115
- trackUsage('didPublishRelease', {
1116
- totalEntries,
1117
- totalPublishedEntries,
1118
- totalUnpublishedEntries
1119
- });
1120
- } else if (isFetchError(response.error)) {
1121
- // When the response returns an object with 'error', handle fetch error
1122
- toggleNotification({
1123
- type: 'danger',
1124
- message: formatAPIError(response.error)
1125
- });
1126
- } else {
1127
- // Otherwise, the response returns an object with 'error', handle a generic error
1128
- toggleNotification({
1129
- type: 'danger',
1130
- message: formatMessage({
1131
- id: 'notification.error',
1132
- defaultMessage: 'An error occurred'
1133
- })
1134
- });
1135
- }
1136
- };
1137
- const handleRefresh = ()=>{
1138
- dispatch(releaseApi.util.invalidateTags([
1139
- {
1140
- type: 'ReleaseAction',
1141
- id: 'LIST'
1142
- },
1143
- {
1144
- type: 'Release',
1145
- id: releaseId
1146
- }
1147
- ]));
1148
- };
1149
- const getCreatedByUser = ()=>{
1150
- if (!release?.createdBy) {
1151
- return null;
1152
- }
1153
- // Favor the username
1154
- if (release.createdBy.username) {
1155
- return release.createdBy.username;
1156
- }
1157
- // Firstname may not exist if created with SSO
1158
- if (release.createdBy.firstname) {
1159
- return `${release.createdBy.firstname} ${release.createdBy.lastname || ''}`.trim();
1160
- }
1161
- // All users must have at least an email
1162
- return release.createdBy.email;
1163
- };
1164
- if (isLoadingDetails) {
1165
- return /*#__PURE__*/ jsx(Page.Loading, {});
1166
- }
1167
- if (isBaseQueryError(error) && 'code' in error || !release) {
1168
- return /*#__PURE__*/ jsx(Navigate, {
1169
- to: "..",
1170
- state: {
1171
- errors: [
1172
- {
1173
- // @ts-expect-error – TODO: fix this weird error flow
1174
- code: error?.code
1175
- }
1176
- ]
1177
- }
1178
- });
1179
- }
1180
- const totalEntries = release.actions.meta.count || 0;
1181
- const hasCreatedByUser = Boolean(getCreatedByUser());
1182
- const isScheduled = release.scheduledAt && release.timezone;
1183
- const numberOfEntriesText = formatMessage({
1184
- id: 'content-releases.pages.Details.header-subtitle',
1185
- defaultMessage: '{number, plural, =0 {No entries} one {# entry} other {# entries}}'
1186
- }, {
1187
- number: totalEntries
1188
- });
1189
- const scheduledText = isScheduled ? formatMessage({
1190
- id: 'content-releases.pages.ReleaseDetails.header-subtitle.scheduled',
1191
- defaultMessage: 'Scheduled for {date} at {time} ({offset})'
1192
- }, {
1193
- date: formatDate(new Date(release.scheduledAt), {
1194
- weekday: 'long',
1195
- day: 'numeric',
1196
- month: 'long',
1197
- year: 'numeric',
1198
- timeZone: release.timezone
1199
- }),
1200
- time: formatTime(new Date(release.scheduledAt), {
1201
- timeZone: release.timezone,
1202
- hourCycle: 'h23'
1203
- }),
1204
- offset: getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
1205
- }) : '';
1206
- return /*#__PURE__*/ jsxs(Main, {
1207
- "aria-busy": isLoadingDetails,
1208
- children: [
1209
- /*#__PURE__*/ jsx(Layouts.Header, {
1210
- title: release.name,
1211
- subtitle: /*#__PURE__*/ jsxs(Flex, {
1212
- gap: 2,
1213
- lineHeight: 6,
1214
- children: [
1215
- /*#__PURE__*/ jsx(Typography, {
1216
- textColor: "neutral600",
1217
- variant: "epsilon",
1218
- children: numberOfEntriesText + (isScheduled ? ` - ${scheduledText}` : '')
1219
- }),
1220
- /*#__PURE__*/ jsx(Badge, {
1221
- ...getBadgeProps(release.status),
1222
- children: release.status
1223
- })
1224
- ]
1225
- }),
1226
- navigationAction: /*#__PURE__*/ jsx(BackButton, {
1227
- fallback: ".."
1228
- }),
1229
- primaryAction: !release.releasedAt && /*#__PURE__*/ jsxs(Flex, {
1230
- gap: 2,
1231
- children: [
1232
- /*#__PURE__*/ jsxs(SimpleMenuButton, {
1233
- label: /*#__PURE__*/ jsx(More, {}),
1234
- variant: "tertiary",
1235
- endIcon: null,
1236
- paddingLeft: "7px",
1237
- paddingRight: "7px",
1238
- "aria-label": formatMessage({
1239
- id: 'content-releases.header.actions.open-release-actions',
1240
- defaultMessage: 'Release edit and delete menu'
1241
- }),
1242
- popoverPlacement: "bottom-end",
1243
- children: [
1244
- /*#__PURE__*/ jsx(StyledMenuItem, {
1245
- disabled: !canUpdate,
1246
- onSelect: toggleEditReleaseModal,
1247
- children: /*#__PURE__*/ jsxs(Flex, {
1248
- alignItems: "center",
1249
- gap: 2,
1250
- hasRadius: true,
1251
- width: "100%",
1252
- children: [
1253
- /*#__PURE__*/ jsx(PencilIcon, {}),
1254
- /*#__PURE__*/ jsx(Typography, {
1255
- ellipsis: true,
1256
- children: formatMessage({
1257
- id: 'content-releases.header.actions.edit',
1258
- defaultMessage: 'Edit'
1259
- })
1260
- })
1261
- ]
1262
- })
1263
- }),
1264
- /*#__PURE__*/ jsx(StyledMenuItem, {
1265
- disabled: !canDelete,
1266
- onSelect: toggleWarningSubmit,
1267
- $variant: "danger",
1268
- children: /*#__PURE__*/ jsxs(Flex, {
1269
- alignItems: "center",
1270
- gap: 2,
1271
- hasRadius: true,
1272
- width: "100%",
1273
- children: [
1274
- /*#__PURE__*/ jsx(TrashIcon, {}),
1275
- /*#__PURE__*/ jsx(Typography, {
1276
- ellipsis: true,
1277
- textColor: "danger600",
1278
- children: formatMessage({
1279
- id: 'content-releases.header.actions.delete',
1280
- defaultMessage: 'Delete'
1281
- })
1282
- })
1283
- ]
1284
- })
1285
- }),
1286
- /*#__PURE__*/ jsxs(ReleaseInfoWrapper, {
1287
- direction: "column",
1288
- justifyContent: "center",
1289
- alignItems: "flex-start",
1290
- gap: 1,
1291
- padding: 4,
1292
- children: [
1293
- /*#__PURE__*/ jsx(Typography, {
1294
- variant: "pi",
1295
- fontWeight: "bold",
1296
- children: formatMessage({
1297
- id: 'content-releases.header.actions.created',
1298
- defaultMessage: 'Created'
1299
- })
1300
- }),
1301
- /*#__PURE__*/ jsxs(Typography, {
1302
- variant: "pi",
1303
- color: "neutral300",
1304
- children: [
1305
- /*#__PURE__*/ jsx(RelativeTime$1, {
1306
- timestamp: new Date(release.createdAt)
1307
- }),
1308
- formatMessage({
1309
- id: 'content-releases.header.actions.created.description',
1310
- defaultMessage: '{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}'
1311
- }, {
1312
- createdBy: getCreatedByUser(),
1313
- hasCreatedByUser
1314
- })
1315
- ]
1316
- })
1317
- ]
1318
- })
1319
- ]
1320
- }),
1321
- /*#__PURE__*/ jsx(Button, {
1322
- size: "S",
1323
- variant: "tertiary",
1324
- onClick: handleRefresh,
1325
- children: formatMessage({
1326
- id: 'content-releases.header.actions.refresh',
1327
- defaultMessage: 'Refresh'
1328
- })
1329
- }),
1330
- canPublish ? /*#__PURE__*/ jsx(Button, {
1331
- size: "S",
1332
- variant: "default",
1333
- onClick: handlePublishRelease(release.id.toString()),
1334
- loading: isPublishing,
1335
- disabled: release.actions.meta.count === 0,
1336
- children: formatMessage({
1337
- id: 'content-releases.header.actions.publish',
1338
- defaultMessage: 'Publish'
1339
- })
1340
- }) : null
1341
- ]
1342
- })
1343
- }),
1344
- children
1345
- ]
1346
- });
1347
- };
1348
- const SimpleMenuButton = styled(SimpleMenu)`
1349
- & > span {
1350
- display: flex;
1351
- }
1352
- `;
1353
- /* -------------------------------------------------------------------------------------------------
1354
- * ReleaseDetailsBody
1355
- * -----------------------------------------------------------------------------------------------*/ const GROUP_BY_OPTIONS = [
1356
- 'contentType',
1357
- 'locale',
1358
- 'action'
1359
- ];
1360
- const GROUP_BY_OPTIONS_NO_LOCALE = [
1361
- 'contentType',
1362
- 'action'
1363
- ];
1364
- const getGroupByOptionLabel = (value)=>{
1365
- if (value === 'locale') {
1366
- return {
1367
- id: 'content-releases.pages.ReleaseDetails.groupBy.option.locales',
1368
- defaultMessage: 'Locales'
1369
- };
1370
- }
1371
- if (value === 'action') {
1372
- return {
1373
- id: 'content-releases.pages.ReleaseDetails.groupBy.option.actions',
1374
- defaultMessage: 'Actions'
1375
- };
1376
- }
1377
- return {
1378
- id: 'content-releases.pages.ReleaseDetails.groupBy.option.content-type',
1379
- defaultMessage: 'Content-Types'
1380
- };
1381
- };
1382
- const ReleaseDetailsBody = ({ releaseId })=>{
1383
- const { formatMessage } = useIntl();
1384
- const [{ query }, setQuery] = useQueryParams();
1385
- const { toggleNotification } = useNotification();
1386
- const { formatAPIError } = useAPIErrorHandler();
1387
- const { data: releaseData, isLoading: isReleaseLoading, error: releaseError } = useGetReleaseQuery({
1388
- id: releaseId
1389
- });
1390
- const { allowedActions: { canUpdate } } = useRBAC(PERMISSIONS);
1391
- const runHookWaterfall = useStrapiApp('ReleaseDetailsPage', (state)=>state.runHookWaterfall);
1392
- // TODO: Migrated displayedHeader to v5
1393
- const { displayedHeaders, hasI18nEnabled } = runHookWaterfall('ContentReleases/pages/ReleaseDetails/add-locale-in-releases', {
1394
- displayedHeaders: [
1395
- {
1396
- label: {
1397
- id: 'content-releases.page.ReleaseDetails.table.header.label.name',
1398
- defaultMessage: 'name'
1399
- },
1400
- name: 'name'
1401
- }
1402
- ],
1403
- hasI18nEnabled: false
1404
- });
1405
- const release = releaseData?.data;
1406
- const selectedGroupBy = query?.groupBy || 'contentType';
1407
- const { isLoading, isFetching, isError, data, error: releaseActionsError } = useGetReleaseActionsQuery({
1408
- ...query,
1409
- releaseId
1410
- });
1411
- const [updateReleaseAction] = useUpdateReleaseActionMutation();
1412
- const handleChangeType = async (e, actionId, actionPath)=>{
1413
- const response = await updateReleaseAction({
1414
- params: {
1415
- releaseId,
1416
- actionId
1417
- },
1418
- body: {
1419
- type: e.target.value
1420
- },
1421
- query,
1422
- actionPath
1423
- });
1424
- if ('error' in response) {
1425
- if (isFetchError(response.error)) {
1426
- // When the response returns an object with 'error', handle fetch error
1427
- toggleNotification({
1428
- type: 'danger',
1429
- message: formatAPIError(response.error)
1430
- });
1431
- } else {
1432
- // Otherwise, the response returns an object with 'error', handle a generic error
1433
- toggleNotification({
1434
- type: 'danger',
1435
- message: formatMessage({
1436
- id: 'notification.error',
1437
- defaultMessage: 'An error occurred'
1438
- })
1439
- });
1440
- }
1441
- }
1442
- };
1443
- if (isLoading || isReleaseLoading) {
1444
- return /*#__PURE__*/ jsx(Page.Loading, {});
1445
- }
1446
- const releaseActions = data?.data;
1447
- const releaseMeta = data?.meta;
1448
- const contentTypes = releaseMeta?.contentTypes || {};
1449
- releaseMeta?.components || {};
1450
- if (isBaseQueryError(releaseError) || !release) {
1451
- const errorsArray = [];
1452
- if (releaseError && 'code' in releaseError) {
1453
- errorsArray.push({
1454
- code: releaseError.code
1455
- });
1456
- }
1457
- if (releaseActionsError && 'code' in releaseActionsError) {
1458
- errorsArray.push({
1459
- code: releaseActionsError.code
1460
- });
1461
- }
1462
- return /*#__PURE__*/ jsx(Navigate, {
1463
- to: "..",
1464
- state: {
1465
- errors: errorsArray
1466
- }
1467
- });
1468
- }
1469
- if (isError || !releaseActions) {
1470
- return /*#__PURE__*/ jsx(Page.Error, {});
1471
- }
1472
- if (Object.keys(releaseActions).length === 0) {
1473
- return /*#__PURE__*/ jsx(Layouts.Content, {
1474
- children: /*#__PURE__*/ jsx(EmptyStateLayout, {
1475
- action: /*#__PURE__*/ jsx(LinkButton, {
1476
- tag: Link,
1477
- to: {
1478
- pathname: '/content-manager'
1479
- },
1480
- style: {
1481
- textDecoration: 'none'
1482
- },
1483
- variant: "secondary",
1484
- children: formatMessage({
1485
- id: 'content-releases.page.Details.button.openContentManager',
1486
- defaultMessage: 'Open the Content Manager'
1487
- })
1488
- }),
1489
- icon: /*#__PURE__*/ jsx(EmptyDocuments, {
1490
- width: "16rem"
1491
- }),
1492
- content: formatMessage({
1493
- id: 'content-releases.pages.Details.tab.emptyEntries',
1494
- defaultMessage: 'This release is empty. Open the Content Manager, select an entry and add it to the release.'
1495
- })
1496
- })
1497
- });
1498
- }
1499
- const groupByLabel = formatMessage({
1500
- id: 'content-releases.pages.ReleaseDetails.groupBy.aria-label',
1501
- defaultMessage: 'Group by'
1502
- });
1503
- const headers = [
1504
- ...displayedHeaders,
1505
- {
1506
- label: {
1507
- id: 'content-releases.page.ReleaseDetails.table.header.label.content-type',
1508
- defaultMessage: 'content-type'
1509
- },
1510
- name: 'content-type'
1511
- },
1512
- {
1513
- label: {
1514
- id: 'content-releases.page.ReleaseDetails.table.header.label.action',
1515
- defaultMessage: 'action'
1516
- },
1517
- name: 'action'
1518
- },
1519
- ...!release.releasedAt ? [
1520
- {
1521
- label: {
1522
- id: 'content-releases.page.ReleaseDetails.table.header.label.status',
1523
- defaultMessage: 'status'
1524
- },
1525
- name: 'status'
1526
- }
1527
- ] : []
1528
- ];
1529
- const options = hasI18nEnabled ? GROUP_BY_OPTIONS : GROUP_BY_OPTIONS_NO_LOCALE;
1530
- return /*#__PURE__*/ jsx(Layouts.Content, {
1531
- children: /*#__PURE__*/ jsxs(Flex, {
1532
- gap: 8,
1533
- direction: "column",
1534
- alignItems: "stretch",
1535
- children: [
1536
- /*#__PURE__*/ jsx(Flex, {
1537
- children: /*#__PURE__*/ jsx(SingleSelect, {
1538
- placeholder: groupByLabel,
1539
- "aria-label": groupByLabel,
1540
- customizeContent: (value)=>formatMessage({
1541
- id: `content-releases.pages.ReleaseDetails.groupBy.label`,
1542
- defaultMessage: `Group by {groupBy}`
1543
- }, {
1544
- groupBy: value
1545
- }),
1546
- value: formatMessage(getGroupByOptionLabel(selectedGroupBy)),
1547
- onChange: (value)=>setQuery({
1548
- groupBy: value
1549
- }),
1550
- children: options.map((option)=>/*#__PURE__*/ jsx(SingleSelectOption, {
1551
- value: option,
1552
- children: formatMessage(getGroupByOptionLabel(option))
1553
- }, option))
1554
- })
1555
- }),
1556
- Object.keys(releaseActions).map((key)=>/*#__PURE__*/ jsxs(Flex, {
1557
- gap: 4,
1558
- direction: "column",
1559
- alignItems: "stretch",
1560
- children: [
1561
- /*#__PURE__*/ jsx(Flex, {
1562
- role: "separator",
1563
- "aria-label": key,
1564
- children: /*#__PURE__*/ jsx(Badge, {
1565
- children: key
1566
- })
1567
- }),
1568
- /*#__PURE__*/ jsx(Table.Root, {
1569
- rows: releaseActions[key].map((item)=>({
1570
- ...item,
1571
- id: Number(item.entry.id)
1572
- })),
1573
- headers: headers,
1574
- isLoading: isLoading || isFetching,
1575
- children: /*#__PURE__*/ jsxs(Table.Content, {
1576
- children: [
1577
- /*#__PURE__*/ jsx(Table.Head, {
1578
- children: headers.map(({ label, name })=>/*#__PURE__*/ jsx(Table.HeaderCell, {
1579
- label: formatMessage(label),
1580
- name: name
1581
- }, name))
1582
- }),
1583
- /*#__PURE__*/ jsx(Table.Loading, {}),
1584
- /*#__PURE__*/ jsx(Table.Body, {
1585
- children: releaseActions[key].map(({ id, contentType, locale, type, entry, status }, actionIndex)=>/*#__PURE__*/ jsxs(Tr, {
1586
- children: [
1587
- /*#__PURE__*/ jsx(Td, {
1588
- width: "25%",
1589
- maxWidth: "200px",
1590
- children: /*#__PURE__*/ jsx(Typography, {
1591
- ellipsis: true,
1592
- children: `${contentType.mainFieldValue || entry.id}`
1593
- })
1594
- }),
1595
- hasI18nEnabled && /*#__PURE__*/ jsx(Td, {
1596
- width: "10%",
1597
- children: /*#__PURE__*/ jsx(Typography, {
1598
- children: `${locale?.name ? locale.name : '-'}`
1599
- })
1600
- }),
1601
- /*#__PURE__*/ jsx(Td, {
1602
- width: "10%",
1603
- children: /*#__PURE__*/ jsx(Typography, {
1604
- children: contentType.displayName || ''
1605
- })
1606
- }),
1607
- /*#__PURE__*/ jsx(Td, {
1608
- width: "20%",
1609
- children: release.releasedAt ? /*#__PURE__*/ jsx(Typography, {
1610
- children: formatMessage({
1611
- id: 'content-releases.page.ReleaseDetails.table.action-published',
1612
- defaultMessage: 'This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>.'
1613
- }, {
1614
- isPublish: type === 'publish',
1615
- b: (children)=>/*#__PURE__*/ jsx(Typography, {
1616
- fontWeight: "bold",
1617
- children: children
1618
- })
1619
- })
1620
- }) : /*#__PURE__*/ jsx(ReleaseActionOptions, {
1621
- selected: type,
1622
- handleChange: (e)=>handleChangeType(e, id, [
1623
- key,
1624
- actionIndex
1625
- ]),
1626
- name: `release-action-${id}-type`,
1627
- disabled: !canUpdate
1628
- })
1629
- }),
1630
- !release.releasedAt && /*#__PURE__*/ jsxs(Fragment, {
1631
- children: [
1632
- /*#__PURE__*/ jsx(Td, {
1633
- width: "20%",
1634
- minWidth: "200px",
1635
- children: /*#__PURE__*/ jsx(EntryValidationPopover, {
1636
- action: type,
1637
- schema: contentTypes?.[contentType.uid],
1638
- entry: entry,
1639
- status: status
1640
- })
1641
- }),
1642
- /*#__PURE__*/ jsx(Td, {
1643
- children: /*#__PURE__*/ jsx(Flex, {
1644
- justifyContent: "flex-end",
1645
- children: /*#__PURE__*/ jsxs(ReleaseActionMenu.Root, {
1646
- children: [
1647
- /*#__PURE__*/ jsx(ReleaseActionMenu.ReleaseActionEntryLinkItem, {
1648
- contentTypeUid: contentType.uid,
1649
- documentId: entry.documentId,
1650
- locale: locale?.code
1651
- }),
1652
- /*#__PURE__*/ jsx(ReleaseActionMenu.DeleteReleaseActionItem, {
1653
- releaseId: release.id,
1654
- actionId: id
1655
- })
1656
- ]
1657
- })
1658
- })
1659
- })
1660
- ]
1661
- })
1662
- ]
1663
- }, id))
1664
- })
1665
- ]
1666
- })
1667
- })
1668
- ]
1669
- }, `releases-group-${key}`)),
1670
- /*#__PURE__*/ jsxs(Pagination.Root, {
1671
- ...releaseMeta?.pagination,
1672
- defaultPageSize: releaseMeta?.pagination?.pageSize,
1673
- children: [
1674
- /*#__PURE__*/ jsx(Pagination.PageSize, {}),
1675
- /*#__PURE__*/ jsx(Pagination.Links, {})
1676
- ]
1677
- })
1678
- ]
1679
- })
1680
- });
1681
- };
1682
- /* -------------------------------------------------------------------------------------------------
1683
- * ReleaseDetailsPage
1684
- * -----------------------------------------------------------------------------------------------*/ const ReleaseDetailsPage = ()=>{
1685
- const { formatMessage } = useIntl();
1686
- const { releaseId } = useParams();
1687
- const { toggleNotification } = useNotification();
1688
- const { formatAPIError } = useAPIErrorHandler();
1689
- const navigate = useNavigate();
1690
- const [releaseModalShown, setReleaseModalShown] = React.useState(false);
1691
- const [showWarningSubmit, setWarningSubmit] = React.useState(false);
1692
- const { isLoading: isLoadingDetails, data, isSuccess: isSuccessDetails } = useGetReleaseQuery({
1693
- id: releaseId
1694
- }, {
1695
- skip: !releaseId
1696
- });
1697
- const { data: dataTimezone, isLoading: isLoadingTimezone } = useGetReleaseSettingsQuery();
1698
- const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();
1699
- const [deleteRelease] = useDeleteReleaseMutation();
1700
- const toggleEditReleaseModal = ()=>{
1701
- setReleaseModalShown((prev)=>!prev);
1702
- };
1703
- const getTimezoneValue = ()=>{
1704
- if (releaseData?.timezone) {
1705
- return releaseData.timezone;
1706
- } else {
1707
- if (dataTimezone?.data.defaultTimezone) {
1708
- return dataTimezone.data.defaultTimezone;
1709
- }
1710
- return null;
1711
- }
1712
- };
1713
- const toggleWarningSubmit = ()=>setWarningSubmit((prevState)=>!prevState);
1714
- if (isLoadingDetails || isLoadingTimezone) {
1715
- return /*#__PURE__*/ jsx(ReleaseDetailsLayout, {
1716
- toggleEditReleaseModal: toggleEditReleaseModal,
1717
- toggleWarningSubmit: toggleWarningSubmit,
1718
- children: /*#__PURE__*/ jsx(Page.Loading, {})
1719
- });
1720
- }
1721
- if (!releaseId) {
1722
- return /*#__PURE__*/ jsx(Navigate, {
1723
- to: ".."
1724
- });
1725
- }
1726
- const releaseData = isSuccessDetails && data?.data || null;
1727
- const title = releaseData?.name || '';
1728
- const timezone = getTimezoneValue();
1729
- const scheduledAt = releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;
1730
- // Just get the date and time to display without considering updated timezone time
1731
- const date = scheduledAt ? format$1(scheduledAt, 'yyyy-MM-dd') : undefined;
1732
- const time = scheduledAt ? format$1(scheduledAt, 'HH:mm') : '';
1733
- const handleEditRelease = async (values)=>{
1734
- const response = await updateRelease({
1735
- id: releaseId,
1736
- name: values.name,
1737
- scheduledAt: values.scheduledAt,
1738
- timezone: values.timezone
1739
- });
1740
- if ('data' in response) {
1741
- // When the response returns an object with 'data', handle success
1742
- toggleNotification({
1743
- type: 'success',
1744
- message: formatMessage({
1745
- id: 'content-releases.modal.release-updated-notification-success',
1746
- defaultMessage: 'Release updated.'
1747
- })
1748
- });
1749
- toggleEditReleaseModal();
1750
- } else if (isFetchError(response.error)) {
1751
- // When the response returns an object with 'error', handle fetch error
1752
- toggleNotification({
1753
- type: 'danger',
1754
- message: formatAPIError(response.error)
1755
- });
1756
- } else {
1757
- // Otherwise, the response returns an object with 'error', handle a generic error
1758
- toggleNotification({
1759
- type: 'danger',
1760
- message: formatMessage({
1761
- id: 'notification.error',
1762
- defaultMessage: 'An error occurred'
1763
- })
1764
- });
1765
- }
1766
- };
1767
- const handleDeleteRelease = async ()=>{
1768
- const response = await deleteRelease({
1769
- id: releaseId
1770
- });
1771
- if ('data' in response) {
1772
- navigate('..');
1773
- } else if (isFetchError(response.error)) {
1774
- // When the response returns an object with 'error', handle fetch error
1775
- toggleNotification({
1776
- type: 'danger',
1777
- message: formatAPIError(response.error)
1778
- });
1779
- } else {
1780
- // Otherwise, the response returns an object with 'error', handle a generic error
1781
- toggleNotification({
1782
- type: 'danger',
1783
- message: formatMessage({
1784
- id: 'notification.error',
1785
- defaultMessage: 'An error occurred'
1786
- })
1787
- });
1788
- }
1789
- };
1790
- return /*#__PURE__*/ jsxs(ReleaseDetailsLayout, {
1791
- toggleEditReleaseModal: toggleEditReleaseModal,
1792
- toggleWarningSubmit: toggleWarningSubmit,
1793
- children: [
1794
- /*#__PURE__*/ jsx(ReleaseDetailsBody, {
1795
- releaseId: releaseId
1796
- }),
1797
- /*#__PURE__*/ jsx(ReleaseModal, {
1798
- open: releaseModalShown,
1799
- handleClose: toggleEditReleaseModal,
1800
- handleSubmit: handleEditRelease,
1801
- isLoading: isLoadingDetails || isSubmittingForm,
1802
- initialValues: {
1803
- name: title || '',
1804
- scheduledAt,
1805
- date,
1806
- time,
1807
- isScheduled: Boolean(scheduledAt),
1808
- timezone
1809
- }
1810
- }),
1811
- /*#__PURE__*/ jsx(Dialog.Root, {
1812
- open: showWarningSubmit,
1813
- onOpenChange: toggleWarningSubmit,
1814
- children: /*#__PURE__*/ jsx(ConfirmDialog, {
1815
- onConfirm: handleDeleteRelease,
1816
- children: formatMessage({
1817
- id: 'content-releases.dialog.confirmation-message',
1818
- defaultMessage: 'Are you sure you want to delete this release?'
1819
- })
1820
- })
1821
- })
1822
- ]
1823
- });
1824
- };
1825
-
1826
- const App = ()=>{
1827
- return /*#__PURE__*/ jsx(Page.Protect, {
1828
- permissions: PERMISSIONS.main,
1829
- children: /*#__PURE__*/ jsxs(Routes, {
1830
- children: [
1831
- /*#__PURE__*/ jsx(Route, {
1832
- index: true,
1833
- element: /*#__PURE__*/ jsx(ReleasesPage, {})
1834
- }),
1835
- /*#__PURE__*/ jsx(Route, {
1836
- path: ':releaseId',
1837
- element: /*#__PURE__*/ jsx(ReleaseDetailsPage, {})
1838
- })
1839
- ]
1840
- })
1841
- });
1842
- };
1843
-
1844
- export { App };
1845
- //# sourceMappingURL=App-BkWgp5q_.mjs.map