@strapi/content-releases 0.0.0-next.44f19b3d2f81d983c343a219aa2781ee0deecb5f → 0.0.0-next.4af8963f6880c5fb9fae32ecd580f5cd33eaddda

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 (29) hide show
  1. package/dist/_chunks/{App-3ycH2d3s.mjs → App-ise7GunC.mjs} +365 -154
  2. package/dist/_chunks/App-ise7GunC.mjs.map +1 -0
  3. package/dist/_chunks/{App-5PsAyVt2.js → App-w2Zq-wj5.js} +363 -151
  4. package/dist/_chunks/App-w2Zq-wj5.js.map +1 -0
  5. package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs +51 -0
  6. package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +1 -0
  7. package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js +51 -0
  8. package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +1 -0
  9. package/dist/_chunks/{en-2DuPv5k0.js → en-7P4i1cWH.js} +11 -3
  10. package/dist/_chunks/en-7P4i1cWH.js.map +1 -0
  11. package/dist/_chunks/{en-SOqjCdyh.mjs → en-pb1wUzhy.mjs} +11 -3
  12. package/dist/_chunks/en-pb1wUzhy.mjs.map +1 -0
  13. package/dist/_chunks/{index-4gUWuCQV.mjs → index-D-Yjf60c.mjs} +57 -16
  14. package/dist/_chunks/index-D-Yjf60c.mjs.map +1 -0
  15. package/dist/_chunks/{index-D57Rztnc.js → index-Q8Pv7enO.js} +57 -16
  16. package/dist/_chunks/index-Q8Pv7enO.js.map +1 -0
  17. package/dist/admin/index.js +1 -1
  18. package/dist/admin/index.mjs +1 -1
  19. package/dist/server/index.js +573 -403
  20. package/dist/server/index.js.map +1 -1
  21. package/dist/server/index.mjs +573 -403
  22. package/dist/server/index.mjs.map +1 -1
  23. package/package.json +12 -9
  24. package/dist/_chunks/App-3ycH2d3s.mjs.map +0 -1
  25. package/dist/_chunks/App-5PsAyVt2.js.map +0 -1
  26. package/dist/_chunks/en-2DuPv5k0.js.map +0 -1
  27. package/dist/_chunks/en-SOqjCdyh.mjs.map +0 -1
  28. package/dist/_chunks/index-4gUWuCQV.mjs.map +0 -1
  29. package/dist/_chunks/index-D57Rztnc.js.map +0 -1
@@ -3,14 +3,17 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const helperPlugin = require("@strapi/helper-plugin");
5
5
  const reactRouterDom = require("react-router-dom");
6
- const index = require("./index-D57Rztnc.js");
6
+ const index = require("./index-Q8Pv7enO.js");
7
7
  const React = require("react");
8
8
  const strapiAdmin = require("@strapi/admin/strapi-admin");
9
9
  const designSystem = require("@strapi/design-system");
10
10
  const v2 = require("@strapi/design-system/v2");
11
11
  const icons = require("@strapi/icons");
12
+ const format = require("date-fns/format");
13
+ const dateFnsTz = require("date-fns-tz");
12
14
  const reactIntl = require("react-intl");
13
15
  const styled = require("styled-components");
16
+ const dateFns = require("date-fns");
14
17
  const formik = require("formik");
15
18
  const yup = require("yup");
16
19
  require("@reduxjs/toolkit/query");
@@ -37,10 +40,28 @@ function _interopNamespace(e) {
37
40
  return Object.freeze(n);
38
41
  }
39
42
  const React__namespace = /* @__PURE__ */ _interopNamespace(React);
43
+ const format__default = /* @__PURE__ */ _interopDefault(format);
40
44
  const styled__default = /* @__PURE__ */ _interopDefault(styled);
41
45
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
42
46
  const RELEASE_SCHEMA = yup__namespace.object().shape({
43
- name: yup__namespace.string().trim().required()
47
+ name: yup__namespace.string().trim().required(),
48
+ scheduledAt: yup__namespace.string().nullable(),
49
+ isScheduled: yup__namespace.boolean().optional(),
50
+ time: yup__namespace.string().when("isScheduled", {
51
+ is: true,
52
+ then: yup__namespace.string().trim().required(),
53
+ otherwise: yup__namespace.string().nullable()
54
+ }),
55
+ timezone: yup__namespace.string().when("isScheduled", {
56
+ is: true,
57
+ then: yup__namespace.string().required().nullable(),
58
+ otherwise: yup__namespace.string().nullable()
59
+ }),
60
+ date: yup__namespace.string().when("isScheduled", {
61
+ is: true,
62
+ then: yup__namespace.string().required().nullable(),
63
+ otherwise: yup__namespace.string().nullable()
64
+ })
44
65
  }).required().noUnknown();
