@strapi/content-releases 0.0.0-experimental.d5b46d578a5c055b8dcc66939e1b5d540976fafb → 0.0.0-experimental.d834c9e658d1fb037e6da1105150593521c667cc

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 (140) hide show
  1. package/LICENSE +17 -1
  2. package/dist/_chunks/{App-x6Tjj3HN.mjs → App-DMILern_.mjs} +584 -543
  3. package/dist/_chunks/App-DMILern_.mjs.map +1 -0
  4. package/dist/_chunks/App-fAgiijnc.js +1377 -0
  5. package/dist/_chunks/App-fAgiijnc.js.map +1 -0
  6. package/dist/_chunks/{PurchaseContentReleases-bpIYXOfu.js → PurchaseContentReleases-Be3acS2L.js} +7 -6
  7. package/dist/_chunks/PurchaseContentReleases-Be3acS2L.js.map +1 -0
  8. package/dist/_chunks/{PurchaseContentReleases-3tRbmbY3.mjs → PurchaseContentReleases-_MxP6-Dt.mjs} +8 -7
  9. package/dist/_chunks/PurchaseContentReleases-_MxP6-Dt.mjs.map +1 -0
  10. package/dist/_chunks/ReleasesSettingsPage-YVZJH-oN.js +178 -0
  11. package/dist/_chunks/ReleasesSettingsPage-YVZJH-oN.js.map +1 -0
  12. package/dist/_chunks/ReleasesSettingsPage-dwoRuXB-.mjs +178 -0
  13. package/dist/_chunks/ReleasesSettingsPage-dwoRuXB-.mjs.map +1 -0
  14. package/dist/_chunks/{en-3SGjiVyR.js → en-CmYoEnA7.js} +10 -2
  15. package/dist/_chunks/en-CmYoEnA7.js.map +1 -0
  16. package/dist/_chunks/{en-bpHsnU0n.mjs → en-D0yVZFqf.mjs} +10 -2
  17. package/dist/_chunks/en-D0yVZFqf.mjs.map +1 -0
  18. package/dist/_chunks/index--_NWfuDG.js +1358 -0
  19. package/dist/_chunks/index--_NWfuDG.js.map +1 -0
  20. package/dist/_chunks/index-CYsQToWs.mjs +1339 -0
  21. package/dist/_chunks/index-CYsQToWs.mjs.map +1 -0
  22. package/dist/_chunks/schemas-63pFihNF.mjs +44 -0
  23. package/dist/_chunks/schemas-63pFihNF.mjs.map +1 -0
  24. package/dist/_chunks/schemas-z5zp-_Gd.js +62 -0
  25. package/dist/_chunks/schemas-z5zp-_Gd.js.map +1 -0
  26. package/dist/admin/index.js +1 -15
  27. package/dist/admin/index.js.map +1 -1
  28. package/dist/admin/index.mjs +2 -16
  29. package/dist/admin/index.mjs.map +1 -1
  30. package/dist/admin/src/components/RelativeTime.d.ts +28 -0
  31. package/dist/admin/src/components/ReleaseAction.d.ts +3 -0
  32. package/dist/admin/src/components/ReleaseActionMenu.d.ts +26 -0
  33. package/dist/admin/src/components/ReleaseActionModal.d.ts +24 -0
  34. package/dist/admin/src/components/ReleaseActionOptions.d.ts +9 -0
  35. package/dist/admin/src/components/ReleaseListCell.d.ts +28 -0
  36. package/dist/admin/src/components/ReleaseModal.d.ts +17 -0
  37. package/dist/admin/src/components/ReleasesPanel.d.ts +3 -0
  38. package/dist/admin/src/constants.d.ts +76 -0
  39. package/dist/admin/src/index.d.ts +3 -0
  40. package/dist/admin/src/modules/hooks.d.ts +7 -0
  41. package/dist/admin/src/pages/App.d.ts +1 -0
  42. package/dist/admin/src/pages/PurchaseContentReleases.d.ts +2 -0
  43. package/dist/admin/src/pages/ReleaseDetailsPage.d.ts +2 -0
  44. package/dist/admin/src/pages/ReleasesPage.d.ts +8 -0
  45. package/dist/admin/src/pages/ReleasesSettingsPage.d.ts +1 -0
  46. package/dist/admin/src/pages/tests/mockReleaseDetailsPageData.d.ts +181 -0
  47. package/dist/admin/src/pages/tests/mockReleasesPageData.d.ts +39 -0
  48. package/dist/admin/src/pluginId.d.ts +1 -0
  49. package/dist/admin/src/services/release.d.ts +112 -0
  50. package/dist/admin/src/store/hooks.d.ts +7 -0
  51. package/dist/admin/src/utils/api.d.ts +6 -0
  52. package/dist/admin/src/utils/prefixPluginTranslations.d.ts +3 -0
  53. package/dist/admin/src/utils/time.d.ts +10 -0
  54. package/dist/admin/src/validation/schemas.d.ts +6 -0
  55. package/dist/server/index.js +850 -618
  56. package/dist/server/index.js.map +1 -1
  57. package/dist/server/index.mjs +851 -618
  58. package/dist/server/index.mjs.map +1 -1
  59. package/dist/server/src/bootstrap.d.ts +5 -0
  60. package/dist/server/src/bootstrap.d.ts.map +1 -0
  61. package/dist/server/src/constants.d.ts +21 -0
  62. package/dist/server/src/constants.d.ts.map +1 -0
  63. package/dist/server/src/content-types/index.d.ts +97 -0
  64. package/dist/server/src/content-types/index.d.ts.map +1 -0
  65. package/dist/server/src/content-types/release/index.d.ts +48 -0
  66. package/dist/server/src/content-types/release/index.d.ts.map +1 -0
  67. package/dist/server/src/content-types/release/schema.d.ts +47 -0
  68. package/dist/server/src/content-types/release/schema.d.ts.map +1 -0
  69. package/dist/server/src/content-types/release-action/index.d.ts +48 -0
  70. package/dist/server/src/content-types/release-action/index.d.ts.map +1 -0
  71. package/dist/server/src/content-types/release-action/schema.d.ts +47 -0
  72. package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -0
  73. package/dist/server/src/controllers/index.d.ts +25 -0
  74. package/dist/server/src/controllers/index.d.ts.map +1 -0
  75. package/dist/server/src/controllers/release-action.d.ts +10 -0
  76. package/dist/server/src/controllers/release-action.d.ts.map +1 -0
  77. package/dist/server/src/controllers/release.d.ts +18 -0
  78. package/dist/server/src/controllers/release.d.ts.map +1 -0
  79. package/dist/server/src/controllers/settings.d.ts +11 -0
  80. package/dist/server/src/controllers/settings.d.ts.map +1 -0
  81. package/dist/server/src/controllers/validation/release-action.d.ts +14 -0
  82. package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -0
  83. package/dist/server/src/controllers/validation/release.d.ts +4 -0
  84. package/dist/server/src/controllers/validation/release.d.ts.map +1 -0
  85. package/dist/server/src/controllers/validation/settings.d.ts +3 -0
  86. package/dist/server/src/controllers/validation/settings.d.ts.map +1 -0
  87. package/dist/server/src/destroy.d.ts +5 -0
  88. package/dist/server/src/destroy.d.ts.map +1 -0
  89. package/dist/server/src/index.d.ts +2113 -0
  90. package/dist/server/src/index.d.ts.map +1 -0
  91. package/dist/server/src/middlewares/documents.d.ts +6 -0
  92. package/dist/server/src/middlewares/documents.d.ts.map +1 -0
  93. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts +9 -0
  94. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts.map +1 -0
  95. package/dist/server/src/migrations/index.d.ts +13 -0
  96. package/dist/server/src/migrations/index.d.ts.map +1 -0
  97. package/dist/server/src/register.d.ts +5 -0
  98. package/dist/server/src/register.d.ts.map +1 -0
  99. package/dist/server/src/routes/index.d.ts +51 -0
  100. package/dist/server/src/routes/index.d.ts.map +1 -0
  101. package/dist/server/src/routes/release-action.d.ts +18 -0
  102. package/dist/server/src/routes/release-action.d.ts.map +1 -0
  103. package/dist/server/src/routes/release.d.ts +18 -0
  104. package/dist/server/src/routes/release.d.ts.map +1 -0
  105. package/dist/server/src/routes/settings.d.ts +18 -0
  106. package/dist/server/src/routes/settings.d.ts.map +1 -0
  107. package/dist/server/src/services/index.d.ts +1826 -0
  108. package/dist/server/src/services/index.d.ts.map +1 -0
  109. package/dist/server/src/services/release-action.d.ts +36 -0
  110. package/dist/server/src/services/release-action.d.ts.map +1 -0
  111. package/dist/server/src/services/release.d.ts +31 -0
  112. package/dist/server/src/services/release.d.ts.map +1 -0
  113. package/dist/server/src/services/scheduling.d.ts +18 -0
  114. package/dist/server/src/services/scheduling.d.ts.map +1 -0
  115. package/dist/server/src/services/settings.d.ts +13 -0
  116. package/dist/server/src/services/settings.d.ts.map +1 -0
  117. package/dist/server/src/services/validation.d.ts +18 -0
  118. package/dist/server/src/services/validation.d.ts.map +1 -0
  119. package/dist/server/src/utils/index.d.ts +35 -0
  120. package/dist/server/src/utils/index.d.ts.map +1 -0
  121. package/dist/shared/contracts/release-actions.d.ts +130 -0
  122. package/dist/shared/contracts/release-actions.d.ts.map +1 -0
  123. package/dist/shared/contracts/releases.d.ts +184 -0
  124. package/dist/shared/contracts/releases.d.ts.map +1 -0
  125. package/dist/shared/contracts/settings.d.ts +39 -0
  126. package/dist/shared/contracts/settings.d.ts.map +1 -0
  127. package/dist/shared/types.d.ts +24 -0
  128. package/dist/shared/types.d.ts.map +1 -0
  129. package/package.json +30 -36
  130. package/dist/_chunks/App-OP70yd5M.js +0 -1338
  131. package/dist/_chunks/App-OP70yd5M.js.map +0 -1
  132. package/dist/_chunks/App-x6Tjj3HN.mjs.map +0 -1
  133. package/dist/_chunks/PurchaseContentReleases-3tRbmbY3.mjs.map +0 -1
  134. package/dist/_chunks/PurchaseContentReleases-bpIYXOfu.js.map +0 -1
  135. package/dist/_chunks/en-3SGjiVyR.js.map +0 -1
  136. package/dist/_chunks/en-bpHsnU0n.mjs.map +0 -1
  137. package/dist/_chunks/index-1ejXLtzt.mjs +0 -1203
  138. package/dist/_chunks/index-1ejXLtzt.mjs.map +0 -1
  139. package/dist/_chunks/index-ydocdaZ0.js +0 -1224
  140. package/dist/_chunks/index-ydocdaZ0.js.map +0 -1
