@strapi/content-releases 0.0.0-next.f4ff842a3cb7b83db540bee67554b704e042b042 → 0.0.0-next.f6dca5adf05ef6bed9605a1535999ab0bbbf063e

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 (141) hide show
  1. package/LICENSE +17 -1
  2. package/dist/_chunks/App-BKB1esYS.js +1395 -0
  3. package/dist/_chunks/App-BKB1esYS.js.map +1 -0
  4. package/dist/_chunks/{App-jrh58sXY.mjs → App-Cne--1Z8.mjs} +602 -558
  5. package/dist/_chunks/App-Cne--1Z8.mjs.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-C1WwGWIH.mjs +178 -0
  11. package/dist/_chunks/ReleasesSettingsPage-C1WwGWIH.mjs.map +1 -0
  12. package/dist/_chunks/ReleasesSettingsPage-kuXIwpWp.js +178 -0
  13. package/dist/_chunks/ReleasesSettingsPage-kuXIwpWp.js.map +1 -0
  14. package/dist/_chunks/{en-HrREghh3.js → en-CmYoEnA7.js} +9 -2
  15. package/dist/_chunks/en-CmYoEnA7.js.map +1 -0
  16. package/dist/_chunks/{en-ltT1TlKQ.mjs → en-D0yVZFqf.mjs} +9 -2
  17. package/dist/_chunks/en-D0yVZFqf.mjs.map +1 -0
  18. package/dist/_chunks/index-5Odi61vw.js +1381 -0
  19. package/dist/_chunks/index-5Odi61vw.js.map +1 -0
  20. package/dist/_chunks/index-Cy7qwpaU.mjs +1362 -0
  21. package/dist/_chunks/index-Cy7qwpaU.mjs.map +1 -0
  22. package/dist/_chunks/schemas-BE1LxE9J.js +62 -0
  23. package/dist/_chunks/schemas-BE1LxE9J.js.map +1 -0
  24. package/dist/_chunks/schemas-DdA2ic2U.mjs +44 -0
  25. package/dist/_chunks/schemas-DdA2ic2U.mjs.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 +843 -636
  56. package/dist/server/index.js.map +1 -1
  57. package/dist/server/index.mjs +844 -636
  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 +2115 -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 +1828 -0
  108. package/dist/server/src/services/index.d.ts.map +1 -0
  109. package/dist/server/src/services/release-action.d.ts +38 -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 +34 -39
  130. package/dist/_chunks/App-dLXY5ei3.js +0 -1353
  131. package/dist/_chunks/App-dLXY5ei3.js.map +0 -1
  132. package/dist/_chunks/App-jrh58sXY.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-HrREghh3.js.map +0 -1
  136. package/dist/_chunks/en-ltT1TlKQ.mjs.map +0 -1
  137. package/dist/_chunks/index-CVO0Rqdm.js +0 -1336
  138. package/dist/_chunks/index-CVO0Rqdm.js.map +0 -1
  139. package/dist/_chunks/index-PiOGBETy.mjs +0 -1315
  140. package/dist/_chunks/index-PiOGBETy.mjs.map +0 -1
  141. package/strapi-server.js +0 -3
@@ -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, useStrapiApp, 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-PiOGBETy.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-Cy7qwpaU.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-DdA2ic2U.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,19 +605,19 @@ 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)`
592
- width: ${({ theme }) => theme.spaces[3]};
593
- height: ${({ theme }) => theme.spaces[3]};
612
+ width: ${({ theme }) => theme.spaces[4]};
613
+ height: ${({ theme }) => theme.spaces[4]};
594
614
  path {
595
615
  fill: ${({ theme }) => theme.colors.neutral600};
596
616
  }
597
617
  `;