45
66
  const ReleaseModal = ({
46
67
  handleClose,
@@ -51,6 +72,24 @@ const ReleaseModal = ({
51
72
  const { formatMessage } = reactIntl.useIntl();
52
73
  const { pathname } = reactRouterDom.useLocation();
53
74
  const isCreatingRelease = pathname === `/plugins/${index.pluginId}`;
75
+ const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
76
+ const { timezoneList, systemTimezone = { value: "UTC+00:00-Africa/Abidjan " } } = getTimezones(
77
+ initialValues.scheduledAt ? new Date(initialValues.scheduledAt) : /* @__PURE__ */ new Date()
78
+ );
79
+ const getScheduledTimestamp = (values) => {
80
+ const { date, time, timezone } = values;
81
+ if (!date || !time || !timezone)
82
+ return null;
83
+ const formattedDate = dateFns.parse(time, "HH:mm", new Date(date));
84
+ const timezoneWithoutOffset = timezone.split("-")[1];
85
+ return dateFnsTz.zonedTimeToUtc(formattedDate, timezoneWithoutOffset);
86
+ };
87
+ const getTimezoneWithOffset = () => {
88
+ const currentTimezone = timezoneList.find(
89
+ (timezone) => timezone.value.split("-")[1] === initialValues.timezone
90
+ );
91
+ return currentTimezone?.value || systemTimezone.value;
92
+ };
54
93
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
55
94
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage(
56
95
  {
@@ -62,45 +101,134 @@ const ReleaseModal = ({
62
101
  /* @__PURE__ */ jsxRuntime.jsx(
63
102
  formik.Formik,
64
103
  {
65
- validateOnChange: false,
66
- onSubmit: handleSubmit,
67
- initialValues,
104
+ onSubmit: (values) => {
105
+ handleSubmit({
106
+ ...values,
107
+ timezone: values.timezone ? values.timezone.split("-")[1] : null,
108
+ scheduledAt: values.isScheduled ? getScheduledTimestamp(values) : null
109
+ });
110
+ },
111
+ initialValues: {
112
+ ...initialValues,
113
+ timezone: initialValues.timezone ? getTimezoneWithOffset() : systemTimezone.value
114
+ },
68
115
  validationSchema: RELEASE_SCHEMA,
69
- children: ({ values, errors, handleChange }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
70
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: /* @__PURE__ */ jsxRuntime.jsx(
71
- designSystem.TextInput,
72
- {
73
- label: formatMessage({
74
- id: "content-releases.modal.form.input.label.release-name",
75
- defaultMessage: "Name"
76
- }),
77
- name: "name",
78
- value: values.name,
79
- error: errors.name,
80
- onChange: handleChange,
81
- required: true
82
- }
83
- ) }),
116
+ validateOnChange: false,
117
+ children: ({ values, errors, handleChange, setFieldValue }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
118
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
119
+ /* @__PURE__ */ jsxRuntime.jsx(
120
+ designSystem.TextInput,
121
+ {
122
+ label: formatMessage({
123
+ id: "content-releases.modal.form.input.label.release-name",
124
+ defaultMessage: "Name"
125
+ }),
126
+ name: "name",
127
+ value: values.name,
128
+ error: errors.name,
129
+ onChange: handleChange,
130
+ required: true
131
+ }
132
+ ),
133
+ IsSchedulingEnabled && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
134
+ /* @__PURE__ */ jsxRuntime.jsx(
135
+ designSystem.Checkbox,
136
+ {
137
+ name: "isScheduled",
138
+ value: values.isScheduled,
139
+ onChange: (event) => {
140
+ setFieldValue("isScheduled", event.target.checked);
141
+ if (!event.target.checked) {
142
+ setFieldValue("date", null);
143
+ setFieldValue("time", "");
144
+ setFieldValue("timezone", null);
145
+ } else {
146
+ setFieldValue("date", initialValues.date);
147
+ setFieldValue("time", initialValues.time);
148
+ setFieldValue(
149
+ "timezone",
150
+ initialValues.timezone ?? systemTimezone?.value
151
+ );
152
+ }
153
+ },
154
+ children: /* @__PURE__ */ jsxRuntime.jsx(
155
+ designSystem.Typography,
156
+ {
157
+ textColor: values.isScheduled ? "primary600" : "neutral800",
158
+ fontWeight: values.isScheduled ? "semiBold" : "regular",
159
+ children: formatMessage({
160
+ id: "modal.form.input.label.schedule-release",
161
+ defaultMessage: "Schedule release"
162
+ })
163
+ }
164
+ )
165
+ }
166
+ ),
167
+ values.isScheduled && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
168
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, alignItems: "start", children: [
169
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
170
+ designSystem.DatePicker,
171
+ {
172
+ label: formatMessage({
173
+ id: "content-releases.modal.form.input.label.date",
174
+ defaultMessage: "Date"
175
+ }),
176
+ name: "date",
177
+ error: errors.date,
178
+ onChange: (date) => {
179
+ const isoFormatDate = date ? dateFns.formatISO(date, { representation: "date" }) : null;
180
+ setFieldValue("date", isoFormatDate);
181
+ },
182
+ clearLabel: formatMessage({
183
+ id: "content-releases.modal.form.input.clearLabel",
184
+ defaultMessage: "Clear"
185
+ }),
186
+ onClear: () => {
187
+ setFieldValue("date", null);
188
+ },
189
+ selectedDate: values.date || void 0,
190
+ required: true
191
+ }
192
+ ) }),
193
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
194
+ designSystem.TimePicker,
195
+ {
196
+ label: formatMessage({
197
+ id: "content-releases.modal.form.input.label.time",
198
+ defaultMessage: "Time"
199
+ }),
200
+ name: "time",
201
+ error: errors.time,
202
+ onChange: (time) => {
203
+ setFieldValue("time", time);
204
+ },
205
+ clearLabel: formatMessage({
206
+ id: "content-releases.modal.form.input.clearLabel",
207
+ defaultMessage: "Clear"
208
+ }),
209
+ onClear: () => {
210
+ setFieldValue("time", "");
211
+ },
212
+ value: values.time || void 0,
213
+ required: true
214
+ }
215
+ ) })
216
+ ] }),
217
+ /* @__PURE__ */ jsxRuntime.jsx(TimezoneComponent, { timezoneOptions: timezoneList })
218
+ ] })
219
+ ] })
220
+ ] }) }),
84
221
  /* @__PURE__ */ jsxRuntime.jsx(
85
222
  designSystem.ModalFooter,
86
223
  {
87
224
  startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }),