@@ -1,45 +1,54 @@
1
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { RelativeTime as RelativeTime$1, useNotification, useAPIErrorHandler, useQueryParams, useTracking, LoadingIndicatorPage, CheckPermissions, PageSizeURLQuery, PaginationURLQuery, AnErrorOccurred, ConfirmDialog, useRBAC, NoContent, Table, CheckPagePermissions } from "@strapi/helper-plugin";
3
- import { useLocation, useHistory, useParams, Redirect, Link as Link$2, Switch, Route } from "react-router-dom";
4
- import { g as getTimezoneOffset, p as pluginId, u as useGetReleasesQuery, a as useCreateReleaseMutation, P as PERMISSIONS, i as isAxiosError, b as useGetReleaseQuery, c as useUpdateReleaseMutation, d as useDeleteReleaseMutation, e as usePublishReleaseMutation, f as useTypedDispatch, h as useGetReleaseActionsQuery, j as useUpdateReleaseActionMutation, R as ReleaseActionOptions, k as ReleaseActionMenu, r as releaseApi } from "./index-1ejXLtzt.mjs";
1
+ import { jsx, jsxs, 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 { useLocation, useNavigate, NavLink, useParams, Navigate, Link as Link$1, 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-CYsQToWs.mjs";
5
5
  import * as React from "react";
6
- import { useLicenseLimits, unstable_useDocument } from "@strapi/admin/strapi-admin";
7
- import { ModalLayout, ModalHeader, Typography, ModalBody, Flex, TextInput, Box, Checkbox, DatePicker, TimePicker, ModalFooter, Button, Combobox, ComboboxOption, Alert, Main, HeaderLayout, ContentLayout, TabGroup, Tabs, Tab, Divider, TabPanels, TabPanel, EmptyStateLayout, Grid, GridItem, Badge, Link as Link$1, IconButton, SingleSelect, SingleSelectOption, Tr, Td, Icon, Tooltip } from "@strapi/design-system";
8
- import { Link, Menu, LinkButton } from "@strapi/design-system/v2";
9
- import { Plus, EmptyDocuments, Pencil, Trash, ArrowLeft, More, CrossCircle, CheckCircle } from "@strapi/icons";
10
- import format from "date-fns/format";
6
+ import { unstable_useDocument } from "@strapi/content-manager/strapi-admin";
7
+ import { Modal, Flex, Field, TextInput, Box, Checkbox, Typography, DatePicker, TimePicker, Button, Combobox, ComboboxOption, Link, Alert, Main, Tabs, Divider, EmptyStateLayout, Grid, Badge, MenuItem, SimpleMenu, Dialog, LinkButton, SingleSelect, SingleSelectOption, Tr, Td, Tooltip } from "@strapi/design-system";
8
+ import { Plus, Pencil, Trash, More, CrossCircle, CheckCircle, ArrowsCounterClockwise } from "@strapi/icons";
9
+ import { EmptyDocuments } from "@strapi/icons/symbols";
10
+ import format$1 from "date-fns/format";
11
11
  import { utcToZonedTime, zonedTimeToUtc } from "date-fns-tz";
12
12
  import { useIntl } from "react-intl";
13
- import styled from "styled-components";
14
- import { formatISO } from "date-fns";
13
+ import { styled } from "styled-components";
14
+ import { intervalToDuration, isPast, formatISO, format } from "date-fns";
15
15
  import { Formik, Form, useFormikContext } from "formik";
16
- import * as yup from "yup";
17
- import "@reduxjs/toolkit/query";
18
- import "axios";
19
- import "@reduxjs/toolkit/query/react";
20
- import "react-redux";
21
- const RELEASE_SCHEMA = yup.object().shape({
22
- name: yup.string().trim().required(),
23
- scheduledAt: yup.string().nullable(),
24
- isScheduled: yup.boolean().optional(),
25
- time: yup.string().when("isScheduled", {
26
- is: true,
27
- then: yup.string().trim().required(),
28
- otherwise: yup.string().nullable()
29
- }),
30
- timezone: yup.string().when("isScheduled", {
31
- is: true,
32
- then: yup.string().required().nullable(),
33
- otherwise: yup.string().nullable()
34
- }),
35
- date: yup.string().when("isScheduled", {
36
- is: true,
37
- then: yup.string().required().nullable(),
38
- otherwise: yup.string().nullable()
39
- })
40
- }).required().noUnknown();
16
+ import { R as RELEASE_SCHEMA } from "./schemas-63pFihNF.mjs";
17
+ import { useDispatch } from "react-redux";
18
+ import { useLicenseLimits } from "@strapi/admin/strapi-admin/ee";
19
+ const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
20
+ const RelativeTime$1 = React.forwardRef(
21
+ ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
22
+ const { formatRelativeTime, formatDate, formatTime } = useIntl();
23
+ const interval = intervalToDuration({
24
+ start: timestamp,
25
+ end: Date.now()
26
+ // see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
27
+ });
28
+ const unit = intervals.find((intervalUnit) => {
29
+ return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
30
+ });
31
+ const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
32
+ const customInterval = customIntervals.find(
33
+ (custom) => interval[custom.unit] < custom.threshold
34
+ );
35
+ const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
36
+ return /* @__PURE__ */ jsx(
37
+ "time",
38
+ {
39
+ ref: forwardedRef,
40
+ dateTime: timestamp.toISOString(),
41
+ role: "time",
42
+ title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
43
+ ...restProps,
44
+ children: displayText
45
+ }
46
+ );
47
+ }
48
+ );
41
49
  const ReleaseModal = ({
42
50
  handleClose,
51
+ open,
43
52
  handleSubmit,
44
53
  initialValues,
45
54
  isLoading = false
@@ -63,8 +72,8 @@ const ReleaseModal = ({
63
72
  );
64
73
  return currentTimezone?.value || systemTimezone.value;
65
74
  };
66
- return /* @__PURE__ */ jsxs(ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
67
- /* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage(
75
+ return /* @__PURE__ */ jsx(Modal.Root, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
76
+ /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: formatMessage(
68
77
  {
69
78
  id: "content-releases.modal.title",
70
79
  defaultMessage: "{isCreatingRelease, select, true {New release} other {Edit release}}"
@@ -87,133 +96,143 @@ const ReleaseModal = ({
87
96
  },
88
97
  validationSchema: RELEASE_SCHEMA,
89
98
  validateOnChange: false,
90
- children: ({ values, errors, handleChange, setFieldValue }) => /* @__PURE__ */ jsxs(Form, { children: [
91
- /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
92
- /* @__PURE__ */ jsx(
93
- TextInput,
94
- {
95
- label: formatMessage({
96
- id: "content-releases.modal.form.input.label.release-name",
97
- defaultMessage: "Name"
98
- }),
99
- name: "name",
100
- value: values.name,
101
- error: errors.name,
102
- onChange: handleChange,
103
- required: true
104
- }
105
- ),
106
- /* @__PURE__ */ jsx(Box, { width: "max-content", children: /* @__PURE__ */ jsx(
107
- Checkbox,
108
- {
109
- name: "isScheduled",
110
- value: values.isScheduled,
111
- onChange: (event) => {
112
- setFieldValue("isScheduled", event.target.checked);
113
- if (!event.target.checked) {
114
- setFieldValue("date", null);
115
- setFieldValue("time", "");
116
- setFieldValue("timezone", null);
117
- } else {
118
- setFieldValue("date", initialValues.date);
119
- setFieldValue("time", initialValues.time);
120
- setFieldValue("timezone", initialValues.timezone ?? systemTimezone?.value);
121
- }
122
- },
123
- children: /* @__PURE__ */ jsx(
124
- Typography,
125
- {
126
- textColor: values.isScheduled ? "primary600" : "neutral800",
127
- fontWeight: values.isScheduled ? "semiBold" : "regular",
128
- children: formatMessage({
129
- id: "modal.form.input.label.schedule-release",
130
- defaultMessage: "Schedule release"
131
- })
132
- }
133
- )
134
- }
135
- ) }),
136
- values.isScheduled && /* @__PURE__ */ jsxs(Fragment, { children: [
137
- /* @__PURE__ */ jsxs(Flex, { gap: 4, alignItems: "start", children: [
138
- /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
139
- DatePicker,
140
- {
141
- label: formatMessage({
142
- id: "content-releases.modal.form.input.label.date",
143
- defaultMessage: "Date"
144
- }),
145
- name: "date",
146
- error: errors.date,
147
- onChange: (date) => {
148
- const isoFormatDate = date ? formatISO(date, { representation: "date" }) : null;
149
- setFieldValue("date", isoFormatDate);
150
- },
151
- clearLabel: formatMessage({
152
- id: "content-releases.modal.form.input.clearLabel",
153
- defaultMessage: "Clear"
154
- }),
155
- onClear: () => {
99
+ children: ({ values, errors, handleChange, setFieldValue }) => {
100
+ return /* @__PURE__ */ jsxs(Form, { children: [
101
+ /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
102
+ /* @__PURE__ */ jsxs(
103
+ Field.Root,
104
+ {
105
+ name: "name",
106
+ error: errors.name && formatMessage({ id: errors.name, defaultMessage: errors.name }),
107
+ required: true,
108
+ children: [
109
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
110
+ id: "content-releases.modal.form.input.label.release-name",
111
+ defaultMessage: "Name"
112
+ }) }),
113
+ /* @__PURE__ */ jsx(TextInput, { value: values.name, onChange: handleChange }),
114
+ /* @__PURE__ */ jsx(Field.Error, {})
115
+ ]
116
+ }
117
+ ),
118
+ /* @__PURE__ */ jsx(Box, { width: "max-content", children: /* @__PURE__ */ jsx(
119
+ Checkbox,
120
+ {
121
+ name: "isScheduled",
122
+ checked: values.isScheduled,
123
+ onCheckedChange: (checked) => {
124
+ setFieldValue("isScheduled", checked);
125
+ if (!checked) {
156
126
  setFieldValue("date", null);
157
- },
158
- selectedDate: values.date || void 0,
159
- required: true,
160
- minDate: utcToZonedTime(/* @__PURE__ */ new Date(), values.timezone.split("&")[1])
161
- }
162
- ) }),
163
- /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
164
- TimePicker,
165
- {
166
- label: formatMessage({
167
- id: "content-releases.modal.form.input.label.time",
168
- defaultMessage: "Time"
169
- }),
170
- name: "time",
171
- error: errors.time,
172
- onChange: (time) => {
173
- setFieldValue("time", time);
174
- },
175
- clearLabel: formatMessage({
176
- id: "content-releases.modal.form.input.clearLabel",
177
- defaultMessage: "Clear"
178
- }),
179
- onClear: () => {
180
127
  setFieldValue("time", "");
181
- },
182
- value: values.time || void 0,
183
- required: true
184
- }
185
- ) })
186
- ] }),
187
- /* @__PURE__ */ jsx(TimezoneComponent, { timezoneOptions: timezoneList })
188
- ] })
189
- ] }) }),
190
- /* @__PURE__ */ jsx(
191
- ModalFooter,
192
- {
193
- startActions: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }),
194
- endActions: /* @__PURE__ */ jsx(Button, { name: "submit", loading: isLoading, type: "submit", children: formatMessage(
128
+ setFieldValue("timezone", null);
129
+ } else {
130
+ setFieldValue("date", initialValues.date);
131
+ setFieldValue("time", initialValues.time);
132
+ setFieldValue(
133
+ "timezone",
134
+ initialValues.timezone ?? systemTimezone?.value
135
+ );
136
+ }
137
+ },
138
+ children: /* @__PURE__ */ jsx(
139
+ Typography,
140
+ {
141
+ textColor: values.isScheduled ? "primary600" : "neutral800",
142
+ fontWeight: values.isScheduled ? "semiBold" : "regular",
143
+ children: formatMessage({
144
+ id: "modal.form.input.label.schedule-release",
145
+ defaultMessage: "Schedule release"
146
+ })
147
+ }
148
+ )
149
+ }
150
+ ) }),
151
+ values.isScheduled && /* @__PURE__ */ jsxs(Fragment, { children: [
152
+ /* @__PURE__ */ jsxs(Flex, { gap: 4, alignItems: "start", children: [
153
+ /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsxs(
154
+ Field.Root,
155
+ {
156
+ name: "date",
157
+ error: errors.date && formatMessage({ id: errors.date, defaultMessage: errors.date }),
158
+ required: true,
159
+ children: [
160
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
161
+ id: "content-releases.modal.form.input.label.date",
162
+ defaultMessage: "Date"
163
+ }) }),
164
+ /* @__PURE__ */ jsx(
165
+ DatePicker,
166
+ {
167
+ onChange: (date) => {
168
+ const isoFormatDate = date ? formatISO(date, { representation: "date" }) : null;
169
+ setFieldValue("date", isoFormatDate);
170
+ },
171
+ clearLabel: formatMessage({
172
+ id: "content-releases.modal.form.input.clearLabel",
173
+ defaultMessage: "Clear"
174
+ }),
175
+ onClear: () => {
176
+ setFieldValue("date", null);
177
+ },
178
+ value: values.date ? new Date(values.date) : /* @__PURE__ */ new Date(),
179
+ minDate: utcToZonedTime(/* @__PURE__ */ new Date(), values.timezone.split("&")[1])
180
+ }
181
+ ),
182
+ /* @__PURE__ */ jsx(Field.Error, {})
183
+ ]
184
+ }
185
+ ) }),
186
+ /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsxs(
187
+ Field.Root,
188
+ {
189
+ name: "time",
190
+ error: errors.time && formatMessage({ id: errors.time, defaultMessage: errors.time }),
191
+ required: true,
192
+ children: [
193
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
194
+ id: "content-releases.modal.form.input.label.time",
195
+ defaultMessage: "Time"
196
+ }) }),
197
+ /* @__PURE__ */ jsx(
198
+ TimePicker,
199
+ {
200
+ onChange: (time) => {
201
+ setFieldValue("time", time);
202
+ },
203
+ clearLabel: formatMessage({
204
+ id: "content-releases.modal.form.input.clearLabel",
205
+ defaultMessage: "Clear"
206
+ }),
207
+ onClear: () => {
208
+ setFieldValue("time", "");
209
+ },
210
+ value: values.time || void 0
211
+ }
212
+ ),
213
+ /* @__PURE__ */ jsx(Field.Error, {})
214
+ ]
215
+ }
216
+ ) })
217
+ ] }),
218
+ /* @__PURE__ */ jsx(TimezoneComponent, { timezoneOptions: timezoneList })
219
+ ] })
220
+ ] }) }),
221
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
222
+ /* @__PURE__ */ jsx(Modal.Close, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }) }),
223
+ /* @__PURE__ */ jsx(Button, { name: "submit", loading: isLoading, type: "submit", children: formatMessage(
195
224
  {
196
225
  id: "content-releases.modal.form.button.submit",
197
226
  defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
198
227
  },
199
228
  { isCreatingRelease }
200
229
  ) })
