@strapi/content-releases 0.0.0-experimental.fc1ac2acd58c8a5a858679956b6d102ac5ee4011 → 0.0.0-experimental.fd379e4937e431407d784eaa5fe7f93cf2a53386

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 (127) hide show
  1. package/LICENSE +17 -1
  2. package/dist/_chunks/{App-C768ulk4.js → App-BKB1esYS.js} +497 -483
  3. package/dist/_chunks/App-BKB1esYS.js.map +1 -0
  4. package/dist/_chunks/{App-0Er6xxcq.mjs → App-Cne--1Z8.mjs} +480 -464
  5. package/dist/_chunks/App-Cne--1Z8.mjs.map +1 -0
  6. package/dist/_chunks/{PurchaseContentReleases-YhAPgpG9.js → PurchaseContentReleases-Be3acS2L.js} +8 -7
  7. package/dist/_chunks/PurchaseContentReleases-Be3acS2L.js.map +1 -0
  8. package/dist/_chunks/{PurchaseContentReleases-Clm0iACO.mjs → PurchaseContentReleases-_MxP6-Dt.mjs} +9 -8
  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-gcJJ5htG.js → en-CmYoEnA7.js} +19 -4
  15. package/dist/_chunks/en-CmYoEnA7.js.map +1 -0
  16. package/dist/_chunks/{en-WuuhP6Bn.mjs → en-D0yVZFqf.mjs} +19 -4
  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/ReleaseAction.d.ts +3 -0
  31. package/dist/admin/src/components/ReleaseActionMenu.d.ts +4 -4
  32. package/dist/admin/src/components/ReleaseActionModal.d.ts +24 -0
  33. package/dist/admin/src/components/ReleaseListCell.d.ts +28 -0
  34. package/dist/admin/src/components/ReleaseModal.d.ts +3 -2
  35. package/dist/admin/src/components/ReleasesPanel.d.ts +3 -0
  36. package/dist/admin/src/constants.d.ts +18 -0
  37. package/dist/admin/src/modules/hooks.d.ts +7 -0
  38. package/dist/admin/src/pages/ReleasesSettingsPage.d.ts +1 -0
  39. package/dist/admin/src/services/release.d.ts +66 -323
  40. package/dist/admin/src/utils/api.d.ts +6 -0
  41. package/dist/admin/src/utils/prefixPluginTranslations.d.ts +3 -0
  42. package/dist/admin/src/utils/time.d.ts +9 -0
  43. package/dist/admin/src/validation/schemas.d.ts +6 -0
  44. package/dist/server/index.js +1057 -646
  45. package/dist/server/index.js.map +1 -1
  46. package/dist/server/index.mjs +1058 -647
  47. package/dist/server/index.mjs.map +1 -1
  48. package/dist/server/src/bootstrap.d.ts +2 -2
  49. package/dist/server/src/bootstrap.d.ts.map +1 -1
  50. package/dist/server/src/constants.d.ts +11 -2
  51. package/dist/server/src/constants.d.ts.map +1 -1
  52. package/dist/server/src/content-types/index.d.ts +3 -5
  53. package/dist/server/src/content-types/index.d.ts.map +1 -1
  54. package/dist/server/src/content-types/release-action/index.d.ts +3 -5
  55. package/dist/server/src/content-types/release-action/index.d.ts.map +1 -1
  56. package/dist/server/src/content-types/release-action/schema.d.ts +3 -5
  57. package/dist/server/src/content-types/release-action/schema.d.ts.map +1 -1
  58. package/dist/server/src/controllers/index.d.ts +8 -1
  59. package/dist/server/src/controllers/index.d.ts.map +1 -1
  60. package/dist/server/src/controllers/release-action.d.ts +1 -0
  61. package/dist/server/src/controllers/release-action.d.ts.map +1 -1
  62. package/dist/server/src/controllers/release.d.ts +8 -1
  63. package/dist/server/src/controllers/release.d.ts.map +1 -1
  64. package/dist/server/src/controllers/settings.d.ts +11 -0
  65. package/dist/server/src/controllers/settings.d.ts.map +1 -0
  66. package/dist/server/src/controllers/validation/release-action.d.ts +13 -2
  67. package/dist/server/src/controllers/validation/release-action.d.ts.map +1 -1
  68. package/dist/server/src/controllers/validation/release.d.ts +2 -0
  69. package/dist/server/src/controllers/validation/release.d.ts.map +1 -1
  70. package/dist/server/src/controllers/validation/settings.d.ts +3 -0
  71. package/dist/server/src/controllers/validation/settings.d.ts.map +1 -0
  72. package/dist/server/src/destroy.d.ts +2 -2
  73. package/dist/server/src/destroy.d.ts.map +1 -1
  74. package/dist/server/src/index.d.ts +1518 -3241
  75. package/dist/server/src/index.d.ts.map +1 -1
  76. package/dist/server/src/middlewares/documents.d.ts +6 -0
  77. package/dist/server/src/middlewares/documents.d.ts.map +1 -0
  78. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts +9 -0
  79. package/dist/server/src/migrations/database/5.0.0-document-id-in-actions.d.ts.map +1 -0
  80. package/dist/server/src/migrations/index.d.ts +3 -0
  81. package/dist/server/src/migrations/index.d.ts.map +1 -1
  82. package/dist/server/src/register.d.ts +2 -2
  83. package/dist/server/src/register.d.ts.map +1 -1
  84. package/dist/server/src/routes/index.d.ts +16 -0
  85. package/dist/server/src/routes/index.d.ts.map +1 -1
  86. package/dist/server/src/routes/release-action.d.ts.map +1 -1
  87. package/dist/server/src/routes/release.d.ts.map +1 -1
  88. package/dist/server/src/routes/settings.d.ts +18 -0
  89. package/dist/server/src/routes/settings.d.ts.map +1 -0
  90. package/dist/server/src/services/index.d.ts +1482 -3226
  91. package/dist/server/src/services/index.d.ts.map +1 -1
  92. package/dist/server/src/services/release-action.d.ts +38 -0
  93. package/dist/server/src/services/release-action.d.ts.map +1 -0
  94. package/dist/server/src/services/release.d.ts +19 -1800
  95. package/dist/server/src/services/release.d.ts.map +1 -1
  96. package/dist/server/src/services/scheduling.d.ts +6 -6
  97. package/dist/server/src/services/scheduling.d.ts.map +1 -1
  98. package/dist/server/src/services/settings.d.ts +13 -0
  99. package/dist/server/src/services/settings.d.ts.map +1 -0
  100. package/dist/server/src/services/validation.d.ts +7 -3
  101. package/dist/server/src/services/validation.d.ts.map +1 -1
  102. package/dist/server/src/utils/index.d.ts +33 -16
  103. package/dist/server/src/utils/index.d.ts.map +1 -1
  104. package/dist/shared/contracts/release-actions.d.ts +37 -12
  105. package/dist/shared/contracts/release-actions.d.ts.map +1 -1
  106. package/dist/shared/contracts/releases.d.ts +24 -6
  107. package/dist/shared/contracts/releases.d.ts.map +1 -1
  108. package/dist/shared/contracts/settings.d.ts +39 -0
  109. package/dist/shared/contracts/settings.d.ts.map +1 -0
  110. package/dist/shared/types.d.ts +2 -2
  111. package/dist/shared/types.d.ts.map +1 -1
  112. package/package.json +29 -27
  113. package/dist/_chunks/App-0Er6xxcq.mjs.map +0 -1
  114. package/dist/_chunks/App-C768ulk4.js.map +0 -1
  115. package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +0 -1
  116. package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +0 -1
  117. package/dist/_chunks/en-WuuhP6Bn.mjs.map +0 -1
  118. package/dist/_chunks/en-gcJJ5htG.js.map +0 -1
  119. package/dist/_chunks/index-BLSMpbpZ.js +0 -1028
  120. package/dist/_chunks/index-BLSMpbpZ.js.map +0 -1
  121. package/dist/_chunks/index-fJx1up7m.mjs +0 -1007
  122. package/dist/_chunks/index-fJx1up7m.mjs.map +0 -1
  123. package/dist/admin/src/components/CMReleasesContainer.d.ts +0 -1
  124. package/dist/admin/src/services/axios.d.ts +0 -29
  125. package/dist/shared/validation-schemas.d.ts +0 -2
  126. package/dist/shared/validation-schemas.d.ts.map +0 -1
  127. package/strapi-server.js +0 -3