88
- endActions: /* @__PURE__ */ jsxRuntime.jsx(
89
- designSystem.Button,
225
+ endActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { name: "submit", loading: isLoading, type: "submit", children: formatMessage(
90
226
  {
91
- name: "submit",
92
- loading: isLoading,
93
- disabled: !values.name || values.name === initialValues.name,
94
- type: "submit",
95
- children: formatMessage(
96
- {
97
- id: "content-releases.modal.form.button.submit",
98
- defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
99
- },
100
- { isCreatingRelease }
101
- )
102
- }
103
- )
227
+ id: "content-releases.modal.form.button.submit",
228
+ defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
229
+ },
230
+ { isCreatingRelease }
231
+ ) })
104
232
  }
105
233
  )
106
234
  ] })
@@ -108,16 +236,67 @@ const ReleaseModal = ({
108
236
  )
109
237
  ] });
110
238
  };
239
+ const getTimezones = (selectedDate) => {
240
+ const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
241
+ const offsetPart = new Intl.DateTimeFormat("en", {
242
+ timeZone: timezone,
243
+ timeZoneName: "longOffset"
244
+ }).formatToParts(selectedDate).find((part) => part.type === "timeZoneName");
245
+ const offset = offsetPart ? offsetPart.value : "";
246
+ let utcOffset = offset.replace("GMT", "UTC");
247
+ if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
248
+ utcOffset = `${utcOffset}+00:00`;
249
+ }
250
+ return { offset: utcOffset, value: `${utcOffset}-${timezone}` };
251
+ });
252
+ const systemTimezone = timezoneList.find(
253
+ (timezone) => timezone.value.split("-")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
254
+ );
255
+ return { timezoneList, systemTimezone };
256
+ };
257
+ const TimezoneComponent = ({ timezoneOptions }) => {
258
+ const { values, errors, setFieldValue } = formik.useFormikContext();
259
+ const { formatMessage } = reactIntl.useIntl();
260
+ const [timezoneList, setTimezoneList] = React__namespace.useState(timezoneOptions);
261
+ React__namespace.useEffect(() => {
262
+ if (values.date) {
263
+ const { timezoneList: timezoneList2 } = getTimezones(new Date(values.date));
264
+ setTimezoneList(timezoneList2);
265
+ const updatedTimezone = values.timezone && timezoneList2.find((tz) => tz.value.split("-")[1] === values.timezone.split("-")[1]);
266
+ if (updatedTimezone) {
267
+ setFieldValue("timezone", updatedTimezone.value);
268
+ }
269
+ }
270
+ }, [setFieldValue, values.date, values.timezone]);
271
+ return /* @__PURE__ */ jsxRuntime.jsx(
272
+ designSystem.Combobox,
273
+ {
274
+ label: formatMessage({
275
+ id: "content-releases.modal.form.input.label.timezone",
276
+ defaultMessage: "Timezone"
277
+ }),
278
+ name: "timezone",
279
+ value: values.timezone || void 0,
280
+ textValue: values.timezone ? values.timezone.replace("-", " ") : void 0,
281
+ onChange: (timezone) => {
282
+ setFieldValue("timezone", timezone);
283
+ },
284
+ onClear: () => {
285
+ setFieldValue("timezone", "");
286
+ },
287
+ error: errors.timezone,
288
+ required: true,
289
+ children: timezoneList.map((timezone) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: timezone.value, children: timezone.value.replace("-", " ") }, timezone.value))
290
+ }
291
+ );
292
+ };
111
293
  const ReleaseInfoWrapper = styled__default.default(designSystem.Flex)`
112
294
  align-self: stretch;
113
295
  border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
114
296
  border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
115
297
  border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
116
298
  `;