201
- }
202
- )
203
- ] })
230
+ ] })
231
+ ] });
232
+ }
204
233
  }
205
234
  )
206
- ] });
207
- };
208
- const getTimezones = (selectedDate) => {
209
- const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
210
- const utcOffset = getTimezoneOffset(timezone, selectedDate);
211
- return { offset: utcOffset, value: `${utcOffset}&${timezone}` };
212
- });
213
- const systemTimezone = timezoneList.find(
214
- (timezone) => timezone.value.split("&")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
215
- );
216
- return { timezoneList, systemTimezone };
235
+ ] }) });
217
236
  };
218
237
  const TimezoneComponent = ({ timezoneOptions }) => {
219
238
  const { values, errors, setFieldValue } = useFormikContext();
@@ -229,32 +248,44 @@ const TimezoneComponent = ({ timezoneOptions }) => {
229
248
  }
230
249
  }
231
250
  }, [setFieldValue, values.date, values.timezone]);
232
- return /* @__PURE__ */ jsx(
233
- Combobox,
251
+ return /* @__PURE__ */ jsxs(
252
+ Field.Root,
234
253
  {
235
- label: formatMessage({
236
- id: "content-releases.modal.form.input.label.timezone",
237
- defaultMessage: "Timezone"
238
- }),
239
- autocomplete: { type: "list", filter: "contains" },
240
254
  name: "timezone",
241
- value: values.timezone || void 0,
242
- textValue: values.timezone ? values.timezone.replace(/&/, " ") : void 0,
243
- onChange: (timezone) => {
244
- setFieldValue("timezone", timezone);
245
- },
246
- onTextValueChange: (timezone) => {
247
- setFieldValue("timezone", timezone);
248
- },
249
- onClear: () => {
250
- setFieldValue("timezone", "");
251
- },
252
- error: errors.timezone,
255
+ error: errors.timezone && formatMessage({ id: errors.timezone, defaultMessage: errors.timezone }),
253
256
  required: true,
254
- children: timezoneList.map((timezone) => /* @__PURE__ */ jsx(ComboboxOption, { value: timezone.value, children: timezone.value.replace(/&/, " ") }, timezone.value))
257
+ children: [
258
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
259
+ id: "content-releases.modal.form.input.label.timezone",
260
+ defaultMessage: "Timezone"
261
+ }) }),
262
+ /* @__PURE__ */ jsx(
263
+ Combobox,
264
+ {
265
+ autocomplete: { type: "list", filter: "contains" },
266
+ value: values.timezone || void 0,
267
+ textValue: values.timezone ? values.timezone.replace(/&/, " ") : void 0,
268
+ onChange: (timezone) => {
269
+ setFieldValue("timezone", timezone);
270
+ },
271
+ onTextValueChange: (timezone) => {
272
+ setFieldValue("timezone", timezone);
273
+ },
274
+ onClear: () => {
275
+ setFieldValue("timezone", "");
276
+ },
277
+ children: timezoneList.map((timezone) => /* @__PURE__ */ jsx(ComboboxOption, { value: timezone.value, children: timezone.value.replace(/&/, " ") }, timezone.value))
278
+ }
279
+ ),
280
+ /* @__PURE__ */ jsx(Field.Error, {})
281
+ ]
255
282
  }