@@ -1,25 +1,23 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { useLicenseLimits, Page, Pagination, unstable_useDocument } from "@strapi/admin/strapi-admin";
3
- import { useLocation, useNavigate, useParams, Navigate, Link as Link$2, Routes, 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-fJx1up7m.mjs";
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 { 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";
7
- import { Link, Menu, LinkButton } from "@strapi/design-system/v2";
8
- import { useNotification, useAPIErrorHandler, useQueryParams, useTracking, CheckPermissions, ConfirmDialog, useRBAC, Table } from "@strapi/helper-plugin";
9
- import { Plus, EmptyDocuments, Pencil, Trash, ArrowLeft, More, CrossCircle, CheckCircle } from "@strapi/icons";
10
- import format from "date-fns/format";
11
- import { zonedTimeToUtc, utcToZonedTime } from "date-fns-tz";
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
+ import { utcToZonedTime, zonedTimeToUtc } from "date-fns-tz";
12
12
  import { useIntl } from "react-intl";
13
- import styled from "styled-components";
14
- import { intervalToDuration, isPast, formatISO, parse } 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";
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";
21
19
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
22
- const RelativeTime = React.forwardRef(
20
+ const RelativeTime$1 = React.forwardRef(
23
21
  ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
24
22
  const { formatRelativeTime, formatDate, formatTime } = useIntl();
25
23
  const interval = intervalToDuration({
@@ -48,28 +46,9 @@ const RelativeTime = React.forwardRef(
48
46
  );
49
47
  }
50
48
  );
51
- const RELEASE_SCHEMA = yup.object().shape({
52
- name: yup.string().trim().required(),
53
- scheduledAt: yup.string().nullable(),
54
- isScheduled: yup.boolean().optional(),
55
- time: yup.string().when("isScheduled", {
56
- is: true,
57
- then: yup.string().trim().required(),
58
- otherwise: yup.string().nullable()
59
- }),
60
- timezone: yup.string().when("isScheduled", {
61
- is: true,
62
- then: yup.string().required().nullable(),
63
- otherwise: yup.string().nullable()
64
- }),
65
- date: yup.string().when("isScheduled", {
66
- is: true,
67
- then: yup.string().required().nullable(),
68
- otherwise: yup.string().nullable()
69
- })
70
- }).required().noUnknown();
71
49
  const ReleaseModal = ({
72
50
  handleClose,
51
+ open,
73
52
  handleSubmit,
74
53
  initialValues,
75
54
  isLoading = false
@@ -77,7 +56,6 @@ const ReleaseModal = ({
77
56
  const { formatMessage } = useIntl();
78
57
  const { pathname } = useLocation();
79
58
  const isCreatingRelease = pathname === `/plugins/${pluginId}`;
80
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
81
59
  const { timezoneList, systemTimezone = { value: "UTC+00:00-Africa/Abidjan " } } = getTimezones(
82
60
  initialValues.scheduledAt ? new Date(initialValues.scheduledAt) : /* @__PURE__ */ new Date()
83
61
  );
@@ -85,18 +63,17 @@ const ReleaseModal = ({
85
63
  const { date, time, timezone } = values;
86
64
  if (!date || !time || !timezone)
87
65
  return null;
88
- const formattedDate = parse(time, "HH:mm", new Date(date));
89
- const timezoneWithoutOffset = timezone.split("_")[1];
90
- return zonedTimeToUtc(formattedDate, timezoneWithoutOffset);
66
+ const timezoneWithoutOffset = timezone.split("&")[1];
67
+ return zonedTimeToUtc(`${date} ${time}`, timezoneWithoutOffset);
91
68
  };
92
69
  const getTimezoneWithOffset = () => {
93
70
  const currentTimezone = timezoneList.find(
94
- (timezone) => timezone.value.split("_")[1] === initialValues.timezone
71
+ (timezone) => timezone.value.split("&")[1] === initialValues.timezone
95
72
  );
96
73
  return currentTimezone?.value || systemTimezone.value;
97
74
  };
98
- return /* @__PURE__ */ jsxs(ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
99
- /* @__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(
100
77
  {
101
78
  id: "content-releases.modal.title",
102
79
  defaultMessage: "{isCreatingRelease, select, true {New release} other {Edit release}}"
@@ -109,7 +86,7 @@ const ReleaseModal = ({
109
86
  onSubmit: (values) => {
110
87
  handleSubmit({
111
88
  ...values,
112
- timezone: values.timezone ? values.timezone.split("_")[1] : null,
89
+ timezone: values.timezone ? values.timezone.split("&")[1] : null,
113
90
  scheduledAt: values.isScheduled ? getScheduledTimestamp(values) : null
114
91
  });
115
92
  },
@@ -119,31 +96,33 @@ const ReleaseModal = ({
119
96
  },
120
97
  validationSchema: RELEASE_SCHEMA,
121
98
  validateOnChange: false,
122
- children: ({ values, errors, handleChange, setFieldValue }) => /* @__PURE__ */ jsxs(Form, { children: [
123
- /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
124
- /* @__PURE__ */ jsx(
125
- TextInput,
126
- {
127
- label: formatMessage({
128
- id: "content-releases.modal.form.input.label.release-name",
129
- defaultMessage: "Name"
130
- }),
131
- name: "name",
132
- value: values.name,
133
- error: errors.name,
134
- onChange: handleChange,
135
- required: true
136
- }
137
- ),
138
- IsSchedulingEnabled && /* @__PURE__ */ jsxs(Fragment, { children: [
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
+ ),
139
118
  /* @__PURE__ */ jsx(Box, { width: "max-content", children: /* @__PURE__ */ jsx(
140
119
  Checkbox,
141
120
  {
142
121
  name: "isScheduled",
143
- value: values.isScheduled,
144
- onChange: (event) => {
145
- setFieldValue("isScheduled", event.target.checked);
146
- if (!event.target.checked) {
122
+ checked: values.isScheduled,
123
+ onCheckedChange: (checked) => {
124
+ setFieldValue("isScheduled", checked);
125
+ if (!checked) {
147
126
  setFieldValue("date", null);
148
127
  setFieldValue("time", "");
149
128
  setFieldValue("timezone", null);
@@ -171,85 +150,89 @@ const ReleaseModal = ({
171
150
  ) }),
172
151
  values.isScheduled && /* @__PURE__ */ jsxs(Fragment, { children: [
173
152
  /* @__PURE__ */ jsxs(Flex, { gap: 4, alignItems: "start", children: [
174
- /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
175
- DatePicker,
153
+ /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsxs(
154
+ Field.Root,
176
155
  {
177
- label: formatMessage({
178
- id: "content-releases.modal.form.input.label.date",
179
- defaultMessage: "Date"
180
- }),
181
156
  name: "date",
182
- error: errors.date,
183
- onChange: (date) => {
184
- const isoFormatDate = date ? formatISO(date, { representation: "date" }) : null;
185
- setFieldValue("date", isoFormatDate);
186
- },
187
- clearLabel: formatMessage({
188
- id: "content-releases.modal.form.input.clearLabel",
189
- defaultMessage: "Clear"
190
- }),
191
- onClear: () => {
192
- setFieldValue("date", null);
193
- },
194
- selectedDate: values.date || void 0,
195
- required: true
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
+ ]
196
184
  }
197
185
  ) }),
198
- /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
199
- TimePicker,
186
+ /* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsxs(
187
+ Field.Root,
200
188
  {
201
- label: formatMessage({
202
- id: "content-releases.modal.form.input.label.time",
203
- defaultMessage: "Time"
204
- }),
205
189
  name: "time",
206
- error: errors.time,
207
- onChange: (time) => {
208
- setFieldValue("time", time);
209
- },
210
- clearLabel: formatMessage({
211
- id: "content-releases.modal.form.input.clearLabel",
212
- defaultMessage: "Clear"
213
- }),
214
- onClear: () => {
215
- setFieldValue("time", "");
216
- },
217
- value: values.time || void 0,
218
- required: true
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
+ ]
219
215
  }
220
216
  ) })
221
217
  ] }),
222
218
  /* @__PURE__ */ jsx(TimezoneComponent, { timezoneOptions: timezoneList })
223
219
  ] })
224
- ] })
225
- ] }) }),
226
- /* @__PURE__ */ jsx(
227
- ModalFooter,
228
- {
229
- startActions: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }),
230
- endActions: /* @__PURE__ */ jsx(Button, { name: "submit", loading: isLoading, type: "submit", children: formatMessage(
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(
231
224
  {
232
225
  id: "content-releases.modal.form.button.submit",
233
226
  defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
234
227
  },
235
228
  { isCreatingRelease }
236
229
  ) })
237
- }
238
- )
239
- ] })
230
+ ] })
231
+ ] });
232
+ }
240
233
  }
241
234
  )
242
- ] });
243
- };
244
- const getTimezones = (selectedDate) => {
245
- const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
246
- const utcOffset = getTimezoneOffset(timezone, selectedDate);
247
- return { offset: utcOffset, value: `${utcOffset}_${timezone}` };
248
- });
249
- const systemTimezone = timezoneList.find(
250
- (timezone) => timezone.value.split("_")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
251
- );
252
- return { timezoneList, systemTimezone };
235
+ ] }) });
253
236
  };