117
- const StyledFlex = styled__default.default(designSystem.Flex)`
118
- align-self: stretch;
119
- cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
120
-
299
+ const StyledMenuItem = styled__default.default(v2.Menu.Item)`
121
300
  svg path {
122
301
  fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
123
302
  }
@@ -126,15 +305,15 @@ const StyledFlex = styled__default.default(designSystem.Flex)`
126
305
  }
127
306
  `;
128
307
  const PencilIcon = styled__default.default(icons.Pencil)`
129
- width: ${({ theme }) => theme.spaces[4]};
130
- height: ${({ theme }) => theme.spaces[4]};
308
+ width: ${({ theme }) => theme.spaces[3]};
309
+ height: ${({ theme }) => theme.spaces[3]};
131
310
  path {
132
311
  fill: ${({ theme }) => theme.colors.neutral600};
133
312
  }
134
313
  `;
135
314
  const TrashIcon = styled__default.default(icons.Trash)`
136
- width: ${({ theme }) => theme.spaces[4]};
137
- height: ${({ theme }) => theme.spaces[4]};
315
+ width: ${({ theme }) => theme.spaces[3]};
316
+ height: ${({ theme }) => theme.spaces[3]};
138
317
  path {
139
318
  fill: ${({ theme }) => theme.colors.danger600};
140
319
  }
@@ -142,24 +321,6 @@ const TrashIcon = styled__default.default(icons.Trash)`
142
321
  const TypographyMaxWidth = styled__default.default(designSystem.Typography)`
143
322
  max-width: 300px;
144
323
  `;