598
618
  const TrashIcon = styled(Trash)`
599
- width: ${({ theme }) => theme.spaces[3]};
600
- height: ${({ theme }) => theme.spaces[3]};
619
+ width: ${({ theme }) => theme.spaces[4]};
620
+ height: ${({ theme }) => theme.spaces[4]};
601
621
  path {
602
622
  fill: ${({ theme }) => theme.colors.danger600};
603
623
  }
@@ -605,40 +625,93 @@ 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
+ const errorsToString = (errors2, prefix = "") => {
641
+ if (Object.keys(errors2).length === 0) {
642
+ return "";
643
+ }
644
+ return Object.entries(errors2).map(([key, value]) => {
645
+ if (value === void 0 || value === null) {
646
+ return "";
647
+ }
648
+ if (typeof value === "string") {
649
+ return formatMessage(
650
+ { id: value, defaultMessage: value },
651
+ { field: prefix ? `${prefix}.${key}` : key }
652
+ );
653
+ }
654
+ if (typeof value === "object" && value !== null && "id" in value && "defaultMessage" in value) {
655
+ return formatMessage(
656
+ // @ts-expect-error – TODO: default message will be a string
657
+ { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
658
+ { field: prefix ? `${prefix}.${key}` : key }
659
+ );
660
+ }
661
+ return errorsToString(value, key);
662
+ }).join(" ");
663
+ };
664
+ if (isLoading) {
665
+ return null;
627
666
  }
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
- ] });
667
+ const errors = validate(entry) ?? {};
668
+ if (action === "publish") {
669
+ if (Object.keys(errors).length > 0) {
670
+ const validationErrorsMessages = errorsToString(errors);
671
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
672
+ /* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
673
+ /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(
674
+ TypographyMaxWidth,
675
+ {
676
+ textColor: "danger600",
677
+ variant: "omega",
678
+ fontWeight: "semiBold",
679
+ ellipsis: true,
680
+ children: validationErrorsMessages
681
+ }
682
+ ) })
683
+ ] });
684
+ }
685
+ if (status === "draft") {
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.ready-to-publish",
690
+ defaultMessage: "Ready to publish"
691
+ }) })
692
+ ] });
693
+ }
694
+ if (status === "modified") {
695
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
696
+ /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
697
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
698
+ id: "content-releases.pages.ReleaseDetails.entry-validation.modified",
699
+ defaultMessage: "Ready to publish changes"
700
+ }) })
701
+ ] });
702
+ }
703
+ if (status === "published") {
704
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
705
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
706
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
707
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
708
+ defaultMessage: "Already published"
709
+ }) })
710
+ ] });
711
+ }
639
712
  }
640
713
  return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
641
- /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
714
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
642
715
  !entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
643
716
  id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
644
717
  defaultMessage: "Already unpublished"
@@ -658,20 +731,23 @@ const ReleaseDetailsLayout = ({
658
731
  const {
659
732
  data,
660
733
  isLoading: isLoadingDetails,
661
- isError,
662
734
  error
663
- } = useGetReleaseQuery({ id: releaseId });
735
+ } = useGetReleaseQuery(
736
+ { id: releaseId },
737
+ {
738
+ skip: !releaseId
739
+ }
740
+ );
664
741
  const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();
665
- const toggleNotification = useNotification();
742
+ const { toggleNotification } = useNotification();
666
743
  const { formatAPIError } = useAPIErrorHandler();
667
- const {
668
- allowedActions: { canUpdate, canDelete }
669
- } = useRBAC(PERMISSIONS);
744
+ const { allowedActions } = useRBAC(PERMISSIONS);
745
+ const { canUpdate, canDelete, canPublish } = allowedActions;
670
746
  const dispatch = useTypedDispatch();
671
747
  const { trackUsage } = useTracking();
672
748
  const release = data?.data;
673
- const handlePublishRelease = async () => {
674
- const response = await publishRelease({ id: releaseId });
749
+ const handlePublishRelease = (id) => async () => {
750
+ const response = await publishRelease({ id });
675
751
  if ("data" in response) {
676
752
  toggleNotification({
677
753
  type: "success",
@@ -686,14 +762,14 @@ const ReleaseDetailsLayout = ({
686
762
  totalPublishedEntries,
687
763
  totalUnpublishedEntries
688
764
  });
689
- } else if (isAxiosError(response.error)) {
765
+ } else if (isFetchError(response.error)) {
690
766
  toggleNotification({
691
- type: "warning",
767
+ type: "danger",
692
768
  message: formatAPIError(response.error)
693
769
  });
694
770
  } else {
695
771
  toggleNotification({
696
- type: "warning",
772
+ type: "danger",
697
773
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
698
774
  });
699
775
  }
@@ -719,21 +795,20 @@ const ReleaseDetailsLayout = ({
719
795
  return release.createdBy.email;
720
796
  };
721
797
  if (isLoadingDetails) {
722
- return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
798
+ return /* @__PURE__ */ jsx(Page.Loading, {});
723
799
  }
724
- if (isError || !release) {
800
+ if (isBaseQueryError(error) && "code" in error || !release) {
725
801
  return /* @__PURE__ */ jsx(
726
- Redirect,
802
+ Navigate,
727
803
  {
728
- to: {
729
- pathname: "/plugins/content-releases",
730
- state: {
731
- errors: [
732
- {
733
- code: error?.code
734
- }
735
- ]
736
- }
804
+ to: "..",
805
+ state: {
806
+ errors: [
807
+ {
808
+ // @ts-expect-error – TODO: fix this weird error flow
809
+ code: error?.code
810
+ }
811
+ ]
737
812
  }
738
813
  }
739
814
  );
@@ -770,106 +845,90 @@ const ReleaseDetailsLayout = ({
770
845
  ) : "";
771
846
  return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
772
847
  /* @__PURE__ */ jsx(
773
- HeaderLayout,
848
+ Layouts.Header,
774
849
  {
775
850
  title: release.name,
776
851
  subtitle: /* @__PURE__ */ jsxs(Flex, { gap: 2, lineHeight: 6, children: [
777
852
  /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", variant: "epsilon", children: numberOfEntriesText + (isScheduled ? ` - ${scheduledText}` : "") }),
778
853
  /* @__PURE__ */ jsx(Badge, { ...getBadgeProps(release.status), children: release.status })
779
854
  ] }),
780
- navigationAction: /* @__PURE__ */ jsx(Link$1, { startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
781
- id: "global.back",
782
- defaultMessage: "Back"
783
- }) }),
855
+ navigationAction: /* @__PURE__ */ jsx(BackButton, {}),
784
856
  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"
857
+ /* @__PURE__ */ jsxs(
858
+ SimpleMenuButton,
859
+ {
860
+ label: /* @__PURE__ */ jsx(More, {}),
861
+ variant: "tertiary",
862
+ endIcon: null,
863
+ paddingLeft: "7px",
864
+ paddingRight: "7px",
865
+ "aria-label": formatMessage({
866
+ id: "content-releases.header.actions.open-release-actions",
867
+ defaultMessage: "Release edit and delete menu"
868
+ }),
869
+ popoverPlacement: "bottom-end",
870
+ children: [
871
+ /* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
872
+ /* @__PURE__ */ jsx(PencilIcon, {}),
873
+ /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
874
+ id: "content-releases.header.actions.edit",
875
+ defaultMessage: "Edit"
876
+ }) })
877
+ ] }) }),
878
+ /* @__PURE__ */ jsx(
879
+ StyledMenuItem,
880
+ {
881
+ disabled: !canDelete,
882
+ onSelect: toggleWarningSubmit,
883
+ $variant: "danger",
884
+ children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
885
+ /* @__PURE__ */ jsx(TrashIcon, {}),
886
+ /* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
887
+ id: "content-releases.header.actions.delete",
888
+ defaultMessage: "Delete"
815
889
  }) })
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
890
  ] })
858
- ]
859
- }
860
- )
861
- ] })
862
- ] }),
891
+ }
892
+ ),
893
+ /* @__PURE__ */ jsxs(
894
+ ReleaseInfoWrapper,
895
+ {
896
+ direction: "column",
897
+ justifyContent: "center",
898
+ alignItems: "flex-start",
899
+ gap: 1,
900
+ padding: 4,
901
+ children: [
902
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
903
+ id: "content-releases.header.actions.created",
904
+ defaultMessage: "Created"
905
+ }) }),
906
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", color: "neutral300", children: [
907
+ /* @__PURE__ */ jsx(RelativeTime$1, { timestamp: new Date(release.createdAt) }),
908
+ formatMessage(
909
+ {
910
+ id: "content-releases.header.actions.created.description",
911
+ defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
912
+ },
913
+ { createdBy: getCreatedByUser(), hasCreatedByUser }
914
+ )
915
+ ] })
916
+ ]
917
+ }
918
+ )
919
+ ]
920
+ }
921
+ ),
863
922
  /* @__PURE__ */ jsx(Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
864
923
  id: "content-releases.header.actions.refresh",
865
924
  defaultMessage: "Refresh"
866
925
  }) }),
867
- /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.publish, children: /* @__PURE__ */ jsx(
926
+ canPublish ? /* @__PURE__ */ jsx(
868
927
  Button,
869
928
  {
870
929
  size: "S",
871
930
  variant: "default",
872
- onClick: handlePublishRelease,
931
+ onClick: handlePublishRelease(release.id.toString()),
873
932
  loading: isPublishing,
874
933
  disabled: release.actions.meta.count === 0,
875
934
  children: formatMessage({
@@ -877,13 +936,18 @@ const ReleaseDetailsLayout = ({
877
936
  defaultMessage: "Publish"
878
937
  })
879
938
  }
880
- ) })
939
+ ) : null
881
940
  ] })
882
941
  }
883
942
  ),
884
943
  children
885
944
  ] });
886
945
  };
946
+ const SimpleMenuButton = styled(SimpleMenu)`
947
+ & > span {
948
+ display: flex;
949
+ }
950
+ `;
887
951
  const GROUP_BY_OPTIONS = ["contentType", "locale", "action"];
888
952
  const GROUP_BY_OPTIONS_NO_LOCALE = ["contentType", "action"];
889
953
  const getGroupByOptionLabel = (value) => {
@@ -904,47 +968,32 @@ const getGroupByOptionLabel = (value) => {
904
968
  defaultMessage: "Content-Types"
905
969
  };
906
970
  };
907
- const DEFAULT_RELEASE_DETAILS_HEADER = [
908
- {
909
- key: "__name__",
910
- fieldSchema: { type: "string" },
911
- metadatas: {
912
- label: {
913
- id: "content-releases.page.ReleaseDetails.table.header.label.name",
914
- defaultMessage: "name"
915
- },
916
- searchable: false,
917
- sortable: false
918
- },
919
- name: "name"
920
- }
921
- ];
922
- const ReleaseDetailsBody = () => {
971
+ const ReleaseDetailsBody = ({ releaseId }) => {
923
972
  const { formatMessage } = useIntl();
924
- const { releaseId } = useParams();
925
973
  const [{ query }, setQuery] = useQueryParams();
926
- const toggleNotification = useNotification();
974
+ const { toggleNotification } = useNotification();
927
975
  const { formatAPIError } = useAPIErrorHandler();
928
976
  const {
929
977
  data: releaseData,
930
978
  isLoading: isReleaseLoading,
931
- isError: isReleaseError,
932
979
  error: releaseError
933
980
  } = useGetReleaseQuery({ id: releaseId });
934
981
  const {
935
982
  allowedActions: { canUpdate }
936
983
  } = useRBAC(PERMISSIONS);
937
- const { runHookWaterfall } = useStrapiApp();
938
- const {
939
- displayedHeaders,
940
- hasI18nEnabled
941
- } = runHookWaterfall(
942
- "ContentReleases/pages/ReleaseDetails/add-locale-in-releases",
943
- {
944
- displayedHeaders: DEFAULT_RELEASE_DETAILS_HEADER,
945
- hasI18nEnabled: false
946
- }
947
- );
984
+ const runHookWaterfall = useStrapiApp("ReleaseDetailsPage", (state) => state.runHookWaterfall);
985
+ const { displayedHeaders, hasI18nEnabled } = runHookWaterfall("ContentReleases/pages/ReleaseDetails/add-locale-in-releases", {
986
+ displayedHeaders: [
987
+ {
988
+ label: {
989
+ id: "content-releases.page.ReleaseDetails.table.header.label.name",
990
+ defaultMessage: "name"
991
+ },
992
+ name: "name"
993
+ }
994
+ ],
995
+ hasI18nEnabled: false
996
+ });
948
997
  const release = releaseData?.data;
949
998
  const selectedGroupBy = query?.groupBy || "contentType";
950
999
  const {
@@ -973,65 +1022,59 @@ const ReleaseDetailsBody = () => {
973
1022
  // We are passing the action path to found the position in the cache of the action for optimistic updates
974
1023
  });
975
1024
  if ("error" in response) {
976
- if (isAxiosError(response.error)) {
1025
+ if (isFetchError(response.error)) {
977
1026
  toggleNotification({
978
- type: "warning",
1027
+ type: "danger",
979
1028
  message: formatAPIError(response.error)
980
1029
  });
981
1030
  } else {
982
1031
  toggleNotification({
983
- type: "warning",
1032
+ type: "danger",
984
1033
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
985
1034
  });
986
1035
  }
987
1036
  }
988
1037
  };
989
1038
  if (isLoading || isReleaseLoading) {
990
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
1039
+ return /* @__PURE__ */ jsx(Page.Loading, {});
991
1040
  }
992
1041
  const releaseActions = data?.data;
993
1042
  const releaseMeta = data?.meta;
994
1043
  const contentTypes = releaseMeta?.contentTypes || {};
995
1044
  const components = releaseMeta?.components || {};
996
- if (isReleaseError || !release) {
1045
+ if (isBaseQueryError(releaseError) || !release) {
997
1046
  const errorsArray = [];
998
- if (releaseError) {
1047
+ if (releaseError && "code" in releaseError) {
999
1048
  errorsArray.push({
1000
1049
  code: releaseError.code
1001
1050
  });
1002
1051
  }
1003
- if (releaseActionsError) {
1052
+ if (releaseActionsError && "code" in releaseActionsError) {
1004
1053
  errorsArray.push({
1005
1054
  code: releaseActionsError.code
1006
1055
  });
1007
1056
  }
1008
1057
  return /* @__PURE__ */ jsx(
1009
- Redirect,
1058
+ Navigate,
1010
1059
  {
1011
- to: {
1012
- pathname: "/plugins/content-releases",
1013
- state: {
1014
- errors: errorsArray
1015
- }
1060
+ to: "..",
1061
+ state: {
1062
+ errors: errorsArray
1016
1063
  }
1017
1064
  }
1018
1065
  );
1019
1066
  }
1020
1067
  if (isError || !releaseActions) {
1021
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(AnErrorOccurred, {}) });
1068
+ return /* @__PURE__ */ jsx(Page.Error, {});
1022
1069
  }
1023
1070
  if (Object.keys(releaseActions).length === 0) {
1024
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(
1025
- NoContent,
1071
+ return /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsx(
1072
+ EmptyStateLayout,
1026
1073
  {
1027
- content: {
1028
- id: "content-releases.pages.Details.tab.emptyEntries",
1029
- defaultMessage: "This release is empty. Open the Content Manager, select an entry and add it to the release."
1030
- },
1031
1074
  action: /* @__PURE__ */ jsx(
1032
1075
  LinkButton,
1033
1076
  {
1034
- as: Link$2,
1077
+ tag: Link$1,
1035
1078
  to: {
1036
1079
  pathname: "/content-manager"
1037
1080
  },
@@ -1042,19 +1085,52 @@ const ReleaseDetailsBody = () => {
1042
1085
  defaultMessage: "Open the Content Manager"
1043
1086
  })
1044
1087
  }
1045
- )
1088
+ ),
1089
+ icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "16rem" }),
1090
+ content: formatMessage({
1091
+ id: "content-releases.pages.Details.tab.emptyEntries",
1092
+ defaultMessage: "This release is empty. Open the Content Manager, select an entry and add it to the release."
1093
+ })
1046
1094
  }
1047
1095
  ) });
1048
1096
  }
1097
+ const groupByLabel = formatMessage({
1098
+ id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
1099
+ defaultMessage: "Group by"
1100
+ });
1101
+ const headers = [
1102
+ ...displayedHeaders,
1103
+ {
1104
+ label: {
1105
+ id: "content-releases.page.ReleaseDetails.table.header.label.content-type",
1106
+ defaultMessage: "content-type"
1107
+ },
1108
+ name: "content-type"
1109
+ },
1110
+ {
1111
+ label: {
1112
+ id: "content-releases.page.ReleaseDetails.table.header.label.action",
1113
+ defaultMessage: "action"
1114
+ },
1115
+ name: "action"
1116
+ },
1117
+ ...!release.releasedAt ? [
1118
+ {
1119
+ label: {
1120
+ id: "content-releases.page.ReleaseDetails.table.header.label.status",
1121
+ defaultMessage: "status"
1122
+ },
1123
+ name: "status"
1124
+ }
1125
+ ] : []
1126
+ ];
1049
1127
  const options = hasI18nEnabled ? GROUP_BY_OPTIONS : GROUP_BY_OPTIONS_NO_LOCALE;
1050
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
1128
+ return /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
1051
1129
  /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
1052
1130
  SingleSelect,
1053
1131
  {
1054
- "aria-label": formatMessage({
1055
- id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
1056
- defaultMessage: "Group by"
1057
- }),
1132
+ placeholder: groupByLabel,
1133
+ "aria-label": groupByLabel,
1058
1134
  customizeContent: (value) => formatMessage(
1059
1135
  {
1060
1136
  id: `content-releases.pages.ReleaseDetails.groupBy.label`,
@@ -1078,57 +1154,13 @@ const ReleaseDetailsBody = () => {
1078
1154
  ...item,
1079
1155
  id: Number(item.entry.id)
1080
1156
  })),
1081
- colCount: releaseActions[key].length,
1082
- isLoading,
1083
- isFetching,
1157
+ headers,
1158
+ isLoading: isLoading || isFetching,
1084
1159
  children: /* @__PURE__ */ jsxs(Table.Content, { children: [
1085
- /* @__PURE__ */ jsxs(Table.Head, { children: [
1086
- displayedHeaders.map(({ key: key2, fieldSchema, metadatas, name }) => /* @__PURE__ */ jsx(
1087
- Table.HeaderCell,
1088
- {
1089
- fieldSchemaType: fieldSchema.type,
1090
- label: formatMessage(metadatas.label),
1091
- name
1092
- },
1093
- key2
1094
- )),
1095
- /* @__PURE__ */ jsx(
1096
- Table.HeaderCell,
1097
- {
1098
- fieldSchemaType: "string",
1099
- label: formatMessage({
1100
- id: "content-releases.page.ReleaseDetails.table.header.label.content-type",
1101
- defaultMessage: "content-type"
1102
- }),
1103
- name: "content-type"
1104
- }
1105
- ),
1106
- /* @__PURE__ */ jsx(
1107
- Table.HeaderCell,
1108
- {
1109
- fieldSchemaType: "string",
1110
- label: formatMessage({
1111
- id: "content-releases.page.ReleaseDetails.table.header.label.action",
1112
- defaultMessage: "action"
1113
- }),
1114
- name: "action"
1115
- }
1116
- ),
1117
- !release.releasedAt && /* @__PURE__ */ jsx(
1118
- Table.HeaderCell,
1119
- {
1120
- fieldSchemaType: "string",
1121
- label: formatMessage({
1122
- id: "content-releases.page.ReleaseDetails.table.header.label.status",
1123
- defaultMessage: "status"
1124
- }),
1125
- name: "status"
1126
- }
1127
- )
1128
- ] }),
1129
- /* @__PURE__ */ jsx(Table.LoadingBody, {}),
1160
+ /* @__PURE__ */ jsx(Table.Head, { children: headers.map(({ label, name }) => /* @__PURE__ */ jsx(Table.HeaderCell, { label: formatMessage(label), name }, name)) }),
1161
+ /* @__PURE__ */ jsx(Table.Loading, {}),
1130
1162
  /* @__PURE__ */ jsx(Table.Body, { children: releaseActions[key].map(
1131
- ({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxs(Tr, { children: [
1163
+ ({ id, contentType, locale, type, entry, status }, actionIndex) => /* @__PURE__ */ jsxs(Tr, { children: [
1132
1164
  /* @__PURE__ */ jsx(Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
1133
1165
  hasI18nEnabled && /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
1134
1166
  /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: contentType.displayName || "" }) }),
@@ -1157,7 +1189,8 @@ const ReleaseDetailsBody = () => {
1157
1189
  action: type,
1158
1190
  schema: contentTypes?.[contentType.uid],
1159
1191
  components,
1160
- entry
1192
+ entry,
1193
+ status
1161
1194
  }
1162
1195
  ) }),
1163
1196
  /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { children: [
@@ -1165,7 +1198,7 @@ const ReleaseDetailsBody = () => {
1165
1198
  ReleaseActionMenu.ReleaseActionEntryLinkItem,
1166
1199
  {
1167
1200
  contentTypeUid: contentType.uid,
1168
- entryId: entry.id,
1201
+ documentId: entry.documentId,
1169
1202
  locale: locale?.code
1170
1203
  }
1171
1204
  ),
@@ -1184,54 +1217,73 @@ const ReleaseDetailsBody = () => {
1184
1217
  }
1185
1218
  )
1186
1219
  ] }, `releases-group-${key}`)),
1187
- /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
1188
- /* @__PURE__ */ jsx(PageSizeURLQuery, { defaultValue: releaseMeta?.pagination?.pageSize.toString() }),
1189
- /* @__PURE__ */ jsx(
1190
- PaginationURLQuery,
1191
- {
1192
- pagination: {
1193
- pageCount: releaseMeta?.pagination?.pageCount || 0
1194
- }
1195
- }
1196
- )
1197
- ] })
1220
+ /* @__PURE__ */ jsxs(
1221
+ Pagination.Root,
1222
+ {
1223
+ ...releaseMeta?.pagination,
1224
+ defaultPageSize: releaseMeta?.pagination?.pageSize,
1225
+ children: [
1226
+ /* @__PURE__ */ jsx(Pagination.PageSize, {}),
1227
+ /* @__PURE__ */ jsx(Pagination.Links, {})
1228
+ ]
1229
+ }
1230
+ )
1198
1231
  ] }) });
1199
1232
  };
1200
1233
  const ReleaseDetailsPage = () => {
1201
1234
  const { formatMessage } = useIntl();
1202
1235
  const { releaseId } = useParams();
1203
- const toggleNotification = useNotification();
1236
+ const { toggleNotification } = useNotification();
1204
1237
  const { formatAPIError } = useAPIErrorHandler();
1205
- const { replace } = useHistory();
1238
+ const navigate = useNavigate();
1206
1239
  const [releaseModalShown, setReleaseModalShown] = React.useState(false);
1207
1240
  const [showWarningSubmit, setWarningSubmit] = React.useState(false);
1208
1241
  const {
1209
1242
  isLoading: isLoadingDetails,
1210
1243
  data,
1211
1244
  isSuccess: isSuccessDetails
1212
- } = useGetReleaseQuery({ id: releaseId });
1245
+ } = useGetReleaseQuery(
1246
+ { id: releaseId },
1247
+ {
1248
+ skip: !releaseId
1249
+ }
1250
+ );
1251
+ const { data: dataTimezone, isLoading: isLoadingTimezone } = useGetReleaseSettingsQuery();
1213
1252
  const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();
1214
- const [deleteRelease, { isLoading: isDeletingRelease }] = useDeleteReleaseMutation();
1253
+ const [deleteRelease] = useDeleteReleaseMutation();
1215
1254
  const toggleEditReleaseModal = () => {
1216
1255
  setReleaseModalShown((prev) => !prev);
1217
1256
  };
1257
+ const getTimezoneValue = () => {
1258
+ if (releaseData?.timezone) {
1259
+ return releaseData.timezone;
1260
+ } else {
1261
+ if (dataTimezone?.data.defaultTimezone) {
1262
+ return dataTimezone.data.defaultTimezone;
1263
+ }
1264
+ return null;
1265
+ }
1266
+ };
1218
1267
  const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);
1219
- if (isLoadingDetails) {
1268
+ if (isLoadingDetails || isLoadingTimezone) {
1220
1269
  return /* @__PURE__ */ jsx(
1221
1270
  ReleaseDetailsLayout,
1222
1271
  {
1223
1272
  toggleEditReleaseModal,
1224
1273
  toggleWarningSubmit,
1225
- children: /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) })
1274
+ children: /* @__PURE__ */ jsx(Page.Loading, {})
1226
1275
  }
1227
1276
  );
1228
1277
  }
1278
+ if (!releaseId) {
1279
+ return /* @__PURE__ */ jsx(Navigate, { to: ".." });
1280
+ }
1229
1281
  const releaseData = isSuccessDetails && data?.data || null;
1230
1282
  const title = releaseData?.name || "";
1231
- const timezone = releaseData?.timezone ?? null;
1283
+ const timezone = getTimezoneValue();
1232
1284
  const scheduledAt = releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;
1233
- const date = scheduledAt ? format(scheduledAt, "yyyy-MM-dd") : null;
1234
- const time = scheduledAt ? format(scheduledAt, "HH:mm") : "";
1285
+ const date = scheduledAt ? format$1(scheduledAt, "yyyy-MM-dd") : void 0;
1286
+ const time = scheduledAt ? format$1(scheduledAt, "HH:mm") : "";
1235
1287
  const handleEditRelease = async (values) => {
1236
1288
  const response = await updateRelease({
1237
1289
  id: releaseId,
@@ -1248,14 +1300,14 @@ const ReleaseDetailsPage = () => {
1248
1300
  })
1249
1301
  });
1250
1302
  toggleEditReleaseModal();
1251
- } else if (isAxiosError(response.error)) {
1303
+ } else if (isFetchError(response.error)) {
1252
1304
  toggleNotification({
1253
- type: "warning",
1305
+ type: "danger",
1254
1306
  message: formatAPIError(response.error)
1255
1307
  });
1256
1308
  } else {
1257
1309
  toggleNotification({
1258
- type: "warning",
1310
+ type: "danger",
1259
1311
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1260
1312
  });
1261
1313
  }
@@ -1265,15 +1317,15 @@ const ReleaseDetailsPage = () => {
1265
1317
  id: releaseId
1266
1318
  });
1267
1319
  if ("data" in response) {
1268
- replace("/plugins/content-releases");
1269
- } else if (isAxiosError(response.error)) {
1320
+ navigate("..");
1321
+ } else if (isFetchError(response.error)) {
1270
1322
  toggleNotification({
1271
- type: "warning",
1323
+ type: "danger",
1272
1324
  message: formatAPIError(response.error)
1273
1325
  });
1274
1326
  } else {
1275
1327
  toggleNotification({
1276
- type: "warning",
1328
+ type: "danger",
1277
1329
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1278
1330
  });
1279
1331
  }
@@ -1284,10 +1336,11 @@ const ReleaseDetailsPage = () => {
1284
1336
  toggleEditReleaseModal,
1285
1337
  toggleWarningSubmit,
1286
1338
  children: [
1287
- /* @__PURE__ */ jsx(ReleaseDetailsBody, {}),
1288
- releaseModalShown && /* @__PURE__ */ jsx(
1339
+ /* @__PURE__ */ jsx(ReleaseDetailsBody, { releaseId }),
1340
+ /* @__PURE__ */ jsx(
1289
1341
  ReleaseModal,
1290
1342
  {
1343
+ open: releaseModalShown,
1291
1344
  handleClose: toggleEditReleaseModal,
1292
1345
  handleSubmit: handleEditRelease,
1293
1346
  isLoading: isLoadingDetails || isSubmittingForm,
@@ -1301,30 +1354,21 @@ const ReleaseDetailsPage = () => {
1301
1354
  }
1302
1355
  }
1303
1356
  ),
1304
- /* @__PURE__ */ jsx(
1305
- ConfirmDialog,
1306
- {
1307
- bodyText: {
1308
- id: "content-releases.dialog.confirmation-message",
1309
- defaultMessage: "Are you sure you want to delete this release?"
1310
- },
1311
- isOpen: showWarningSubmit,
1312
- isConfirmButtonLoading: isDeletingRelease,
1313
- onToggleDialog: toggleWarningSubmit,
1314
- onConfirm: handleDeleteRelease
1315
- }
1316
- )
1357
+ /* @__PURE__ */ jsx(Dialog.Root, { open: showWarningSubmit, onOpenChange: toggleWarningSubmit, children: /* @__PURE__ */ jsx(ConfirmDialog, { onConfirm: handleDeleteRelease, children: formatMessage({
1358
+ id: "content-releases.dialog.confirmation-message",
1359
+ defaultMessage: "Are you sure you want to delete this release?"
1360
+ }) }) })
1317
1361
  ]
1318
1362
  }
1319
1363
  );
1320
1364
  };
1321
1365
  const App = () => {
1322
- return /* @__PURE__ */ jsx(CheckPagePermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(Switch, { children: [
1323
- /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}`, component: ReleasesPage }),
1324
- /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}/:releaseId`, component: ReleaseDetailsPage })
1366
+ return /* @__PURE__ */ jsx(Page.Protect, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(Routes, { children: [
1367
+ /* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(ReleasesPage, {}) }),
1368
+ /* @__PURE__ */ jsx(Route, { path: ":releaseId", element: /* @__PURE__ */ jsx(ReleaseDetailsPage, {}) })
1325
1369
  ] }) });
1326
1370
  };
1327
1371
  export {
1328
1372
  App
1329
1373
  };
1330
- //# sourceMappingURL=App-jrh58sXY.mjs.map
1374
+ //# sourceMappingURL=App-Cne--1Z8.mjs.map