254
237
  const TimezoneComponent = ({ timezoneOptions }) => {
255
238
  const { values, errors, setFieldValue } = useFormikContext();
@@ -259,42 +242,58 @@ const TimezoneComponent = ({ timezoneOptions }) => {
259
242
  if (values.date) {
260
243
  const { timezoneList: timezoneList2 } = getTimezones(new Date(values.date));
261
244
  setTimezoneList(timezoneList2);
262
- const updatedTimezone = values.timezone && timezoneList2.find((tz) => tz.value.split("_")[1] === values.timezone.split("_")[1]);
245
+ const updatedTimezone = values.timezone && timezoneList2.find((tz) => tz.value.split("&")[1] === values.timezone.split("&")[1]);
263
246
  if (updatedTimezone) {
264
247
  setFieldValue("timezone", updatedTimezone.value);
265
248
  }
266
249
  }
267
250
  }, [setFieldValue, values.date, values.timezone]);
268
- return /* @__PURE__ */ jsx(
269
- Combobox,
251
+ return /* @__PURE__ */ jsxs(
252
+ Field.Root,
270
253
  {
271
- label: formatMessage({
272
- id: "content-releases.modal.form.input.label.timezone",
273
- defaultMessage: "Timezone"
274
- }),
275
254
  name: "timezone",
276
- value: values.timezone || void 0,
277
- textValue: values.timezone ? values.timezone.replace("_", " ") : void 0,
278
- onChange: (timezone) => {
279
- setFieldValue("timezone", timezone);
280
- },
281
- onTextValueChange: (timezone) => {
282
- setFieldValue("timezone", timezone);
283
- },
284
- onClear: () => {
285
- setFieldValue("timezone", "");
286
- },
287
- error: errors.timezone,
255
+ error: errors.timezone && formatMessage({ id: errors.timezone, defaultMessage: errors.timezone }),
288
256
  required: true,
289
- 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
+ ]
290
282
  }
291
283
  );
292
284
  };
285
+ const useTypedDispatch = useDispatch;
286
+ const isBaseQueryError = (error) => {
287
+ return typeof error !== "undefined" && error.name !== void 0;
288
+ };
293
289
  const LinkCard = styled(Link)`
294
290
  display: block;
295
291
  `;