145
- const PopoverButton = ({ onClick, disabled, children }) => {
146
- return /* @__PURE__ */ jsxRuntime.jsx(
147
- StyledFlex,
148
- {
149
- paddingTop: 2,
150
- paddingBottom: 2,
151
- paddingLeft: 4,
152
- paddingRight: 4,
153
- alignItems: "center",
154
- gap: 2,
155
- as: "button",
156
- hasRadius: true,
157
- onClick,
158
- disabled,
159
- children
160
- }
161
- );
162
- };
163
324
  const EntryValidationText = ({ action, schema, components, entry }) => {
164
325
  const { formatMessage } = reactIntl.useIntl();
165
326
  const { validate } = strapiAdmin.unstable_useDocument();
@@ -210,8 +371,6 @@ const ReleaseDetailsLayout = ({
210
371
  }) => {
211
372
  const { formatMessage } = reactIntl.useIntl();
212
373
  const { releaseId } = reactRouterDom.useParams();
213
- const [isPopoverVisible, setIsPopoverVisible] = React__namespace.useState(false);
214
- const moreButtonRef = React__namespace.useRef(null);
215
374
  const {
216
375
  data,
217
376
  isLoading: isLoadingDetails,
@@ -227,13 +386,6 @@ const ReleaseDetailsLayout = ({
227
386
  const dispatch = index.useTypedDispatch();
228
387
  const { trackUsage } = helperPlugin.useTracking();
229
388
  const release = data?.data;
230
- const handleTogglePopover = () => {
231
- setIsPopoverVisible((prev) => !prev);
232
- };
233
- const openReleaseModal = () => {
234
- toggleEditReleaseModal();
235
- handleTogglePopover();
236
- };
237
389
  const handlePublishRelease = async () => {
238
390
  const response = await publishRelease({ id: releaseId });
239
391
  if ("data" in response) {
@@ -262,13 +414,21 @@ const ReleaseDetailsLayout = ({
262
414
  });
263
415
  }
264
416
  };
265
- const openWarningConfirmDialog = () => {
266
- toggleWarningSubmit();
267
- handleTogglePopover();
268
- };
269
417
  const handleRefresh = () => {
270
418
  dispatch(index.releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
271
419
  };
420
+ const getCreatedByUser = () => {
421
+ if (!release?.createdBy) {
422
+ return null;
423
+ }
424
+ if (release.createdBy.username) {
425
+ return release.createdBy.username;
426
+ }
427
+ if (release.createdBy.firstname) {
428
+ return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
429
+ }
430
+ return release.createdBy.email;
431
+ };
272
432
  if (isLoadingDetails) {
273
433
  return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
274
434
  }
@@ -290,7 +450,7 @@ const ReleaseDetailsLayout = ({
290
450
  );
291
451
  }
292
452
  const totalEntries = release.actions.meta.count || 0;
293
- const createdBy = release.createdBy.lastname ? `${release.createdBy.firstname} ${release.createdBy.lastname}` : `${release.createdBy.firstname}`;
453
+ const hasCreatedByUser = Boolean(getCreatedByUser());
294
454
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoadingDetails, children: [
295
455
  /* @__PURE__ */ jsxRuntime.jsx(
296
456
  designSystem.HeaderLayout,
@@ -308,72 +468,98 @@ const ReleaseDetailsLayout = ({
308
468
  defaultMessage: "Back"
309
469
  }) }),
310
470
  primaryAction: !release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
311
- /* @__PURE__ */ jsxRuntime.jsx(
312
- designSystem.IconButton,
313
- {
314
- label: formatMessage({
315
- id: "content-releases.header.actions.open-release-actions",
316
- defaultMessage: "Release actions"
317
- }),
318
- ref: moreButtonRef,
319
- onClick: handleTogglePopover,
320
- children: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {})
321
- }
322
- ),
323
- isPopoverVisible && /* @__PURE__ */ jsxRuntime.jsxs(
324
- designSystem.Popover,
325
- {
326
- source: moreButtonRef,
327
- placement: "bottom-end",
328
- onDismiss: handleTogglePopover,
329
- spacing: 4,
330
- minWidth: "242px",
331
- children: [
332
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", justifyContent: "center", direction: "column", padding: 1, children: [
333
- /* @__PURE__ */ jsxRuntime.jsxs(PopoverButton, { disabled: !canUpdate, onClick: openReleaseModal, children: [
334
- /* @__PURE__ */ jsxRuntime.jsx(PencilIcon, {}),
335
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: formatMessage({
336
- id: "content-releases.header.actions.edit",
337
- defaultMessage: "Edit"
338
- }) })
339
- ] }),
340
- /* @__PURE__ */ jsxRuntime.jsxs(PopoverButton, { disabled: !canDelete, onClick: openWarningConfirmDialog, children: [
341
- /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {}),
342
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
343
- id: "content-releases.header.actions.delete",
344
- defaultMessage: "Delete"
345
- }) })
346
- ] })
347
- ] }),
348
- /* @__PURE__ */ jsxRuntime.jsxs(
349
- ReleaseInfoWrapper,
350
- {
351
- direction: "column",
352
- justifyContent: "center",
353
- alignItems: "flex-start",
354
- gap: 1,
355
- padding: 5,
356
- children: [
357
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
358
- id: "content-releases.header.actions.created",
359
- defaultMessage: "Created"
360
- }) }),
361
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", color: "neutral300", children: [
362
- /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.RelativeTime, { timestamp: new Date(release.createdAt) }),
363
- formatMessage(
364
- {
365
- id: "content-releases.header.actions.created.description",
366
- defaultMessage: " by {createdBy}"
367
- },
368
- { createdBy }
369
- )
370
- ] })
371
- ]
372
- }
373
- )
374
- ]
375
- }
376
- ),
471
+ /* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Root, { children: [
472
+ /* @__PURE__ */ jsxRuntime.jsx(
473
+ v2.Menu.Trigger,
474
+ {
475
+ as: designSystem.IconButton,
476
+ paddingLeft: 2,
477
+ paddingRight: 2,
478
+ "aria-label": formatMessage({
479
+ id: "content-releases.header.actions.open-release-actions",
480
+ defaultMessage: "Release edit and delete menu"
481
+ }),
482
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {}),
483
+ variant: "tertiary"
484
+ }
485
+ ),
486
+ /* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: [
487
+ /* @__PURE__ */ jsxRuntime.jsxs(
488
+ designSystem.Flex,
489
+ {
490
+ alignItems: "center",
491
+ justifyContent: "center",
492
+ direction: "column",
493
+ padding: 1,
494
+ width: "100%",
495
+ children: [
496
+ /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxRuntime.jsxs(
497
+ designSystem.Flex,
498
+ {
499
+ paddingTop: 2,
500
+ paddingBottom: 2,
501
+ alignItems: "center",
502
+ gap: 2,
503
+ hasRadius: true,
504
+ width: "100%",
505
+ children: [
506
+ /* @__PURE__ */ jsxRuntime.jsx(PencilIcon, {}),
507
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: formatMessage({
508
+ id: "content-releases.header.actions.edit",
509
+ defaultMessage: "Edit"
510
+ }) })
511
+ ]
512
+ }
513
+ ) }),
514
+ /* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canDelete, onSelect: toggleWarningSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(
515
+ designSystem.Flex,
516
+ {
517
+ paddingTop: 2,
518
+ paddingBottom: 2,
519
+ alignItems: "center",
520
+ gap: 2,
521
+ hasRadius: true,
522
+ width: "100%",
523
+ children: [
524
+ /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {}),
525
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
526
+ id: "content-releases.header.actions.delete",
527
+ defaultMessage: "Delete"
528
+ }) })
529
+ ]
530
+ }
531
+ ) })
532
+ ]
533
+ }
534
+ ),
535
+ /* @__PURE__ */ jsxRuntime.jsxs(
536
+ ReleaseInfoWrapper,
537
+ {
538
+ direction: "column",
539
+ justifyContent: "center",
540
+ alignItems: "flex-start",
541
+ gap: 1,
542
+ padding: 5,
543
+ children: [
544
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
545
+ id: "content-releases.header.actions.created",
546
+ defaultMessage: "Created"
547
+ }) }),
548
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", color: "neutral300", children: [
549
+ /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.RelativeTime, { timestamp: new Date(release.createdAt) }),
550
+ formatMessage(
551
+ {
552
+ id: "content-releases.header.actions.created.description",
553
+ defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
554
+ },
555
+ { createdBy: getCreatedByUser(), hasCreatedByUser }
556
+ )
557
+ ] })
558
+ ]
559
+ }
560
+ )
561
+ ] })
562
+ ] }),
377
563
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
378
564
  id: "content-releases.header.actions.refresh",