256
283
  );
257
284
  };
285
+ const useTypedDispatch = useDispatch;
286
+ const isBaseQueryError = (error) => {
287
+ return typeof error !== "undefined" && error.name !== void 0;
288
+ };
258
289
  const LinkCard = styled(Link)`
259
290
  display: block;
260
291
  `;
@@ -292,7 +323,7 @@ const getBadgeProps = (status) => {
292
323
  const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
293
324
  const { formatMessage } = useIntl();
294
325
  if (isError) {
295
- return /* @__PURE__ */ jsx(AnErrorOccurred, {});
326
+ return /* @__PURE__ */ jsx(Page.Error, {});
296
327
  }
297
328
  if (releases?.length === 0) {
298
329
  return /* @__PURE__ */ jsx(
@@ -307,11 +338,11 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
307
338
  target: sectionTitle
308
339
  }
309
340
  ),
310
- icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem" })
341
+ icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "16rem" })
311
342
  }
312
343
  );
313
344
  }
314
- return /* @__PURE__ */ jsx(Grid, { gap: 4, children: releases.map(({ id, name, scheduledAt, status }) => /* @__PURE__ */ jsx(GridItem, { col: 3, s: 6, xs: 12, children: /* @__PURE__ */ jsx(LinkCard, { href: `content-releases/${id}`, isExternal: false, children: /* @__PURE__ */ jsxs(
345
+ return /* @__PURE__ */ jsx(Grid.Root, { gap: 4, children: releases.map(({ id, name, scheduledAt, status }) => /* @__PURE__ */ jsx(Grid.Item, { col: 3, s: 6, xs: 12, direction: "column", alignItems: "stretch", children: /* @__PURE__ */ jsx(LinkCard, { tag: NavLink, to: `${id}`, isExternal: false, children: /* @__PURE__ */ jsxs(
315
346
  Flex,
316
347
  {
317
348
  direction: "column",
@@ -326,7 +357,7 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
326
357
  gap: 4,
327
358
  children: [
328
359
  /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "start", gap: 1, children: [
329
- /* @__PURE__ */ jsx(Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
360
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", tag: "h3", variant: "delta", fontWeight: "bold", children: name }),
330
361
  /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: scheduledAt ? /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
331
362
  id: "content-releases.pages.Releases.not-scheduled",
332
363
  defaultMessage: "Not scheduled"
@@ -347,33 +378,35 @@ const StyledAlert = styled(Alert)`
347
378
  `;
348
379
  const INITIAL_FORM_VALUES = {
349
380
  name: "",
350
- date: null,
381
+ date: format(/* @__PURE__ */ new Date(), "yyyy-MM-dd"),
351
382
  time: "",
352
383
  isScheduled: true,
353
384
  scheduledAt: null,
354
385
  timezone: null
355
386
  };
356
387
  const ReleasesPage = () => {
357
- const tabRef = React.useRef(null);
358
388
  const location = useLocation();
359
389
  const [releaseModalShown, setReleaseModalShown] = React.useState(false);
360
- const toggleNotification = useNotification();
390
+ const { toggleNotification } = useNotification();
361
391
  const { formatMessage } = useIntl();
362
- const { push, replace } = useHistory();
392
+ const navigate = useNavigate();
363
393
  const { formatAPIError } = useAPIErrorHandler();
364
394
  const [{ query }, setQuery] = useQueryParams();
365
395
  const response = useGetReleasesQuery(query);
396
+ const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();
366
397
  const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();
367
398
  const { getFeature } = useLicenseLimits();
368
399
  const { maximumReleases = 3 } = getFeature("cms-content-releases");
369
400
  const { trackUsage } = useTracking();
370
- const { isLoading, isSuccess, isError } = response;
401
+ const {
402
+ allowedActions: { canCreate }
403
+ } = useRBAC(PERMISSIONS);
404
+ const { isLoading: isLoadingReleases, isSuccess, isError } = response;
371
405
  const activeTab = response?.currentData?.meta?.activeTab || "pending";
372
- const activeTabIndex = ["pending", "done"].indexOf(activeTab);
373
406
  React.useEffect(() => {
374
407
  if (location?.state?.errors) {
375
408
  toggleNotification({
376
- type: "warning",
409
+ type: "danger",
377
410
  title: formatMessage({
378
411
  id: "content-releases.pages.Releases.notification.error.title",
379
412
  defaultMessage: "Your request could not be processed."
@@ -383,30 +416,25 @@ const ReleasesPage = () => {
383
416
  defaultMessage: "Please try again or open another release."
384
417
  })
385
418
  });
386
- replace({ state: null });
419
+ navigate("", { replace: true, state: null });
387
420
  }
388
- }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
389
- React.useEffect(() => {
390
- if (tabRef.current) {
391
- tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
392
- }
393
- }, [activeTabIndex]);
421
+ }, [formatMessage, location?.state?.errors, navigate, toggleNotification]);
394
422
  const toggleAddReleaseModal = () => {
395
423
  setReleaseModalShown((prev) => !prev);
396
424
  };
397
- if (isLoading) {
398
- return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
425
+ if (isLoadingReleases || isLoadingSettings) {
426
+ return /* @__PURE__ */ jsx(Page.Loading, {});
399
427
  }
400
428
  const totalPendingReleases = isSuccess && response.currentData?.meta?.pendingReleasesCount || 0;
401
429
  const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
402
- const handleTabChange = (index) => {
430
+ const handleTabChange = (tabValue) => {
403
431
  setQuery({
404
432
  ...query,
405
433
  page: 1,
406
434
  pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
407
435
  filters: {
408
436
  releasedAt: {
409
- $notNull: index === 0 ? false : true
437
+ $notNull: tabValue !== "pending"
410
438
  }
411
439
  }
412
440
  });
@@ -426,22 +454,22 @@ const ReleasesPage = () => {
426
454
  })
427
455
  });
428
456
  trackUsage("didCreateRelease");
429
- push(`/plugins/content-releases/${response2.data.data.id}`);
430
- } else if (isAxiosError(response2.error)) {
457
+ navigate(response2.data.data.id.toString());
458
+ } else if (isFetchError(response2.error)) {
431
459
  toggleNotification({
432
- type: "warning",
460
+ type: "danger",
433
461
  message: formatAPIError(response2.error)
434
462
  });
435
463
  } else {
436
464
  toggleNotification({
437
- type: "warning",
465
+ type: "danger",
438
466
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
439
467
  });
440
468
  }
441
469
  };
442
- return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoading, children: [
470
+ return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingReleases || isLoadingSettings, children: [
443
471
  /* @__PURE__ */ jsx(
444
- HeaderLayout,
472
+ Layouts.Header,
445
473
  {
446
474
  title: formatMessage({
447
475
  id: "content-releases.pages.Releases.title",
@@ -451,7 +479,7 @@ const ReleasesPage = () => {
451
479
  id: "content-releases.pages.Releases.header-subtitle",
452
480
  defaultMessage: "Create and manage content updates"
453
481
  }),
454
- primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(
482
+ primaryAction: canCreate ? /* @__PURE__ */ jsx(
455
483
  Button,
456
484
  {
457
485
  startIcon: /* @__PURE__ */ jsx(Plus, {}),
@@ -462,10 +490,10 @@ const ReleasesPage = () => {
462
490
  defaultMessage: "New release"
463
491
  })
464
492
  }
465
- ) })
493
+ ) : null
466
494
  }
467
495
  ),
468
- /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
496
+ /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
469
497
  hasReachedMaximumPendingReleases && /* @__PURE__ */ jsx(
470
498
  StyledAlert,
471
499
  {
@@ -490,21 +518,17 @@ const ReleasesPage = () => {
490
518
  })
491
519
  }
492
520
  ),
493
- /* @__PURE__ */ jsxs(
494
- TabGroup,
495
- {
496
- label: formatMessage({
497
- id: "content-releases.pages.Releases.tab-group.label",
498
- defaultMessage: "Releases list"
499
- }),
500
- variant: "simple",
501
- initialSelectedTabIndex: activeTabIndex,
502
- onTabChange: handleTabChange,
503
- ref: tabRef,
504
- children: [
505
- /* @__PURE__ */ jsxs(Box, { paddingBottom: 8, children: [
506
- /* @__PURE__ */ jsxs(Tabs, { children: [
507
- /* @__PURE__ */ jsx(Tab, { children: formatMessage(
521
+ /* @__PURE__ */ jsxs(Tabs.Root, { variant: "simple", onValueChange: handleTabChange, value: activeTab, children: [
522
+ /* @__PURE__ */ jsxs(Box, { paddingBottom: 8, children: [
523
+ /* @__PURE__ */ jsxs(
524
+ Tabs.List,
525
+ {
526
+ "aria-label": formatMessage({
527
+ id: "content-releases.pages.Releases.tab-group.label",
528
+ defaultMessage: "Releases list"
529
+ }),
530
+ children: [
531
+ /* @__PURE__ */ jsx(Tabs.Trigger, { value: "pending", children: formatMessage(
508
532
  {
509
533
  id: "content-releases.pages.Releases.tab.pending",
510
534
  defaultMessage: "Pending ({count})"
@@ -513,59 +537,55 @@ const ReleasesPage = () => {
513
537
  count: totalPendingReleases
514
538
  }
515
539
  ) }),
516
- /* @__PURE__ */ jsx(Tab, { children: formatMessage({
540
+ /* @__PURE__ */ jsx(Tabs.Trigger, { value: "done", children: formatMessage({
517
541
  id: "content-releases.pages.Releases.tab.done",
518
542
  defaultMessage: "Done"
519
543
  }) })
520
- ] }),
521
- /* @__PURE__ */ jsx(Divider, {})
522
- ] }),
523
- /* @__PURE__ */ jsxs(TabPanels, { children: [
524
- /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
525
- ReleasesGrid,
526
- {
527
- sectionTitle: "pending",
528
- releases: response?.currentData?.data,
529
- isError
530
- }
531
- ) }),
532
- /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
533
- ReleasesGrid,
534
- {
535
- sectionTitle: "done",
536
- releases: response?.currentData?.data,
537
- isError
538
- }
539
- ) })
540
- ] })
541
- ]
542
- }
543
- ),
544
- response.currentData?.meta?.pagination?.total ? /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
545
- /* @__PURE__ */ jsx(
546
- PageSizeURLQuery,
544
+ ]
545
+ }
546
+ ),
547
+ /* @__PURE__ */ jsx(Divider, {})
548
+ ] }),
549
+ /* @__PURE__ */ jsx(Tabs.Content, { value: "pending", children: /* @__PURE__ */ jsx(
550
+ ReleasesGrid,
547
551
  {
548
- options: ["8", "16", "32", "64"],
549
- defaultValue: response?.currentData?.meta?.pagination?.pageSize.toString()
552
+ sectionTitle: "pending",
553
+ releases: response?.currentData?.data,
554
+ isError
550
555
  }
551
- ),
552
- /* @__PURE__ */ jsx(
553
- PaginationURLQuery,
556
+ ) }),
557
+ /* @__PURE__ */ jsx(Tabs.Content, { value: "done", children: /* @__PURE__ */ jsx(
558
+ ReleasesGrid,
554
559
  {
555
- pagination: {
556
- pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
557
- }
560
+ sectionTitle: "done",
561
+ releases: response?.currentData?.data,
562
+ isError
558
563
  }
559
- )
560
- ] }) : null
564
+ ) })
565
+ ] }),
566
+ /* @__PURE__ */ jsxs(
567
+ Pagination.Root,
568
+ {
569
+ ...response?.currentData?.meta?.pagination,
570
+ defaultPageSize: response?.currentData?.meta?.pagination?.pageSize,
571
+ children: [
572
+ /* @__PURE__ */ jsx(Pagination.PageSize, { options: ["8", "16", "32", "64"] }),
573
+ /* @__PURE__ */ jsx(Pagination.Links, {})
574
+ ]
575
+ }
576
+ )
561
577
  ] }) }),
562
- releaseModalShown && /* @__PURE__ */ jsx(
578
+ /* @__PURE__ */ jsx(
563
579
  ReleaseModal,
564
580
  {
581
+ open: releaseModalShown,
565
582
  handleClose: toggleAddReleaseModal,
566
583
  handleSubmit: handleAddRelease,
567
584
  isLoading: isSubmittingForm,
568
- initialValues: INITIAL_FORM_VALUES
585
+ initialValues: {
586
+ ...INITIAL_FORM_VALUES,
587
+ timezone: data?.data.defaultTimezone ? data.data.defaultTimezone.split("&")[1] : null
588
+ }
569
589
  }
570
590
  )
571
591
  ] });
@@ -576,7 +596,7 @@ const ReleaseInfoWrapper = styled(Flex)`
576
596
  border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
577
597
  border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
578
598
  `;
579
- const StyledMenuItem = styled(Menu.Item)`
599
+ const StyledMenuItem = styled(MenuItem)`
580
600
  svg path {
581
601
  fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
582
602
  }
@@ -585,7 +605,7 @@ const StyledMenuItem = styled(Menu.Item)`
585
605
  }
586
606
 
587
607
  &:hover {
588
- background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
608
+ background: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}100`]};
589
609
  }
590
610
  `;
591
611
  const PencilIcon = styled(Pencil)`
@@ -605,40 +625,75 @@ const TrashIcon = styled(Trash)`
605
625
  const TypographyMaxWidth = styled(Typography)`
606
626
  max-width: 300px;
607
627
  `;
608
- const EntryValidationText = ({ action, schema, components, entry }) => {
628
+ const EntryValidationText = ({ action, schema, entry, status }) => {
609
629
  const { formatMessage } = useIntl();
610
- const { validate } = unstable_useDocument();
611
- const { errors } = validate(entry, {
612
- contentType: schema,
613
- components,
614
- isCreatingEntry: false
615
- });
616
- if (Object.keys(errors).length > 0) {
617
- const validationErrorsMessages = Object.entries(errors).map(
618
- ([key, value]) => formatMessage(
619
- { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
620
- { field: key }
621
- )
622
- ).join(" ");
623
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
624
- /* @__PURE__ */ jsx(Icon, { color: "danger600", as: CrossCircle }),
625
- /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
626
- ] });
630
+ const { validate, isLoading } = unstable_useDocument(
631
+ {
632
+ collectionType: schema?.kind ?? "",
633
+ model: schema?.uid ?? ""
634
+ },
635
+ {
636
+ // 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
637
+ skip: true
638
+ }
639
+ );
640
+ if (isLoading) {
641
+ return null;
627
642
  }
628
- if (action == "publish") {
629
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
630
- /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
631
- entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
632
- id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
633
- defaultMessage: "Already published"
634
- }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
635
- id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
636
- defaultMessage: "Ready to publish"
637
- }) })
638
- ] });
643
+ const errors = validate(entry) ?? {};
644
+ if (action === "publish") {
645
+ if (Object.keys(errors).length > 0) {
646
+ const validationErrorsMessages = Object.entries(errors).map(
647
+ ([key, value]) => formatMessage(
648
+ // @ts-expect-error – TODO: fix this will better checks
649
+ { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
650
+ { field: key }
651
+ )
652
+ ).join(" ");
653
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
654
+ /* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
655
+ /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(
656
+ TypographyMaxWidth,
657
+ {
658
+ textColor: "danger600",
659
+ variant: "omega",
660
+ fontWeight: "semiBold",
661
+ ellipsis: true,
662
+ children: validationErrorsMessages
663
+ }
664
+ ) })
665
+ ] });
666
+ }
667
+ if (status === "draft") {
668
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
669
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
670
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
671
+ id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
672
+ defaultMessage: "Ready to publish"
673
+ }) })
674
+ ] });
675
+ }
676
+ if (status === "modified") {
677
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
678
+ /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
679
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
680
+ id: "content-releases.pages.ReleaseDetails.entry-validation.modified",
681
+ defaultMessage: "Ready to publish changes"
682
+ }) })
683
+ ] });
684
+ }
685
+ if (status === "published") {
686
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
687
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
688
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
689
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
690
+ defaultMessage: "Already published"
691
+ }) })
692
+ ] });
693
+ }
639
694
  }
640
695
  return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
641
- /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
696
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
642
697
  !entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
643
698
  id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
644
699
  defaultMessage: "Already unpublished"
@@ -658,20 +713,23 @@ const ReleaseDetailsLayout = ({
658
713
  const {
659
714
  data,
660
715
  isLoading: isLoadingDetails,
661
- isError,
662
716
  error
663
- } = useGetReleaseQuery({ id: releaseId });
717
+ } = useGetReleaseQuery(
718
+ { id: releaseId },
719
+ {
720
+ skip: !releaseId
721
+ }
722
+ );
664
723
  const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();
665
- const toggleNotification = useNotification();
724
+ const { toggleNotification } = useNotification();
666
725
  const { formatAPIError } = useAPIErrorHandler();
667
- const {
668
- allowedActions: { canUpdate, canDelete }
669
- } = useRBAC(PERMISSIONS);
726
+ const { allowedActions } = useRBAC(PERMISSIONS);
727
+ const { canUpdate, canDelete, canPublish } = allowedActions;
670
728
  const dispatch = useTypedDispatch();
671
729
  const { trackUsage } = useTracking();
672
730
  const release = data?.data;
673
- const handlePublishRelease = async () => {
674
- const response = await publishRelease({ id: releaseId });
731
+ const handlePublishRelease = (id) => async () => {
732
+ const response = await publishRelease({ id });
675
733
  if ("data" in response) {
676
734
  toggleNotification({
677
735
  type: "success",
@@ -686,14 +744,14 @@ const ReleaseDetailsLayout = ({
686
744
  totalPublishedEntries,
687
745
  totalUnpublishedEntries
688
746
  });
689
- } else if (isAxiosError(response.error)) {
747
+ } else if (isFetchError(response.error)) {
690
748
  toggleNotification({
691
- type: "warning",
749
+ type: "danger",
692
750
  message: formatAPIError(response.error)
693
751
  });
694
752
  } else {
695
753
  toggleNotification({
696
- type: "warning",
754
+ type: "danger",
697
755
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
698
756
  });
699
757
  }
@@ -719,21 +777,20 @@ const ReleaseDetailsLayout = ({
719
777
  return release.createdBy.email;
720
778
  };
721
779
  if (isLoadingDetails) {
722
- return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
780
+ return /* @__PURE__ */ jsx(Page.Loading, {});
723
781
  }
724
- if (isError || !release) {
782
+ if (isBaseQueryError(error) && "code" in error || !release) {
725
783
  return /* @__PURE__ */ jsx(
726
- Redirect,
784
+ Navigate,
727
785
  {
728
- to: {
729
- pathname: "/plugins/content-releases",
730
- state: {
731
- errors: [
732
- {
733
- code: error?.code
734
- }
735
- ]
736
- }
786
+ to: "..",
787
+ state: {
788
+ errors: [
789
+ {
790
+ // @ts-expect-error – TODO: fix this weird error flow
791
+ code: error?.code
792
+ }
793
+ ]
737
794
  }
738
795
  }
739
796
  );
@@ -770,106 +827,90 @@ const ReleaseDetailsLayout = ({
770
827
  ) : "";
771
828
  return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
772
829
  /* @__PURE__ */ jsx(
773
- HeaderLayout,
830
+ Layouts.Header,
774
831
  {
775
832
  title: release.name,
776
833
  subtitle: /* @__PURE__ */ jsxs(Flex, { gap: 2, lineHeight: 6, children: [
777
834
  /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", variant: "epsilon", children: numberOfEntriesText + (isScheduled ? ` - ${scheduledText}` : "") }),
778
835
  /* @__PURE__ */ jsx(Badge, { ...getBadgeProps(release.status), children: release.status })
779
836
  ] }),
780
- navigationAction: /* @__PURE__ */ jsx(Link$1, { startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
781
- id: "global.back",
782
- defaultMessage: "Back"
783
- }) }),
837
+ navigationAction: /* @__PURE__ */ jsx(BackButton, {}),
784
838
  primaryAction: !release.releasedAt && /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
785
- /* @__PURE__ */ jsxs(Menu.Root, { children: [
786
- /* @__PURE__ */ jsx(
787
- Menu.Trigger,
788
- {
789
- as: IconButton,
790
- paddingLeft: 2,
791
- paddingRight: 2,
792
- "aria-label": formatMessage({
793
- id: "content-releases.header.actions.open-release-actions",
794
- defaultMessage: "Release edit and delete menu"
795
- }),
796
- icon: /* @__PURE__ */ jsx(More, {}),
797
- variant: "tertiary"
798
- }
799
- ),
800
- /* @__PURE__ */ jsxs(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: [
801
- /* @__PURE__ */ jsxs(
802
- Flex,
803
- {
804
- alignItems: "center",
805
- justifyContent: "center",
806
- direction: "column",
807
- padding: 1,
808
- width: "100%",
809
- children: [
810
- /* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
811
- /* @__PURE__ */ jsx(PencilIcon, {}),
812
- /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
813
- id: "content-releases.header.actions.edit",
814
- defaultMessage: "Edit"
839
+ /* @__PURE__ */ jsxs(
840
+ SimpleMenuButton,
841
+ {
842
+ label: /* @__PURE__ */ jsx(More, {}),
843
+ variant: "tertiary",
844
+ endIcon: null,
845
+ paddingLeft: "7px",
846
+ paddingRight: "7px",
847
+ "aria-label": formatMessage({
848
+ id: "content-releases.header.actions.open-release-actions",
849
+ defaultMessage: "Release edit and delete menu"
850
+ }),
851
+ popoverPlacement: "bottom-end",
852
+ children: [
853
+ /* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
854
+ /* @__PURE__ */ jsx(PencilIcon, {}),
855
+ /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
856
+ id: "content-releases.header.actions.edit",
857
+ defaultMessage: "Edit"
858
+ }) })
859
+ ] }) }),
860
+ /* @__PURE__ */ jsx(
861
+ StyledMenuItem,
862
+ {
863
+ disabled: !canDelete,
864
+ onSelect: toggleWarningSubmit,
865
+ $variant: "danger",
866
+ children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
867
+ /* @__PURE__ */ jsx(TrashIcon, {}),
868
+ /* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
869
+ id: "content-releases.header.actions.delete",
870
+ defaultMessage: "Delete"
815
871
  }) })
816
- ] }) }),
817
- /* @__PURE__ */ jsx(
818
- StyledMenuItem,
819
- {
820
- disabled: !canDelete,
821
- onSelect: toggleWarningSubmit,
822
- variant: "danger",
823
- children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
824
- /* @__PURE__ */ jsx(TrashIcon, {}),
825
- /* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
826
- id: "content-releases.header.actions.delete",
827
- defaultMessage: "Delete"
828
- }) })
829
- ] })
830
- }
831
- )
832
- ]
833
- }
834
- ),
835
- /* @__PURE__ */ jsxs(
836
- ReleaseInfoWrapper,
837
- {
838
- direction: "column",
839
- justifyContent: "center",
840
- alignItems: "flex-start",
841
- gap: 1,
842
- padding: 5,
843
- children: [
844
- /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
845
- id: "content-releases.header.actions.created",
846
- defaultMessage: "Created"
847
- }) }),
848
- /* @__PURE__ */ jsxs(Typography, { variant: "pi", color: "neutral300", children: [
849
- /* @__PURE__ */ jsx(RelativeTime$1, { timestamp: new Date(release.createdAt) }),
850
- formatMessage(
851
- {
852
- id: "content-releases.header.actions.created.description",
853
- defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
854
- },
855
- { createdBy: getCreatedByUser(), hasCreatedByUser }
856
- )
857
872
  ] })
858
- ]
859
- }
860
- )
861
- ] })
862
- ] }),
873
+ }
874
+ ),
875
+ /* @__PURE__ */ jsxs(
876
+ ReleaseInfoWrapper,
877
+ {
878
+ direction: "column",
879
+ justifyContent: "center",
880
+ alignItems: "flex-start",
881
+ gap: 1,
882
+ padding: 5,
883
+ children: [
884
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
885
+ id: "content-releases.header.actions.created",
886
+ defaultMessage: "Created"
887
+ }) }),
888
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", color: "neutral300", children: [
889
+ /* @__PURE__ */ jsx(RelativeTime$1, { timestamp: new Date(release.createdAt) }),
890
+ formatMessage(
891
+ {
892
+ id: "content-releases.header.actions.created.description",
893
+ defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
894
+ },
895
+ { createdBy: getCreatedByUser(), hasCreatedByUser }
896
+ )
897
+ ] })
898
+ ]
899
+ }
900
+ )
901
+ ]
902
+ }
903
+ ),
863
904
  /* @__PURE__ */ jsx(Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
864
905
  id: "content-releases.header.actions.refresh",
865
906
  defaultMessage: "Refresh"
866
907
  }) }),
867
- /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.publish, children: /* @__PURE__ */ jsx(
908
+ canPublish ? /* @__PURE__ */ jsx(
868
909
  Button,
869
910
  {
870
911
  size: "S",
871
912
  variant: "default",
872
- onClick: handlePublishRelease,
913
+ onClick: handlePublishRelease(release.id.toString()),
873
914
  loading: isPublishing,
874
915
  disabled: release.actions.meta.count === 0,
875
916
  children: formatMessage({
@@ -877,14 +918,20 @@ const ReleaseDetailsLayout = ({
877
918
  defaultMessage: "Publish"
878
919
  })
879
920
  }
880
- ) })
921
+ ) : null
881
922
  ] })
882
923
  }
883
924
  ),
884
925
  children
885
926
  ] });
886
927
  };
928
+ const SimpleMenuButton = styled(SimpleMenu)`
929
+ & > span {
930
+ display: flex;
931
+ }
932
+ `;
887
933
  const GROUP_BY_OPTIONS = ["contentType", "locale", "action"];
934
+ const GROUP_BY_OPTIONS_NO_LOCALE = ["contentType", "action"];
888
935
  const getGroupByOptionLabel = (value) => {
889
936
  if (value === "locale") {
890
937
  return {
@@ -903,21 +950,32 @@ const getGroupByOptionLabel = (value) => {
903
950
  defaultMessage: "Content-Types"
904
951
  };
905
952
  };
906
- const ReleaseDetailsBody = () => {
953
+ const ReleaseDetailsBody = ({ releaseId }) => {
907
954
  const { formatMessage } = useIntl();
908
- const { releaseId } = useParams();
909
955
  const [{ query }, setQuery] = useQueryParams();
910
- const toggleNotification = useNotification();
956
+ const { toggleNotification } = useNotification();
911
957
  const { formatAPIError } = useAPIErrorHandler();
912
958
  const {
913
959
  data: releaseData,
914
960
  isLoading: isReleaseLoading,
915
- isError: isReleaseError,
916
961
  error: releaseError
917
962
  } = useGetReleaseQuery({ id: releaseId });
918
963
  const {
919
964
  allowedActions: { canUpdate }
920
965
  } = useRBAC(PERMISSIONS);
966
+ const runHookWaterfall = useStrapiApp("ReleaseDetailsPage", (state) => state.runHookWaterfall);
967
+ const { displayedHeaders, hasI18nEnabled } = runHookWaterfall("ContentReleases/pages/ReleaseDetails/add-locale-in-releases", {
968
+ displayedHeaders: [
969
+ {
970
+ label: {
971
+ id: "content-releases.page.ReleaseDetails.table.header.label.name",
972
+ defaultMessage: "name"
973
+ },
974
+ name: "name"
975
+ }
976
+ ],
977
+ hasI18nEnabled: false
978
+ });
921
979
  const release = releaseData?.data;
922
980
  const selectedGroupBy = query?.groupBy || "contentType";
923
981
  const {
@@ -946,65 +1004,59 @@ const ReleaseDetailsBody = () => {
946
1004
  // We are passing the action path to found the position in the cache of the action for optimistic updates
947
1005
  });
948
1006
  if ("error" in response) {
949
- if (isAxiosError(response.error)) {
1007
+ if (isFetchError(response.error)) {
950
1008
  toggleNotification({
951
- type: "warning",
1009
+ type: "danger",
952
1010
  message: formatAPIError(response.error)
953
1011
  });
954
1012
  } else {
955
1013
  toggleNotification({
956
- type: "warning",
1014
+ type: "danger",
957
1015
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
958
1016
  });
959
1017
  }
960
1018
  }
961
1019
  };
962
1020
  if (isLoading || isReleaseLoading) {
963
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
1021
+ return /* @__PURE__ */ jsx(Page.Loading, {});
964
1022
  }
965
1023
  const releaseActions = data?.data;
966
1024
  const releaseMeta = data?.meta;
967
1025
  const contentTypes = releaseMeta?.contentTypes || {};
968
1026
  const components = releaseMeta?.components || {};
969
- if (isReleaseError || !release) {
1027
+ if (isBaseQueryError(releaseError) || !release) {
970
1028
  const errorsArray = [];
971
- if (releaseError) {
1029
+ if (releaseError && "code" in releaseError) {
972
1030
  errorsArray.push({
973
1031
  code: releaseError.code
974
1032
  });
975
1033
  }
976
- if (releaseActionsError) {
1034
+ if (releaseActionsError && "code" in releaseActionsError) {
977
1035
  errorsArray.push({
978
1036
  code: releaseActionsError.code
979
1037
  });
980
1038
  }
981
1039
  return /* @__PURE__ */ jsx(
982
- Redirect,
1040
+ Navigate,
983
1041
  {
984
- to: {
985
- pathname: "/plugins/content-releases",
986
- state: {
987
- errors: errorsArray
988
- }
1042
+ to: "..",
1043
+ state: {
1044
+ errors: errorsArray
989
1045
  }
990
1046
  }
991
1047
  );
992
1048
  }
993
1049
  if (isError || !releaseActions) {
994
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(AnErrorOccurred, {}) });
1050
+ return /* @__PURE__ */ jsx(Page.Error, {});
995
1051
  }
996
1052
  if (Object.keys(releaseActions).length === 0) {
997
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(
998
- NoContent,
1053
+ return /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsx(
1054
+ EmptyStateLayout,
999
1055
  {
1000
- content: {
1001
- id: "content-releases.pages.Details.tab.emptyEntries",
1002
- defaultMessage: "This release is empty. Open the Content Manager, select an entry and add it to the release."
1003
- },
1004
1056
  action: /* @__PURE__ */ jsx(
1005
1057
  LinkButton,
1006
1058
  {
1007
- as: Link$2,
1059
+ tag: Link$1,
1008
1060
  to: {
1009
1061
  pathname: "/content-manager"
1010
1062
  },
@@ -1015,18 +1067,52 @@ const ReleaseDetailsBody = () => {
1015
1067
  defaultMessage: "Open the Content Manager"
1016
1068
  })
1017
1069
  }
1018
- )
1070
+ ),
1071
+ icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "16rem" }),
1072
+ content: formatMessage({
1073
+ id: "content-releases.pages.Details.tab.emptyEntries",
1074
+ defaultMessage: "This release is empty. Open the Content Manager, select an entry and add it to the release."
1075
+ })
1019
1076
  }
1020
1077
  ) });
1021
1078
  }
1022
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
1079
+ const groupByLabel = formatMessage({
1080
+ id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
1081
+ defaultMessage: "Group by"
1082
+ });
1083
+ const headers = [
1084
+ ...displayedHeaders,
1085
+ {
1086
+ label: {
1087
+ id: "content-releases.page.ReleaseDetails.table.header.label.content-type",
1088
+ defaultMessage: "content-type"
1089
+ },
1090
+ name: "content-type"
1091
+ },
1092
+ {
1093
+ label: {
1094
+ id: "content-releases.page.ReleaseDetails.table.header.label.action",
1095
+ defaultMessage: "action"
1096
+ },
1097
+ name: "action"
1098
+ },
1099
+ ...!release.releasedAt ? [
1100
+ {
1101
+ label: {
1102
+ id: "content-releases.page.ReleaseDetails.table.header.label.status",
1103
+ defaultMessage: "status"
1104
+ },
1105
+ name: "status"
1106
+ }
1107
+ ] : []
1108
+ ];
1109
+ const options = hasI18nEnabled ? GROUP_BY_OPTIONS : GROUP_BY_OPTIONS_NO_LOCALE;
1110
+ return /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
1023
1111
  /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
1024
1112
  SingleSelect,
1025
1113
  {
1026
- "aria-label": formatMessage({
1027
- id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
1028
- defaultMessage: "Group by"
1029
- }),
1114
+ placeholder: groupByLabel,
1115
+ "aria-label": groupByLabel,
1030
1116
  customizeContent: (value) => formatMessage(
1031
1117
  {
1032
1118
  id: `content-releases.pages.ReleaseDetails.groupBy.label`,
@@ -1038,7 +1124,7 @@ const ReleaseDetailsBody = () => {
1038
1124
  ),
1039
1125
  value: formatMessage(getGroupByOptionLabel(selectedGroupBy)),
1040
1126
  onChange: (value) => setQuery({ groupBy: value }),
1041
- children: GROUP_BY_OPTIONS.map((option) => /* @__PURE__ */ jsx(SingleSelectOption, { value: option, children: formatMessage(getGroupByOptionLabel(option)) }, option))
1127
+ children: options.map((option) => /* @__PURE__ */ jsx(SingleSelectOption, { value: option, children: formatMessage(getGroupByOptionLabel(option)) }, option))
1042
1128
  }
1043
1129
  ) }),
1044
1130
  Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
@@ -1050,72 +1136,15 @@ const ReleaseDetailsBody = () => {
1050
1136
  ...item,
1051
1137
  id: Number(item.entry.id)
1052
1138
  })),
1053
- colCount: releaseActions[key].length,
1054
- isLoading,
1055
- isFetching,
1139
+ headers,
1140
+ isLoading: isLoading || isFetching,
1056
1141
  children: /* @__PURE__ */ jsxs(Table.Content, { children: [
1057
- /* @__PURE__ */ jsxs(Table.Head, { children: [
1058
- /* @__PURE__ */ jsx(
1059
- Table.HeaderCell,
1060
- {
1061
- fieldSchemaType: "string",
1062
- label: formatMessage({
1063
- id: "content-releases.page.ReleaseDetails.table.header.label.name",
1064
- defaultMessage: "name"
1065
- }),
1066
- name: "name"
1067
- }
1068
- ),
1069
- /* @__PURE__ */ jsx(
1070
- Table.HeaderCell,
1071
- {
1072
- fieldSchemaType: "string",
1073
- label: formatMessage({
1074
- id: "content-releases.page.ReleaseDetails.table.header.label.locale",
1075
- defaultMessage: "locale"
1076
- }),
1077
- name: "locale"
1078
- }
1079
- ),
1080
- /* @__PURE__ */ jsx(
1081
- Table.HeaderCell,
1082
- {
1083
- fieldSchemaType: "string",
1084
- label: formatMessage({
1085
- id: "content-releases.page.ReleaseDetails.table.header.label.content-type",
1086
- defaultMessage: "content-type"
1087
- }),
1088
- name: "content-type"
1089
- }
1090
- ),
1091
- /* @__PURE__ */ jsx(
1092
- Table.HeaderCell,
1093
- {
1094
- fieldSchemaType: "string",
1095
- label: formatMessage({
1096
- id: "content-releases.page.ReleaseDetails.table.header.label.action",
1097
- defaultMessage: "action"
1098
- }),
1099
- name: "action"
1100
- }
1101
- ),
1102
- !release.releasedAt && /* @__PURE__ */ jsx(
1103
- Table.HeaderCell,
1104
- {
1105
- fieldSchemaType: "string",
1106
- label: formatMessage({
1107
- id: "content-releases.page.ReleaseDetails.table.header.label.status",
1108
- defaultMessage: "status"
1109
- }),
1110
- name: "status"
1111
- }
1112
- )
1113
- ] }),
1114
- /* @__PURE__ */ jsx(Table.LoadingBody, {}),
1142
+ /* @__PURE__ */ jsx(Table.Head, { children: headers.map(({ label, name }) => /* @__PURE__ */ jsx(Table.HeaderCell, { label: formatMessage(label), name }, name)) }),
1143
+ /* @__PURE__ */ jsx(Table.Loading, {}),
1115
1144
  /* @__PURE__ */ jsx(Table.Body, { children: releaseActions[key].map(
1116
- ({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxs(Tr, { children: [
1145
+ ({ id, contentType, locale, type, entry, status }, actionIndex) => /* @__PURE__ */ jsxs(Tr, { children: [
1117
1146
  /* @__PURE__ */ jsx(Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
1118
- /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
1147
+ hasI18nEnabled && /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
1119
1148
  /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: contentType.displayName || "" }) }),
1120
1149
  /* @__PURE__ */ jsx(Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsx(Typography, { children: formatMessage(
1121
1150
  {
@@ -1142,7 +1171,8 @@ const ReleaseDetailsBody = () => {
1142
1171
  action: type,
1143
1172
  schema: contentTypes?.[contentType.uid],
1144
1173
  components,
1145
- entry
1174
+ entry,
1175
+ status
1146
1176
  }
1147
1177
  ) }),
1148
1178
  /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { children: [
@@ -1150,7 +1180,7 @@ const ReleaseDetailsBody = () => {
1150
1180
  ReleaseActionMenu.ReleaseActionEntryLinkItem,
1151
1181
  {
1152
1182
  contentTypeUid: contentType.uid,
1153
- entryId: entry.id,
1183
+ documentId: entry.documentId,
1154
1184
  locale: locale?.code
1155
1185
  }
1156
1186
  ),
@@ -1169,54 +1199,73 @@ const ReleaseDetailsBody = () => {
1169
1199
  }
1170
1200
  )
1171
1201
  ] }, `releases-group-${key}`)),
1172
- /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
1173
- /* @__PURE__ */ jsx(PageSizeURLQuery, { defaultValue: releaseMeta?.pagination?.pageSize.toString() }),
1174
- /* @__PURE__ */ jsx(
1175
- PaginationURLQuery,
1176
- {
1177
- pagination: {
1178
- pageCount: releaseMeta?.pagination?.pageCount || 0
1179
- }
1180
- }
1181
- )
1182
- ] })
1202
+ /* @__PURE__ */ jsxs(
1203
+ Pagination.Root,
1204
+ {
1205
+ ...releaseMeta?.pagination,
1206
+ defaultPageSize: releaseMeta?.pagination?.pageSize,
1207
+ children: [
1208
+ /* @__PURE__ */ jsx(Pagination.PageSize, {}),
1209
+ /* @__PURE__ */ jsx(Pagination.Links, {})
1210
+ ]
1211
+ }
1212
+ )
1183
1213
  ] }) });
1184
1214
  };
1185
1215
  const ReleaseDetailsPage = () => {
1186
1216
  const { formatMessage } = useIntl();
1187
1217
  const { releaseId } = useParams();
1188
- const toggleNotification = useNotification();
1218
+ const { toggleNotification } = useNotification();
1189
1219
  const { formatAPIError } = useAPIErrorHandler();
1190
- const { replace } = useHistory();
1220
+ const navigate = useNavigate();
1191
1221
  const [releaseModalShown, setReleaseModalShown] = React.useState(false);
1192
1222
  const [showWarningSubmit, setWarningSubmit] = React.useState(false);
1193
1223
  const {
1194
1224
  isLoading: isLoadingDetails,
1195
1225
  data,
1196
1226
  isSuccess: isSuccessDetails
1197
- } = useGetReleaseQuery({ id: releaseId });
1227
+ } = useGetReleaseQuery(
1228
+ { id: releaseId },
1229
+ {
1230
+ skip: !releaseId
1231
+ }
1232
+ );
1233
+ const { data: dataTimezone, isLoading: isLoadingTimezone } = useGetReleaseSettingsQuery();
1198
1234
  const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();
1199
- const [deleteRelease, { isLoading: isDeletingRelease }] = useDeleteReleaseMutation();
1235
+ const [deleteRelease] = useDeleteReleaseMutation();
1200
1236
  const toggleEditReleaseModal = () => {
1201
1237
  setReleaseModalShown((prev) => !prev);
1202
1238
  };
1239
+ const getTimezoneValue = () => {
1240
+ if (releaseData?.timezone) {
1241
+ return releaseData.timezone;
1242
+ } else {
1243
+ if (dataTimezone?.data.defaultTimezone) {
1244
+ return dataTimezone.data.defaultTimezone;
1245
+ }
1246
+ return null;
1247
+ }
1248
+ };
1203
1249
  const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);
1204
- if (isLoadingDetails) {
1250
+ if (isLoadingDetails || isLoadingTimezone) {
1205
1251
  return /* @__PURE__ */ jsx(
1206
1252
  ReleaseDetailsLayout,
1207
1253
  {
1208
1254
  toggleEditReleaseModal,
1209
1255
  toggleWarningSubmit,
1210
- children: /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) })
1256
+ children: /* @__PURE__ */ jsx(Page.Loading, {})
1211
1257
  }
1212
1258
  );
1213
1259
  }
1260
+ if (!releaseId) {
1261
+ return /* @__PURE__ */ jsx(Navigate, { to: ".." });
1262
+ }
1214
1263
  const releaseData = isSuccessDetails && data?.data || null;
1215
1264
  const title = releaseData?.name || "";
1216
- const timezone = releaseData?.timezone ?? null;
1265
+ const timezone = getTimezoneValue();
1217
1266
  const scheduledAt = releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;
1218
- const date = scheduledAt ? format(scheduledAt, "yyyy-MM-dd") : null;
1219
- const time = scheduledAt ? format(scheduledAt, "HH:mm") : "";
1267
+ const date = scheduledAt ? format$1(scheduledAt, "yyyy-MM-dd") : void 0;
1268
+ const time = scheduledAt ? format$1(scheduledAt, "HH:mm") : "";
1220
1269
  const handleEditRelease = async (values) => {
1221
1270
  const response = await updateRelease({
1222
1271
  id: releaseId,
@@ -1233,14 +1282,14 @@ const ReleaseDetailsPage = () => {
1233
1282
  })
1234
1283
  });
1235
1284
  toggleEditReleaseModal();
1236
- } else if (isAxiosError(response.error)) {
1285
+ } else if (isFetchError(response.error)) {
1237
1286
  toggleNotification({
1238
- type: "warning",
1287
+ type: "danger",
1239
1288
  message: formatAPIError(response.error)
1240
1289
  });
1241
1290
  } else {
1242
1291
  toggleNotification({
1243
- type: "warning",
1292
+ type: "danger",
1244
1293
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1245
1294
  });
1246
1295
  }
@@ -1250,15 +1299,15 @@ const ReleaseDetailsPage = () => {
1250
1299
  id: releaseId
1251
1300
  });
1252
1301
  if ("data" in response) {
1253
- replace("/plugins/content-releases");
1254
- } else if (isAxiosError(response.error)) {
1302
+ navigate("..");
1303
+ } else if (isFetchError(response.error)) {
1255
1304
  toggleNotification({
1256
- type: "warning",
1305
+ type: "danger",
1257
1306
  message: formatAPIError(response.error)
1258
1307
  });
1259
1308
  } else {
1260
1309
  toggleNotification({
1261
- type: "warning",
1310
+ type: "danger",
1262
1311
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1263
1312
  });
1264
1313
  }
@@ -1269,10 +1318,11 @@ const ReleaseDetailsPage = () => {
1269
1318
  toggleEditReleaseModal,
1270
1319
  toggleWarningSubmit,
1271
1320
  children: [
1272
- /* @__PURE__ */ jsx(ReleaseDetailsBody, {}),
1273
- releaseModalShown && /* @__PURE__ */ jsx(
1321
+ /* @__PURE__ */ jsx(ReleaseDetailsBody, { releaseId }),
1322
+ /* @__PURE__ */ jsx(
1274
1323
  ReleaseModal,
1275
1324
  {
1325
+ open: releaseModalShown,
1276
1326
  handleClose: toggleEditReleaseModal,
1277
1327
  handleSubmit: handleEditRelease,
1278
1328
  isLoading: isLoadingDetails || isSubmittingForm,
@@ -1286,30 +1336,21 @@ const ReleaseDetailsPage = () => {
1286
1336
  }
1287
1337
  }
1288
1338
  ),
1289
- /* @__PURE__ */ jsx(
1290
- ConfirmDialog,
1291
- {
1292
- bodyText: {
1293
- id: "content-releases.dialog.confirmation-message",
1294
- defaultMessage: "Are you sure you want to delete this release?"
1295
- },
1296
- isOpen: showWarningSubmit,
1297
- isConfirmButtonLoading: isDeletingRelease,
1298
- onToggleDialog: toggleWarningSubmit,
1299
- onConfirm: handleDeleteRelease
1300
- }
1301
- )
1339
+ /* @__PURE__ */ jsx(Dialog.Root, { open: showWarningSubmit, onOpenChange: toggleWarningSubmit, children: /* @__PURE__ */ jsx(ConfirmDialog, { onConfirm: handleDeleteRelease, children: formatMessage({
1340
+ id: "content-releases.dialog.confirmation-message",
1341
+ defaultMessage: "Are you sure you want to delete this release?"
1342
+ }) }) })
1302
1343
  ]
1303
1344
  }
1304
1345
  );
1305
1346
  };
1306
1347
  const App = () => {
1307
- return /* @__PURE__ */ jsx(CheckPagePermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(Switch, { children: [
1308
- /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}`, component: ReleasesPage }),
1309
- /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}/:releaseId`, component: ReleaseDetailsPage })
1348
+ return /* @__PURE__ */ jsx(Page.Protect, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(Routes, { children: [
1349
+ /* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(ReleasesPage, {}) }),
1350
+ /* @__PURE__ */ jsx(Route, { path: ":releaseId", element: /* @__PURE__ */ jsx(ReleaseDetailsPage, {}) })
1310
1351
  ] }) });
1311
1352
  };
1312
1353
  export {
1313
1354
  App
1314
1355
  };
1315
- //# sourceMappingURL=App-x6Tjj3HN.mjs.map
1356
+ //# sourceMappingURL=App-DMILern_.mjs.map