296
- const CapitalizeRelativeTime = styled(RelativeTime)`
297
- text-transform: capitalize;
292
+ const RelativeTime = styled(RelativeTime$1)`
293
+ display: inline-block;
294
+ &::first-letter {
295
+ text-transform: uppercase;
296
+ }
298
297
  `;
299
298
  const getBadgeProps = (status) => {
300
299
  let color;
@@ -323,7 +322,6 @@ const getBadgeProps = (status) => {
323
322
  };
324
323
  const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
325
324
  const { formatMessage } = useIntl();
326
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
327
325
  if (isError) {
328
326
  return /* @__PURE__ */ jsx(Page.Error, {});
329
327
  }
@@ -340,11 +338,11 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
340
338
  target: sectionTitle
341
339
  }
342
340
  ),
343
- icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem" })
341
+ icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "16rem" })
344
342
  }
345
343
  );
346
344
  }
347
- return /* @__PURE__ */ jsx(Grid, { gap: 4, children: releases.map(({ id, name, actions, 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(
348
346
  Flex,
349
347
  {
350
348
  direction: "column",
@@ -359,17 +357,11 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
359
357
  gap: 4,
360
358
  children: [
361
359
  /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "start", gap: 1, children: [
362
- /* @__PURE__ */ jsx(Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
363
- /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: IsSchedulingEnabled ? scheduledAt ? /* @__PURE__ */ jsx(CapitalizeRelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
360
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", tag: "h3", variant: "delta", fontWeight: "bold", children: name }),
361
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: scheduledAt ? /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
364
362
  id: "content-releases.pages.Releases.not-scheduled",
365
363
  defaultMessage: "Not scheduled"
366
- }) : formatMessage(
367
- {
368
- id: "content-releases.page.Releases.release-item.entries",
369
- defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
370
- },
371
- { number: actions.meta.count }
372
- ) })
364
+ }) })
373
365
  ] }),
374
366
  /* @__PURE__ */ jsx(Badge, { ...getBadgeProps(status), children: status })
375
367
  ]
@@ -386,34 +378,35 @@ const StyledAlert = styled(Alert)`
386
378
  `;
387
379
  const INITIAL_FORM_VALUES = {
388
380
  name: "",
389
- date: null,
381
+ date: format(/* @__PURE__ */ new Date(), "yyyy-MM-dd"),
390
382
  time: "",
391
- // Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
392
- isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
383
+ isScheduled: true,
393
384
  scheduledAt: null,
394
385
  timezone: null
395
386
  };
396
387
  const ReleasesPage = () => {
397
- const tabRef = React.useRef(null);
398
388
  const location = useLocation();
399
389
  const [releaseModalShown, setReleaseModalShown] = React.useState(false);
400
- const toggleNotification = useNotification();
390
+ const { toggleNotification } = useNotification();
401
391
  const { formatMessage } = useIntl();
402
392
  const navigate = useNavigate();
403
393
  const { formatAPIError } = useAPIErrorHandler();
404
394
  const [{ query }, setQuery] = useQueryParams();
405
395
  const response = useGetReleasesQuery(query);
396
+ const { data, isLoading: isLoadingSettings } = useGetReleaseSettingsQuery();
406
397
  const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();
407
398
  const { getFeature } = useLicenseLimits();
408
399
  const { maximumReleases = 3 } = getFeature("cms-content-releases");
409
400
  const { trackUsage } = useTracking();
410
- const { isLoading, isSuccess, isError } = response;
401
+ const {
402
+ allowedActions: { canCreate }
403
+ } = useRBAC(PERMISSIONS);
404
+ const { isLoading: isLoadingReleases, isSuccess, isError } = response;
411
405
  const activeTab = response?.currentData?.meta?.activeTab || "pending";
412
- const activeTabIndex = ["pending", "done"].indexOf(activeTab);
413
406
  React.useEffect(() => {
414
407
  if (location?.state?.errors) {
415
408
  toggleNotification({
416
- type: "warning",
409
+ type: "danger",
417
410
  title: formatMessage({
418
411
  id: "content-releases.pages.Releases.notification.error.title",
419
412
  defaultMessage: "Your request could not be processed."
@@ -426,27 +419,22 @@ const ReleasesPage = () => {
426
419
  navigate("", { replace: true, state: null });
427
420
  }
428
421
  }, [formatMessage, location?.state?.errors, navigate, toggleNotification]);
429
- React.useEffect(() => {
430
- if (tabRef.current) {
431
- tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
432
- }
433
- }, [activeTabIndex]);
434
422
  const toggleAddReleaseModal = () => {
435
423
  setReleaseModalShown((prev) => !prev);
436
424
  };
437
- if (isLoading) {
425
+ if (isLoadingReleases || isLoadingSettings) {
438
426
  return /* @__PURE__ */ jsx(Page.Loading, {});
439
427
  }
440
428
  const totalPendingReleases = isSuccess && response.currentData?.meta?.pendingReleasesCount || 0;
441
429
  const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
442
- const handleTabChange = (index) => {
430
+ const handleTabChange = (tabValue) => {
443
431
  setQuery({
444
432
  ...query,
445
433
  page: 1,
446
434
  pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
447
435
  filters: {
448
436
  releasedAt: {
449
- $notNull: index === 0 ? false : true
437
+ $notNull: tabValue !== "pending"
450
438
  }
451
439
  }
452
440
  });
@@ -467,21 +455,21 @@ const ReleasesPage = () => {
467
455
  });
468
456
  trackUsage("didCreateRelease");
469
457
  navigate(response2.data.data.id.toString());
470
- } else if (isAxiosError(response2.error)) {
458
+ } else if (isFetchError(response2.error)) {
471
459
  toggleNotification({
472
- type: "warning",
460
+ type: "danger",
473
461
  message: formatAPIError(response2.error)
474
462
  });
475
463
  } else {
476
464
  toggleNotification({
477
- type: "warning",
465
+ type: "danger",
478
466
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
479
467
  });
480
468
  }
481
469
  };
482
- return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoading, children: [
470
+ return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingReleases || isLoadingSettings, children: [
483
471
  /* @__PURE__ */ jsx(
484
- HeaderLayout,
472
+ Layouts.Header,
485
473
  {
486
474
  title: formatMessage({
487
475
  id: "content-releases.pages.Releases.title",
@@ -491,7 +479,7 @@ const ReleasesPage = () => {
491
479
  id: "content-releases.pages.Releases.header-subtitle",
492
480
  defaultMessage: "Create and manage content updates"
493
481
  }),
494
- primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(
482
+ primaryAction: canCreate ? /* @__PURE__ */ jsx(
495
483
  Button,
496
484
  {
497
485
  startIcon: /* @__PURE__ */ jsx(Plus, {}),
@@ -502,10 +490,10 @@ const ReleasesPage = () => {
502
490
  defaultMessage: "New release"
503
491
  })
504
492
  }
505
- ) })
493
+ ) : null
506
494
  }
507
495
  ),
508
- /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
496
+ /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
509
497
  hasReachedMaximumPendingReleases && /* @__PURE__ */ jsx(
510
498
  StyledAlert,
511
499
  {
@@ -530,21 +518,17 @@ const ReleasesPage = () => {
530
518
  })
531
519
  }
532
520
  ),
533
- /* @__PURE__ */ jsxs(
534
- TabGroup,
535
- {
536
- label: formatMessage({
537
- id: "content-releases.pages.Releases.tab-group.label",
538
- defaultMessage: "Releases list"
539
- }),
540
- variant: "simple",
541
- initialSelectedTabIndex: activeTabIndex,
542
- onTabChange: handleTabChange,
543
- ref: tabRef,
544
- children: [
545
- /* @__PURE__ */ jsxs(Box, { paddingBottom: 8, children: [
546
- /* @__PURE__ */ jsxs(Tabs, { children: [
547
- /* @__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(
548
532
  {
549
533
  id: "content-releases.pages.Releases.tab.pending",
550
534
  defaultMessage: "Pending ({count})"
@@ -553,34 +537,32 @@ const ReleasesPage = () => {
553
537
  count: totalPendingReleases
554
538
  }
555
539
  ) }),
556
- /* @__PURE__ */ jsx(Tab, { children: formatMessage({
540
+ /* @__PURE__ */ jsx(Tabs.Trigger, { value: "done", children: formatMessage({
557
541
  id: "content-releases.pages.Releases.tab.done",
558
542
  defaultMessage: "Done"
559
543
  }) })
560
- ] }),
561
- /* @__PURE__ */ jsx(Divider, {})
562
- ] }),
563
- /* @__PURE__ */ jsxs(TabPanels, { children: [
564
- /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
565
- ReleasesGrid,
566
- {
567
- sectionTitle: "pending",
568
- releases: response?.currentData?.data,
569
- isError
570
- }
571
- ) }),
572
- /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
573
- ReleasesGrid,
574
- {
575
- sectionTitle: "done",
576
- releases: response?.currentData?.data,
577
- isError
578
- }
579
- ) })
580
- ] })
581
- ]
582
- }
583
- ),
544
+ ]
545
+ }
546
+ ),
547
+ /* @__PURE__ */ jsx(Divider, {})
548
+ ] }),
549
+ /* @__PURE__ */ jsx(Tabs.Content, { value: "pending", children: /* @__PURE__ */ jsx(
550
+ ReleasesGrid,
551
+ {
552
+ sectionTitle: "pending",
553
+ releases: response?.currentData?.data,
554
+ isError
555
+ }
556
+ ) }),
557
+ /* @__PURE__ */ jsx(Tabs.Content, { value: "done", children: /* @__PURE__ */ jsx(
558
+ ReleasesGrid,
559
+ {
560
+ sectionTitle: "done",
561
+ releases: response?.currentData?.data,
562
+ isError
563
+ }
564
+ ) })
565
+ ] }),
584
566
  /* @__PURE__ */ jsxs(
585
567
  Pagination.Root,
586
568
  {
@@ -593,13 +575,17 @@ const ReleasesPage = () => {
593
575
  }
594
576
  )
595
577
  ] }) }),
596
- releaseModalShown && /* @__PURE__ */ jsx(
578
+ /* @__PURE__ */ jsx(
597
579
  ReleaseModal,
598
580
  {
581
+ open: releaseModalShown,
599
582
  handleClose: toggleAddReleaseModal,
600
583
  handleSubmit: handleAddRelease,
601
584
  isLoading: isSubmittingForm,
602
- initialValues: INITIAL_FORM_VALUES
585
+ initialValues: {
586
+ ...INITIAL_FORM_VALUES,
587
+ timezone: data?.data.defaultTimezone ? data.data.defaultTimezone.split("&")[1] : null
588
+ }
603
589
  }
604
590
  )
605
591
  ] });
@@ -610,7 +596,7 @@ const ReleaseInfoWrapper = styled(Flex)`
610
596
  border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