379
565
  defaultMessage: "Refresh"
@@ -429,6 +615,9 @@ const ReleaseDetailsBody = () => {
429
615
  isError: isReleaseError,
430
616
  error: releaseError
431
617
  } = index.useGetReleaseQuery({ id: releaseId });
618
+ const {
619
+ allowedActions: { canUpdate }
620
+ } = helperPlugin.useRBAC(index.PERMISSIONS);
432
621
  const release = releaseData?.data;
433
622
  const selectedGroupBy = query?.groupBy || "contentType";
434
623
  const {
@@ -535,7 +724,7 @@ const ReleaseDetailsBody = () => {
535
724
  designSystem.SingleSelect,
536
725
  {
537
726
  "aria-label": formatMessage({
538
- id: "content-releases.pages.ReleaseDetails.groupBy.label",
727
+ id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
539
728
  defaultMessage: "Group by"
540
729
  }),
541
730
  customizeContent: (value) => formatMessage(
@@ -553,7 +742,7 @@ const ReleaseDetailsBody = () => {
553
742
  }
554
743
  ) }),
555
744
  Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
556
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: key }) }),
745
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { role: "separator", "aria-label": key, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: key }) }),
557
746
  /* @__PURE__ */ jsxRuntime.jsx(
558
747
  helperPlugin.Table.Root,
559
748
  {
@@ -642,7 +831,8 @@ const ReleaseDetailsBody = () => {
642
831
  {
643
832
  selected: type,
644
833
  handleChange: (e) => handleChangeType(e, id, [key, actionIndex]),
645
- name: `release-action-${id}-type`
834
+ name: `release-action-${id}-type`,
835
+ disabled: !canUpdate
646
836
  }
647
837
  ) }),