611
597
  border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
612
598
  `;
613
- const StyledMenuItem = styled(Menu.Item)`
599
+ const StyledMenuItem = styled(MenuItem)`
614
600
  svg path {
615
601
  fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
616
602
  }
@@ -619,19 +605,19 @@ const StyledMenuItem = styled(Menu.Item)`
619
605
  }
620
606
 
621
607
  &:hover {
622
- background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
608
+ background: ${({ theme, $variant = "neutral" }) => theme.colors[`${$variant}100`]};
623
609
  }
624
610
  `;
625
611
  const PencilIcon = styled(Pencil)`
626
- width: ${({ theme }) => theme.spaces[3]};
627
- height: ${({ theme }) => theme.spaces[3]};
612
+ width: ${({ theme }) => theme.spaces[4]};
613
+ height: ${({ theme }) => theme.spaces[4]};
628
614
  path {
629
615
  fill: ${({ theme }) => theme.colors.neutral600};
630
616
  }
631
617
  `;
632
618
  const TrashIcon = styled(Trash)`
633
- width: ${({ theme }) => theme.spaces[3]};
634
- height: ${({ theme }) => theme.spaces[3]};
619
+ width: ${({ theme }) => theme.spaces[4]};
620
+ height: ${({ theme }) => theme.spaces[4]};
635
621
  path {
636
622
  fill: ${({ theme }) => theme.colors.danger600};
637
623
  }
@@ -639,44 +625,93 @@ const TrashIcon = styled(Trash)`
639
625
  const TypographyMaxWidth = styled(Typography)`
640
626
  max-width: 300px;
641
627
  `;
642
- const EntryValidationText = ({ action, schema, entry }) => {
628
+ const EntryValidationText = ({ action, schema, entry, status }) => {
643
629
  const { formatMessage } = useIntl();
644
- const { validate } = unstable_useDocument(
630
+ const { validate, isLoading } = unstable_useDocument(
645
631
  {
646
632
  collectionType: schema?.kind ?? "",
647
633
  model: schema?.uid ?? ""
648
634
  },
649
635
  {
650
- skip: !schema
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
651
638
  }
652
639
  );
653
- const errors = validate(entry) ?? {};
654
- if (Object.keys(errors).length > 0) {
655
- const validationErrorsMessages = Object.entries(errors).map(
656
- ([key, value]) => formatMessage(
657
- { id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
658
- { field: key }
659
- )
660
- ).join(" ");
661
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
662
- /* @__PURE__ */ jsx(Icon, { color: "danger600", as: CrossCircle }),
663
- /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
664
- ] });
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;
665
666
  }
666
- if (action == "publish") {
667
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
668
- /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
669
- entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
670
- id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
671
- defaultMessage: "Already published"
672
- }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
673
- id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
674
- defaultMessage: "Ready to publish"
675
- }) })
676
- ] });
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
+ }
677
712
  }
678
713
  return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
679
- /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
714
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
680
715
  !entry.publishedAt ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
681
716
  id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
682
717
  defaultMessage: "Already unpublished"
@@ -696,7 +731,6 @@ const ReleaseDetailsLayout = ({
696
731
  const {
697
732
  data,
698
733
  isLoading: isLoadingDetails,
699
- isError,
700
734
  error
701
735
  } = useGetReleaseQuery(
702
736
  { id: releaseId },
@@ -705,11 +739,10 @@ const ReleaseDetailsLayout = ({
705
739
  }
706
740
  );
707
741
  const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();
708
- const toggleNotification = useNotification();
742
+ const { toggleNotification } = useNotification();
709
743
  const { formatAPIError } = useAPIErrorHandler();
710
- const {
711
- allowedActions: { canUpdate, canDelete }
712
- } = useRBAC(PERMISSIONS);
744
+ const { allowedActions } = useRBAC(PERMISSIONS);
745
+ const { canUpdate, canDelete, canPublish } = allowedActions;
713
746
  const dispatch = useTypedDispatch();
714
747
  const { trackUsage } = useTracking();
715
748
  const release = data?.data;
@@ -729,20 +762,25 @@ const ReleaseDetailsLayout = ({
729
762
  totalPublishedEntries,
730
763
  totalUnpublishedEntries
731
764
  });
732
- } else if (isAxiosError(response.error)) {
765
+ } else if (isFetchError(response.error)) {
733
766
  toggleNotification({
734
- type: "warning",
767
+ type: "danger",
735
768
  message: formatAPIError(response.error)
736
769
  });
737
770
  } else {
738
771
  toggleNotification({
739
- type: "warning",
772
+ type: "danger",
740
773
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
741
774
  });
742
775
  }
743
776
  };
744
777
  const handleRefresh = () => {
745
- dispatch(releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
778
+ dispatch(
779
+ releaseApi.util.invalidateTags([
780
+ { type: "ReleaseAction", id: "LIST" },
781
+ { type: "Release", id: releaseId }
782
+ ])
783
+ );
746
784
  };
747
785
  const getCreatedByUser = () => {
748
786
  if (!release?.createdBy) {
@@ -759,7 +797,7 @@ const ReleaseDetailsLayout = ({
759
797
  if (isLoadingDetails) {
760
798
  return /* @__PURE__ */ jsx(Page.Loading, {});
761
799
  }
762
- if (isError || !release) {
800
+ if (isBaseQueryError(error) && "code" in error || !release) {
763
801
  return /* @__PURE__ */ jsx(
764
802
  Navigate,
765
803
  {
@@ -767,6 +805,7 @@ const ReleaseDetailsLayout = ({
767
805
  state: {
768
806
  errors: [
769
807
  {
808
+ // @ts-expect-error – TODO: fix this weird error flow
770
809
  code: error?.code
771
810
  }
772
811
  ]
@@ -776,7 +815,6 @@ const ReleaseDetailsLayout = ({
776
815
  }
777
816
  const totalEntries = release.actions.meta.count || 0;
778
817
  const hasCreatedByUser = Boolean(getCreatedByUser());
779
- const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
780
818
  const isScheduled = release.scheduledAt && release.timezone;
781
819
  const numberOfEntriesText = formatMessage(
782
820
  {
@@ -807,101 +845,85 @@ const ReleaseDetailsLayout = ({
807
845
  ) : "";
808
846
  return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
809
847
  /* @__PURE__ */ jsx(
810
- HeaderLayout,
848
+ Layouts.Header,
811
849
  {
812
850
  title: release.name,
813
851
  subtitle: /* @__PURE__ */ jsxs(Flex, { gap: 2, lineHeight: 6, children: [
814
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", variant: "epsilon", children: numberOfEntriesText + (IsSchedulingEnabled && isScheduled ? ` - ${scheduledText}` : "") }),
852
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", variant: "epsilon", children: numberOfEntriesText + (isScheduled ? ` - ${scheduledText}` : "") }),
815
853
  /* @__PURE__ */ jsx(Badge, { ...getBadgeProps(release.status), children: release.status })
816
854
  ] }),
817
- navigationAction: /* @__PURE__ */ jsx(Link$1, { startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
818
- id: "global.back",
819
- defaultMessage: "Back"
820
- }) }),
855
+ navigationAction: /* @__PURE__ */ jsx(BackButton, {}),
821
856
  primaryAction: !release.releasedAt && /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
822
- /* @__PURE__ */ jsxs(Menu.Root, { children: [
823
- /* @__PURE__ */ jsx(
824
- Menu.Trigger,
825
- {
826
- as: IconButton,
827
- paddingLeft: 2,
828
- paddingRight: 2,
829
- "aria-label": formatMessage({
830
- id: "content-releases.header.actions.open-release-actions",
831
- defaultMessage: "Release edit and delete menu"
832
- }),
833
- icon: /* @__PURE__ */ jsx(More, {}),
834
- variant: "tertiary"
835
- }
836
- ),
837
- /* @__PURE__ */ jsxs(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: [
838
- /* @__PURE__ */ jsxs(
839
- Flex,
840
- {
841
- alignItems: "center",
842
- justifyContent: "center",
843
- direction: "column",
844
- padding: 1,
845
- width: "100%",
846
- children: [
847
- /* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
848
- /* @__PURE__ */ jsx(PencilIcon, {}),
849
- /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
850
- id: "content-releases.header.actions.edit",
851
- 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"
852
889
  }) })
853
- ] }) }),
854
- /* @__PURE__ */ jsx(
855
- StyledMenuItem,
856
- {
857
- disabled: !canDelete,
858
- onSelect: toggleWarningSubmit,
859
- variant: "danger",
860
- children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
861
- /* @__PURE__ */ jsx(TrashIcon, {}),
862
- /* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
863
- id: "content-releases.header.actions.delete",
864
- defaultMessage: "Delete"
865
- }) })
866
- ] })
867
- }
868
- )
869
- ]
870
- }
871
- ),
872
- /* @__PURE__ */ jsxs(
873
- ReleaseInfoWrapper,
874
- {
875
- direction: "column",
876
- justifyContent: "center",
877
- alignItems: "flex-start",
878
- gap: 1,
879
- padding: 5,
880
- children: [
881
- /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
882
- id: "content-releases.header.actions.created",
883
- defaultMessage: "Created"
884
- }) }),
885
- /* @__PURE__ */ jsxs(Typography, { variant: "pi", color: "neutral300", children: [
886
- /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(release.createdAt) }),
887
- formatMessage(
888
- {
889
- id: "content-releases.header.actions.created.description",
890
- defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
891
- },
892
- { createdBy: getCreatedByUser(), hasCreatedByUser }
893
- )
894
890
  ] })
895
- ]
896
- }
897
- )
898
- ] })
899
- ] }),
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
+ ),
900
922
  /* @__PURE__ */ jsx(Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
901
923
  id: "content-releases.header.actions.refresh",
902
924
  defaultMessage: "Refresh"
903
925
  }) }),
904
- /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.publish, children: /* @__PURE__ */ jsx(
926
+ canPublish ? /* @__PURE__ */ jsx(
905
927
  Button,
906
928
  {
907
929
  size: "S",
@@ -914,14 +936,20 @@ const ReleaseDetailsLayout = ({
914
936
  defaultMessage: "Publish"
915
937
  })
916
938
  }
917
- ) })
939
+ ) : null
918
940
  ] })
919
941
  }
920
942
  ),
921
943
  children
922
944
  ] });
923
945
  };
946
+ const SimpleMenuButton = styled(SimpleMenu)`
947
+ & > span {
948
+ display: flex;
949
+ }
950
+ `;
924
951
  const GROUP_BY_OPTIONS = ["contentType", "locale", "action"];
952
+ const GROUP_BY_OPTIONS_NO_LOCALE = ["contentType", "action"];
925
953
  const getGroupByOptionLabel = (value) => {
926
954
  if (value === "locale") {
927
955
  return {
@@ -943,17 +971,29 @@ const getGroupByOptionLabel = (value) => {
943
971
  const ReleaseDetailsBody = ({ releaseId }) => {
944
972
  const { formatMessage } = useIntl();
945
973
  const [{ query }, setQuery] = useQueryParams();
946
- const toggleNotification = useNotification();
974
+ const { toggleNotification } = useNotification();
947
975
  const { formatAPIError } = useAPIErrorHandler();
948
976
  const {
949
977
  data: releaseData,
950
978
  isLoading: isReleaseLoading,
951
- isError: isReleaseError,
952
979
  error: releaseError
953
980
  } = useGetReleaseQuery({ id: releaseId });
954
981
  const {
955
982
  allowedActions: { canUpdate }
956
983
  } = useRBAC(PERMISSIONS);
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
+ });
957
997
  const release = releaseData?.data;
958
998
  const selectedGroupBy = query?.groupBy || "contentType";
959
999
  const {
@@ -982,14 +1022,14 @@ const ReleaseDetailsBody = ({ releaseId }) => {
982
1022
  // We are passing the action path to found the position in the cache of the action for optimistic updates
983
1023
  });
984
1024
  if ("error" in response) {
985
- if (isAxiosError(response.error)) {
1025
+ if (isFetchError(response.error)) {
986
1026
  toggleNotification({
987
- type: "warning",
1027
+ type: "danger",
988
1028
  message: formatAPIError(response.error)
989
1029
  });
990
1030
  } else {
991
1031
  toggleNotification({
992
- type: "warning",
1032
+ type: "danger",
993
1033
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
994
1034
  });
995
1035
  }
@@ -1002,14 +1042,14 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1002
1042
  const releaseMeta = data?.meta;
1003
1043
  const contentTypes = releaseMeta?.contentTypes || {};
1004
1044
  const components = releaseMeta?.components || {};
1005
- if (isReleaseError || !release) {
1045
+ if (isBaseQueryError(releaseError) || !release) {
1006
1046
  const errorsArray = [];
1007
- if (releaseError) {
1047
+ if (releaseError && "code" in releaseError) {
1008
1048
  errorsArray.push({
1009
1049
  code: releaseError.code
1010
1050
  });
1011
1051
  }
1012
- if (releaseActionsError) {
1052
+ if (releaseActionsError && "code" in releaseActionsError) {
1013
1053
  errorsArray.push({
1014
1054
  code: releaseActionsError.code
1015
1055
  });
@@ -1028,13 +1068,13 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1028
1068
  return /* @__PURE__ */ jsx(Page.Error, {});
1029
1069
  }
1030
1070
  if (Object.keys(releaseActions).length === 0) {
1031
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(
1071
+ return /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsx(
1032
1072
  EmptyStateLayout,
1033
1073
  {
1034
1074
  action: /* @__PURE__ */ jsx(
1035
1075
  LinkButton,
1036
1076
  {
1037
- as: Link$2,
1077
+ tag: Link$1,
1038
1078
  to: {
1039
1079
  pathname: "/content-manager"
1040
1080
  },
@@ -1046,7 +1086,7 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1046
1086
  })
1047
1087
  }
1048
1088
  ),
1049
- icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem" }),
1089
+ icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "16rem" }),
1050
1090
  content: formatMessage({
1051
1091
  id: "content-releases.pages.Details.tab.emptyEntries",
1052
1092
  defaultMessage: "This release is empty. Open the Content Manager, select an entry and add it to the release."
@@ -1054,14 +1094,43 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1054
1094
  }
1055
1095
  ) });
1056
1096
  }
1057
- return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
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
+ ];
1127
+ const options = hasI18nEnabled ? GROUP_BY_OPTIONS : GROUP_BY_OPTIONS_NO_LOCALE;
1128
+ return /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
1058
1129
  /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
1059
1130
  SingleSelect,
1060
1131
  {
1061
- "aria-label": formatMessage({
1062
- id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
1063
- defaultMessage: "Group by"
1064
- }),
1132
+ placeholder: groupByLabel,
1133
+ "aria-label": groupByLabel,
1065
1134
  customizeContent: (value) => formatMessage(
1066
1135
  {
1067
1136
  id: `content-releases.pages.ReleaseDetails.groupBy.label`,
@@ -1073,7 +1142,7 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1073
1142
  ),
1074
1143
  value: formatMessage(getGroupByOptionLabel(selectedGroupBy)),
1075
1144
  onChange: (value) => setQuery({ groupBy: value }),
1076
- children: GROUP_BY_OPTIONS.map((option) => /* @__PURE__ */ jsx(SingleSelectOption, { value: option, children: formatMessage(getGroupByOptionLabel(option)) }, option))
1145
+ children: options.map((option) => /* @__PURE__ */ jsx(SingleSelectOption, { value: option, children: formatMessage(getGroupByOptionLabel(option)) }, option))
1077
1146
  }
1078
1147
  ) }),
1079
1148
  Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
@@ -1085,72 +1154,15 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1085
1154
  ...item,
1086
1155
  id: Number(item.entry.id)
1087
1156
  })),
1088
- colCount: releaseActions[key].length,
1089
- isLoading,
1090
- isFetching,
1157
+ headers,
1158
+ isLoading: isLoading || isFetching,
1091
1159
  children: /* @__PURE__ */ jsxs(Table.Content, { children: [
1092
- /* @__PURE__ */ jsxs(Table.Head, { children: [
1093
- /* @__PURE__ */ jsx(
1094
- Table.HeaderCell,
1095
- {
1096
- attribute: { type: "string" },
1097
- label: formatMessage({
1098
- id: "content-releases.page.ReleaseDetails.table.header.label.name",
1099
- defaultMessage: "name"
1100
- }),
1101
- name: "name"
1102
- }
1103
- ),
1104
- /* @__PURE__ */ jsx(
1105
- Table.HeaderCell,
1106
- {
1107
- attribute: { type: "string" },
1108
- label: formatMessage({
1109
- id: "content-releases.page.ReleaseDetails.table.header.label.locale",
1110
- defaultMessage: "locale"
1111
- }),
1112
- name: "locale"
1113
- }
1114
- ),
1115
- /* @__PURE__ */ jsx(
1116
- Table.HeaderCell,
1117
- {
1118
- attribute: { type: "string" },
1119
- label: formatMessage({
1120
- id: "content-releases.page.ReleaseDetails.table.header.label.content-type",
1121
- defaultMessage: "content-type"
1122
- }),
1123
- name: "content-type"
1124
- }
1125
- ),
1126
- /* @__PURE__ */ jsx(
1127
- Table.HeaderCell,
1128
- {
1129
- attribute: { type: "string" },
1130
- label: formatMessage({
1131
- id: "content-releases.page.ReleaseDetails.table.header.label.action",
1132
- defaultMessage: "action"
1133
- }),
1134
- name: "action"
1135
- }
1136
- ),
1137
- !release.releasedAt && /* @__PURE__ */ jsx(
1138
- Table.HeaderCell,
1139
- {
1140
- attribute: { type: "string" },
1141
- label: formatMessage({
1142
- id: "content-releases.page.ReleaseDetails.table.header.label.status",
1143
- defaultMessage: "status"
1144
- }),
1145
- name: "status"
1146
- }
1147
- )
1148
- ] }),
1149
- /* @__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, {}),
1150
1162
  /* @__PURE__ */ jsx(Table.Body, { children: releaseActions[key].map(
1151
- ({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxs(Tr, { children: [
1163
+ ({ id, contentType, locale, type, entry, status }, actionIndex) => /* @__PURE__ */ jsxs(Tr, { children: [
1152
1164
  /* @__PURE__ */ jsx(Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
1153
- /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
1165
+ hasI18nEnabled && /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
1154
1166
  /* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: contentType.displayName || "" }) }),
1155
1167
  /* @__PURE__ */ jsx(Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsx(Typography, { children: formatMessage(
1156
1168
  {
@@ -1177,7 +1189,8 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1177
1189
  action: type,
1178
1190
  schema: contentTypes?.[contentType.uid],
1179
1191
  components,
1180
- entry
1192
+ entry,
1193
+ status
1181
1194
  }
1182
1195
  ) }),
1183
1196
  /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { children: [
@@ -1185,7 +1198,7 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1185
1198
  ReleaseActionMenu.ReleaseActionEntryLinkItem,
1186
1199
  {
1187
1200
  contentTypeUid: contentType.uid,
1188
- entryId: entry.id,
1201
+ documentId: entry.documentId,
1189
1202
  locale: locale?.code
1190
1203
  }
1191
1204
  ),
@@ -1220,7 +1233,7 @@ const ReleaseDetailsBody = ({ releaseId }) => {
1220
1233
  const ReleaseDetailsPage = () => {
1221
1234
  const { formatMessage } = useIntl();
1222
1235
  const { releaseId } = useParams();
1223
- const toggleNotification = useNotification();
1236
+ const { toggleNotification } = useNotification();
1224
1237
  const { formatAPIError } = useAPIErrorHandler();
1225
1238
  const navigate = useNavigate();
1226
1239
  const [releaseModalShown, setReleaseModalShown] = React.useState(false);
@@ -1235,13 +1248,24 @@ const ReleaseDetailsPage = () => {
1235
1248
  skip: !releaseId
1236
1249
  }
1237
1250
  );
1251
+ const { data: dataTimezone, isLoading: isLoadingTimezone } = useGetReleaseSettingsQuery();
1238
1252
  const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();
1239
- const [deleteRelease, { isLoading: isDeletingRelease }] = useDeleteReleaseMutation();
1253
+ const [deleteRelease] = useDeleteReleaseMutation();
1240
1254
  const toggleEditReleaseModal = () => {
1241
1255
  setReleaseModalShown((prev) => !prev);
1242
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
+ };
1243
1267
  const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);
1244
- if (isLoadingDetails) {
1268
+ if (isLoadingDetails || isLoadingTimezone) {
1245
1269
  return /* @__PURE__ */ jsx(
1246
1270
  ReleaseDetailsLayout,
1247
1271
  {
@@ -1256,10 +1280,10 @@ const ReleaseDetailsPage = () => {
1256
1280
  }
1257
1281
  const releaseData = isSuccessDetails && data?.data || null;
1258
1282
  const title = releaseData?.name || "";
1259
- const timezone = releaseData?.timezone ?? null;
1283
+ const timezone = getTimezoneValue();
1260
1284
  const scheduledAt = releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;
1261
- const date = scheduledAt ? new Date(format(scheduledAt, "yyyy-MM-dd")) : null;
1262
- 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") : "";
1263
1287
  const handleEditRelease = async (values) => {
1264
1288
  const response = await updateRelease({
1265
1289
  id: releaseId,
@@ -1275,18 +1299,18 @@ const ReleaseDetailsPage = () => {
1275
1299
  defaultMessage: "Release updated."
1276
1300
  })
1277
1301
  });
1278
- } else if (isAxiosError(response.error)) {
1302
+ toggleEditReleaseModal();
1303
+ } else if (isFetchError(response.error)) {
1279
1304
  toggleNotification({
1280
- type: "warning",
1305
+ type: "danger",
1281
1306
  message: formatAPIError(response.error)
1282
1307
  });
1283
1308
  } else {
1284
1309
  toggleNotification({
1285
- type: "warning",
1310
+ type: "danger",
1286
1311
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1287
1312
  });
1288
1313
  }
1289
- toggleEditReleaseModal();
1290
1314
  };
1291
1315
  const handleDeleteRelease = async () => {
1292
1316
  const response = await deleteRelease({
@@ -1294,14 +1318,14 @@ const ReleaseDetailsPage = () => {
1294
1318
  });
1295
1319
  if ("data" in response) {
1296
1320
  navigate("..");
1297
- } else if (isAxiosError(response.error)) {
1321
+ } else if (isFetchError(response.error)) {
1298
1322
  toggleNotification({
1299
- type: "warning",
1323
+ type: "danger",
1300
1324
  message: formatAPIError(response.error)
1301
1325
  });
1302
1326
  } else {
1303
1327
  toggleNotification({
1304
- type: "warning",
1328
+ type: "danger",
1305
1329
  message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
1306
1330
  });
1307
1331
  }
@@ -1313,9 +1337,10 @@ const ReleaseDetailsPage = () => {
1313
1337
  toggleWarningSubmit,
1314
1338
  children: [
1315
1339
  /* @__PURE__ */ jsx(ReleaseDetailsBody, { releaseId }),
1316
- releaseModalShown && /* @__PURE__ */ jsx(
1340
+ /* @__PURE__ */ jsx(
1317
1341
  ReleaseModal,
1318
1342
  {
1343
+ open: releaseModalShown,
1319
1344
  handleClose: toggleEditReleaseModal,
1320
1345
  handleSubmit: handleEditRelease,
1321
1346
  isLoading: isLoadingDetails || isSubmittingForm,
@@ -1329,19 +1354,10 @@ const ReleaseDetailsPage = () => {
1329
1354
  }
1330
1355
  }
1331
1356
  ),
1332
- /* @__PURE__ */ jsx(
1333
- ConfirmDialog,
1334
- {
1335
- bodyText: {
1336
- id: "content-releases.dialog.confirmation-message",
1337
- defaultMessage: "Are you sure you want to delete this release?"
1338
- },
1339
- isOpen: showWarningSubmit,
1340
- isConfirmButtonLoading: isDeletingRelease,
1341
- onToggleDialog: toggleWarningSubmit,
1342
- onConfirm: handleDeleteRelease
1343
- }
1344
- )
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
+ }) }) })
1345
1361
  ]
1346
1362
  }
1347
1363
  );
@@ -1355,4 +1371,4 @@ const App = () => {
1355
1371
  export {
1356
1372
  App
1357
1373
  };
1358
- //# sourceMappingURL=App-0Er6xxcq.mjs.map
1374
+ //# sourceMappingURL=App-Cne--1Z8.mjs.map