648
838
  !release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -721,11 +911,18 @@ const ReleaseDetailsPage = () => {
721
911
  }
722
912
  );
723
913
  }
724
- const title = isSuccessDetails && data?.data?.name || "";
914
+ const releaseData = isSuccessDetails && data?.data || null;
915
+ const title = releaseData?.name || "";
916
+ const timezone = releaseData?.timezone ?? null;
917
+ const scheduledAt = releaseData?.scheduledAt && timezone ? dateFnsTz.utcToZonedTime(releaseData.scheduledAt, timezone) : null;
918
+ const date = scheduledAt ? new Date(format__default.default(scheduledAt, "yyyy-MM-dd")) : null;
919
+ const time = scheduledAt ? format__default.default(scheduledAt, "HH:mm") : "";
725
920
  const handleEditRelease = async (values) => {
726
921
  const response = await updateRelease({
727
922
  id: releaseId,
728
- name: values.name
923
+ name: values.name,
924
+ scheduledAt: values.scheduledAt,
925
+ timezone: values.timezone
729
926
  });
730
927
  if ("data" in response) {
731
928
  toggleNotification({
@@ -779,7 +976,14 @@ const ReleaseDetailsPage = () => {
779
976
  handleClose: toggleEditReleaseModal,
780
977
  handleSubmit: handleEditRelease,
781
978
  isLoading: isLoadingDetails || isSubmittingForm,
782
- initialValues: { name: title || "" }
979
+ initialValues: {
980
+ name: title || "",
981
+ scheduledAt,
982
+ date,
983
+ time,
984
+ isScheduled: Boolean(scheduledAt),
985
+ timezone
986
+ }
783
987
  }
784
988
  ),
785
989
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -859,7 +1063,13 @@ const StyledAlert = styled__default.default(designSystem.Alert)`
859
1063
  }
860
1064
  `;
861
1065
  const INITIAL_FORM_VALUES = {
862
- name: ""
1066
+ name: "",
1067
+ date: null,
1068
+ time: "",
1069
+ // Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
1070
+ isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
1071
+ scheduledAt: null,
1072
+ timezone: null
863
1073
  };
864
1074
  const ReleasesPage = () => {
865
1075
  const tabRef = React__namespace.useRef(null);
@@ -919,9 +1129,11 @@ const ReleasesPage = () => {
919
1129
  }
920
1130
  });
921
1131
  };
922
- const handleAddRelease = async (values) => {
1132
+ const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
923
1133
  const response2 = await createRelease({
924
- name: values.name
1134
+ name,
1135
+ scheduledAt,
1136
+ timezone
925
1137
  });
926
1138
  if ("data" in response2) {
927
1139
  toggleNotification({
@@ -1081,4 +1293,4 @@ const App = () => {
1081
1293
  ] }) });
1082
1294
  };
1083
1295
  exports.App = App;
1084
- //# sourceMappingURL=App-5PsAyVt2.js.map
1296
+ //# sourceMappingURL=App-w2Zq-wj5.js.map