@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.
- package/dist/_chunks/{App-3ycH2d3s.mjs → App-ise7GunC.mjs} +365 -154
- package/dist/_chunks/App-ise7GunC.mjs.map +1 -0
- package/dist/_chunks/{App-5PsAyVt2.js → App-w2Zq-wj5.js} +363 -151
- package/dist/_chunks/App-w2Zq-wj5.js.map +1 -0
- package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs +51 -0
- package/dist/_chunks/PurchaseContentReleases-Clm0iACO.mjs.map +1 -0
- package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js +51 -0
- package/dist/_chunks/PurchaseContentReleases-YhAPgpG9.js.map +1 -0
- package/dist/_chunks/{en-2DuPv5k0.js → en-7P4i1cWH.js} +11 -3
- package/dist/_chunks/en-7P4i1cWH.js.map +1 -0
- package/dist/_chunks/{en-SOqjCdyh.mjs → en-pb1wUzhy.mjs} +11 -3
- package/dist/_chunks/en-pb1wUzhy.mjs.map +1 -0
- package/dist/_chunks/{index-4gUWuCQV.mjs → index-D-Yjf60c.mjs} +57 -16
- package/dist/_chunks/index-D-Yjf60c.mjs.map +1 -0
- package/dist/_chunks/{index-D57Rztnc.js → index-Q8Pv7enO.js} +57 -16
- package/dist/_chunks/index-Q8Pv7enO.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +573 -403
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +573 -403
- package/dist/server/index.mjs.map +1 -1
- package/package.json +12 -9
- package/dist/_chunks/App-3ycH2d3s.mjs.map +0 -1
- package/dist/_chunks/App-5PsAyVt2.js.map +0 -1
- package/dist/_chunks/en-2DuPv5k0.js.map +0 -1
- package/dist/_chunks/en-SOqjCdyh.mjs.map +0 -1
- package/dist/_chunks/index-4gUWuCQV.mjs.map +0 -1
- package/dist/_chunks/index-D57Rztnc.js.map +0 -1
|
@@ -1,22 +1,42 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useNotification, useAPIErrorHandler, LoadingIndicatorPage, ConfirmDialog, useRBAC, useTracking, RelativeTime, CheckPermissions, useQueryParams, AnErrorOccurred, NoContent, Table, PageSizeURLQuery, PaginationURLQuery, CheckPagePermissions } from "@strapi/helper-plugin";
|
|
3
3
|
import { useLocation, useParams, useHistory, Redirect, Link as Link$1, Switch, Route } from "react-router-dom";
|
|
4
|
-
import { p as pluginId, u as useGetReleaseQuery, a as useUpdateReleaseMutation, b as useDeleteReleaseMutation, c as usePublishReleaseMutation, P as PERMISSIONS, d as useTypedDispatch, e as useGetReleaseActionsQuery, f as useUpdateReleaseActionMutation, R as ReleaseActionOptions, g as ReleaseActionMenu, i as isAxiosError, r as releaseApi, h as useGetReleasesQuery, j as useCreateReleaseMutation } from "./index-
|
|
4
|
+
import { p as pluginId, u as useGetReleaseQuery, a as useUpdateReleaseMutation, b as useDeleteReleaseMutation, c as usePublishReleaseMutation, P as PERMISSIONS, d as useTypedDispatch, e as useGetReleaseActionsQuery, f as useUpdateReleaseActionMutation, R as ReleaseActionOptions, g as ReleaseActionMenu, i as isAxiosError, r as releaseApi, h as useGetReleasesQuery, j as useCreateReleaseMutation } from "./index-D-Yjf60c.mjs";
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
import { unstable_useDocument, useLicenseLimits } from "@strapi/admin/strapi-admin";
|
|
7
|
-
import { ModalLayout, ModalHeader, Typography, ModalBody, TextInput, ModalFooter, Button,
|
|
8
|
-
import { LinkButton, Link as Link$2 } from "@strapi/design-system/v2";
|
|
7
|
+
import { ModalLayout, ModalHeader, Typography, ModalBody, Flex, TextInput, Checkbox, Box, DatePicker, TimePicker, ModalFooter, Button, Combobox, ComboboxOption, ContentLayout, Main, HeaderLayout, Link, IconButton, SingleSelect, SingleSelectOption, Badge, Tr, Td, Icon, Tooltip, Alert, TabGroup, Tabs, Tab, Divider, TabPanels, TabPanel, EmptyStateLayout, Grid, GridItem } from "@strapi/design-system";
|
|
8
|
+
import { Menu, LinkButton, Link as Link$2 } from "@strapi/design-system/v2";
|
|
9
9
|
import { Pencil, Trash, ArrowLeft, More, CrossCircle, CheckCircle, Plus, EmptyDocuments } from "@strapi/icons";
|
|
10
|
+
import format from "date-fns/format";
|
|
11
|
+
import { zonedTimeToUtc, utcToZonedTime } from "date-fns-tz";
|
|
10
12
|
import { useIntl } from "react-intl";
|
|
11
13
|
import styled from "styled-components";
|
|
12
|
-
import {
|
|
14
|
+
import { formatISO, parse } from "date-fns";
|
|
15
|
+
import { Formik, Form, useFormikContext } from "formik";
|
|
13
16
|
import * as yup from "yup";
|
|
14
17
|
import "@reduxjs/toolkit/query";
|
|
15
18
|
import "axios";
|
|
16
19
|
import "@reduxjs/toolkit/query/react";
|
|
17
20
|
import "react-redux";
|
|
18
21
|
const RELEASE_SCHEMA = yup.object().shape({
|
|
19
|
-
name: yup.string().trim().required()
|
|
22
|
+
name: yup.string().trim().required(),
|
|
23
|
+
scheduledAt: yup.string().nullable(),
|
|
24
|
+
isScheduled: yup.boolean().optional(),
|
|
25
|
+
time: yup.string().when("isScheduled", {
|
|
26
|
+
is: true,
|
|
27
|
+
then: yup.string().trim().required(),
|
|
28
|
+
otherwise: yup.string().nullable()
|
|
29
|
+
}),
|
|
30
|
+
timezone: yup.string().when("isScheduled", {
|
|
31
|
+
is: true,
|
|
32
|
+
then: yup.string().required().nullable(),
|
|
33
|
+
otherwise: yup.string().nullable()
|
|
34
|
+
}),
|
|
35
|
+
date: yup.string().when("isScheduled", {
|
|
36
|
+
is: true,
|
|
37
|
+
then: yup.string().required().nullable(),
|
|
38
|
+
otherwise: yup.string().nullable()
|
|
39
|
+
})
|
|
20
40
|
}).required().noUnknown();
|
|
21
41
|
const ReleaseModal = ({
|
|
22
42
|
handleClose,
|
|
@@ -27,6 +47,24 @@ const ReleaseModal = ({
|
|
|
27
47
|
const { formatMessage } = useIntl();
|
|
28
48
|
const { pathname } = useLocation();
|
|
29
49
|
const isCreatingRelease = pathname === `/plugins/${pluginId}`;
|
|
50
|
+
const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
|
|
51
|
+
const { timezoneList, systemTimezone = { value: "UTC+00:00-Africa/Abidjan " } } = getTimezones(
|
|
52
|
+
initialValues.scheduledAt ? new Date(initialValues.scheduledAt) : /* @__PURE__ */ new Date()
|
|
53
|
+
);
|
|
54
|
+
const getScheduledTimestamp = (values) => {
|
|
55
|
+
const { date, time, timezone } = values;
|
|
56
|
+
if (!date || !time || !timezone)
|
|
57
|
+
return null;
|
|
58
|
+
const formattedDate = parse(time, "HH:mm", new Date(date));
|
|
59
|
+
const timezoneWithoutOffset = timezone.split("-")[1];
|
|
60
|
+
return zonedTimeToUtc(formattedDate, timezoneWithoutOffset);
|
|
61
|
+
};
|
|
62
|
+
const getTimezoneWithOffset = () => {
|
|
63
|
+
const currentTimezone = timezoneList.find(
|
|
64
|
+
(timezone) => timezone.value.split("-")[1] === initialValues.timezone
|
|
65
|
+
);
|
|
66
|
+
return currentTimezone?.value || systemTimezone.value;
|
|
67
|
+
};
|
|
30
68
|
return /* @__PURE__ */ jsxs(ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
|
|
31
69
|
/* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage(
|
|
32
70
|
{
|
|
@@ -38,45 +76,134 @@ const ReleaseModal = ({
|
|
|
38
76
|
/* @__PURE__ */ jsx(
|
|
39
77
|
Formik,
|
|
40
78
|
{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
79
|
+
onSubmit: (values) => {
|
|
80
|
+
handleSubmit({
|
|
81
|
+
...values,
|
|
82
|
+
timezone: values.timezone ? values.timezone.split("-")[1] : null,
|
|
83
|
+
scheduledAt: values.isScheduled ? getScheduledTimestamp(values) : null
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
initialValues: {
|
|
87
|
+
...initialValues,
|
|
88
|
+
timezone: initialValues.timezone ? getTimezoneWithOffset() : systemTimezone.value
|
|
89
|
+
},
|
|
44
90
|
validationSchema: RELEASE_SCHEMA,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
91
|
+
validateOnChange: false,
|
|
92
|
+
children: ({ values, errors, handleChange, setFieldValue }) => /* @__PURE__ */ jsxs(Form, { children: [
|
|
93
|
+
/* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
|
|
94
|
+
/* @__PURE__ */ jsx(
|
|
95
|
+
TextInput,
|
|
96
|
+
{
|
|
97
|
+
label: formatMessage({
|
|
98
|
+
id: "content-releases.modal.form.input.label.release-name",
|
|
99
|
+
defaultMessage: "Name"
|
|
100
|
+
}),
|
|
101
|
+
name: "name",
|
|
102
|
+
value: values.name,
|
|
103
|
+
error: errors.name,
|
|
104
|
+
onChange: handleChange,
|
|
105
|
+
required: true
|
|
106
|
+
}
|
|
107
|
+
),
|
|
108
|
+
IsSchedulingEnabled && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
109
|
+
/* @__PURE__ */ jsx(
|
|
110
|
+
Checkbox,
|
|
111
|
+
{
|
|
112
|
+
name: "isScheduled",
|
|
113
|
+
value: values.isScheduled,
|
|
114
|
+
onChange: (event) => {
|
|
115
|
+
setFieldValue("isScheduled", event.target.checked);
|
|
116
|
+
if (!event.target.checked) {
|
|
117
|
+
setFieldValue("date", null);
|
|
118
|
+
setFieldValue("time", "");
|
|
119
|
+
setFieldValue("timezone", null);
|
|
120
|
+
} else {
|
|
121
|
+
setFieldValue("date", initialValues.date);
|
|
122
|
+
setFieldValue("time", initialValues.time);
|
|
123
|
+
setFieldValue(
|
|
124
|
+
"timezone",
|
|
125
|
+
initialValues.timezone ?? systemTimezone?.value
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
children: /* @__PURE__ */ jsx(
|
|
130
|
+
Typography,
|
|
131
|
+
{
|
|
132
|
+
textColor: values.isScheduled ? "primary600" : "neutral800",
|
|
133
|
+
fontWeight: values.isScheduled ? "semiBold" : "regular",
|
|
134
|
+
children: formatMessage({
|
|
135
|
+
id: "modal.form.input.label.schedule-release",
|
|
136
|
+
defaultMessage: "Schedule release"
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
),
|
|
142
|
+
values.isScheduled && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
143
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 4, alignItems: "start", children: [
|
|
144
|
+
/* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
|
|
145
|
+
DatePicker,
|
|
146
|
+
{
|
|
147
|
+
label: formatMessage({
|
|
148
|
+
id: "content-releases.modal.form.input.label.date",
|
|
149
|
+
defaultMessage: "Date"
|
|
150
|
+
}),
|
|
151
|
+
name: "date",
|
|
152
|
+
error: errors.date,
|
|
153
|
+
onChange: (date) => {
|
|
154
|
+
const isoFormatDate = date ? formatISO(date, { representation: "date" }) : null;
|
|
155
|
+
setFieldValue("date", isoFormatDate);
|
|
156
|
+
},
|
|
157
|
+
clearLabel: formatMessage({
|
|
158
|
+
id: "content-releases.modal.form.input.clearLabel",
|
|
159
|
+
defaultMessage: "Clear"
|
|
160
|
+
}),
|
|
161
|
+
onClear: () => {
|
|
162
|
+
setFieldValue("date", null);
|
|
163
|
+
},
|
|
164
|
+
selectedDate: values.date || void 0,
|
|
165
|
+
required: true
|
|
166
|
+
}
|
|
167
|
+
) }),
|
|
168
|
+
/* @__PURE__ */ jsx(Box, { width: "100%", children: /* @__PURE__ */ jsx(
|
|
169
|
+
TimePicker,
|
|
170
|
+
{
|
|
171
|
+
label: formatMessage({
|
|
172
|
+
id: "content-releases.modal.form.input.label.time",
|
|
173
|
+
defaultMessage: "Time"
|
|
174
|
+
}),
|
|
175
|
+
name: "time",
|
|
176
|
+
error: errors.time,
|
|
177
|
+
onChange: (time) => {
|
|
178
|
+
setFieldValue("time", time);
|
|
179
|
+
},
|
|
180
|
+
clearLabel: formatMessage({
|
|
181
|
+
id: "content-releases.modal.form.input.clearLabel",
|
|
182
|
+
defaultMessage: "Clear"
|
|
183
|
+
}),
|
|
184
|
+
onClear: () => {
|
|
185
|
+
setFieldValue("time", "");
|
|
186
|
+
},
|
|
187
|
+
value: values.time || void 0,
|
|
188
|
+
required: true
|
|
189
|
+
}
|
|
190
|
+
) })
|
|
191
|
+
] }),
|
|
192
|
+
/* @__PURE__ */ jsx(TimezoneComponent, { timezoneOptions: timezoneList })
|
|
193
|
+
] })
|
|
194
|
+
] })
|
|
195
|
+
] }) }),
|
|
60
196
|
/* @__PURE__ */ jsx(
|
|
61
197
|
ModalFooter,
|
|
62
198
|
{
|
|
63
199
|
startActions: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }),
|
|
64
|
-
endActions: /* @__PURE__ */ jsx(
|
|
65
|
-
Button,
|
|
200
|
+
endActions: /* @__PURE__ */ jsx(Button, { name: "submit", loading: isLoading, type: "submit", children: formatMessage(
|
|
66
201
|
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
{
|
|
73
|
-
id: "content-releases.modal.form.button.submit",
|
|
74
|
-
defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
|
|
75
|
-
},
|
|
76
|
-
{ isCreatingRelease }
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
)
|
|
202
|
+
id: "content-releases.modal.form.button.submit",
|
|
203
|
+
defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
|
|
204
|
+
},
|
|
205
|
+
{ isCreatingRelease }
|
|
206
|
+
) })
|
|
80
207
|
}
|
|
81
208
|
)
|
|
82
209
|
] })
|
|
@@ -84,16 +211,67 @@ const ReleaseModal = ({
|
|
|
84
211
|
)
|
|
85
212
|
] });
|
|
86
213
|
};
|
|
214
|
+
const getTimezones = (selectedDate) => {
|
|
215
|
+
const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
|
|
216
|
+
const offsetPart = new Intl.DateTimeFormat("en", {
|
|
217
|
+
timeZone: timezone,
|
|
218
|
+
timeZoneName: "longOffset"
|
|
219
|
+
}).formatToParts(selectedDate).find((part) => part.type === "timeZoneName");
|
|
220
|
+
const offset = offsetPart ? offsetPart.value : "";
|
|
221
|
+
let utcOffset = offset.replace("GMT", "UTC");
|
|
222
|
+
if (!utcOffset.includes("+") && !utcOffset.includes("-")) {
|
|
223
|
+
utcOffset = `${utcOffset}+00:00`;
|
|
224
|
+
}
|
|
225
|
+
return { offset: utcOffset, value: `${utcOffset}-${timezone}` };
|
|
226
|
+
});
|
|
227
|
+
const systemTimezone = timezoneList.find(
|
|
228
|
+
(timezone) => timezone.value.split("-")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
229
|
+
);
|
|
230
|
+
return { timezoneList, systemTimezone };
|
|
231
|
+
};
|
|
232
|
+
const TimezoneComponent = ({ timezoneOptions }) => {
|
|
233
|
+
const { values, errors, setFieldValue } = useFormikContext();
|
|
234
|
+
const { formatMessage } = useIntl();
|
|
235
|
+
const [timezoneList, setTimezoneList] = React.useState(timezoneOptions);
|
|
236
|
+
React.useEffect(() => {
|
|
237
|
+
if (values.date) {
|
|
238
|
+
const { timezoneList: timezoneList2 } = getTimezones(new Date(values.date));
|
|
239
|
+
setTimezoneList(timezoneList2);
|
|
240
|
+
const updatedTimezone = values.timezone && timezoneList2.find((tz) => tz.value.split("-")[1] === values.timezone.split("-")[1]);
|
|
241
|
+
if (updatedTimezone) {
|
|
242
|
+
setFieldValue("timezone", updatedTimezone.value);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}, [setFieldValue, values.date, values.timezone]);
|
|
246
|
+
return /* @__PURE__ */ jsx(
|
|
247
|
+
Combobox,
|
|
248
|
+
{
|
|
249
|
+
label: formatMessage({
|
|
250
|
+
id: "content-releases.modal.form.input.label.timezone",
|
|
251
|
+
defaultMessage: "Timezone"
|
|
252
|
+
}),
|
|
253
|
+
name: "timezone",
|
|
254
|
+
value: values.timezone || void 0,
|
|
255
|
+
textValue: values.timezone ? values.timezone.replace("-", " ") : void 0,
|
|
256
|
+
onChange: (timezone) => {
|
|
257
|
+
setFieldValue("timezone", timezone);
|
|
258
|
+
},
|
|
259
|
+
onClear: () => {
|
|
260
|
+
setFieldValue("timezone", "");
|
|
261
|
+
},
|
|
262
|
+
error: errors.timezone,
|
|
263
|
+
required: true,
|
|
264
|
+
children: timezoneList.map((timezone) => /* @__PURE__ */ jsx(ComboboxOption, { value: timezone.value, children: timezone.value.replace("-", " ") }, timezone.value))
|
|
265
|
+
}
|
|
266
|
+
);
|
|
267
|
+
};
|
|
87
268
|
const ReleaseInfoWrapper = styled(Flex)`
|
|
88
269
|
align-self: stretch;
|
|
89
270
|
border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
|
|
90
271
|
border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
|
|
91
272
|
border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
|
|
92
273
|
`;
|
|
93
|
-
const
|
|
94
|
-
align-self: stretch;
|
|
95
|
-
cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
|
|
96
|
-
|
|
274
|
+
const StyledMenuItem = styled(Menu.Item)`
|
|
97
275
|
svg path {
|
|
98
276
|
fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
|
|
99
277
|
}
|
|
@@ -102,15 +280,15 @@ const StyledFlex = styled(Flex)`
|
|
|
102
280
|
}
|
|
103
281
|
`;
|
|
104
282
|
const PencilIcon = styled(Pencil)`
|
|
105
|
-
width: ${({ theme }) => theme.spaces[
|
|
106
|
-
height: ${({ theme }) => theme.spaces[
|
|
283
|
+
width: ${({ theme }) => theme.spaces[3]};
|
|
284
|
+
height: ${({ theme }) => theme.spaces[3]};
|
|
107
285
|
path {
|
|
108
286
|
fill: ${({ theme }) => theme.colors.neutral600};
|
|
109
287
|
}
|
|
110
288
|
`;
|
|
111
289
|
const TrashIcon = styled(Trash)`
|
|
112
|
-
width: ${({ theme }) => theme.spaces[
|
|
113
|
-
height: ${({ theme }) => theme.spaces[
|
|
290
|
+
width: ${({ theme }) => theme.spaces[3]};
|
|
291
|
+
height: ${({ theme }) => theme.spaces[3]};
|
|
114
292
|
path {
|
|
115
293
|
fill: ${({ theme }) => theme.colors.danger600};
|
|
116
294
|
}
|
|
@@ -118,24 +296,6 @@ const TrashIcon = styled(Trash)`
|
|
|
118
296
|
const TypographyMaxWidth = styled(Typography)`
|
|
119
297
|
max-width: 300px;
|
|
120
298
|
`;
|
|
121
|
-
const PopoverButton = ({ onClick, disabled, children }) => {
|
|
122
|
-
return /* @__PURE__ */ jsx(
|
|
123
|
-
StyledFlex,
|
|
124
|
-
{
|
|
125
|
-
paddingTop: 2,
|
|
126
|
-
paddingBottom: 2,
|
|
127
|
-
paddingLeft: 4,
|
|
128
|
-
paddingRight: 4,
|
|
129
|
-
alignItems: "center",
|
|
130
|
-
gap: 2,
|
|
131
|
-
as: "button",
|
|
132
|
-
hasRadius: true,
|
|
133
|
-
onClick,
|
|
134
|
-
disabled,
|
|
135
|
-
children
|
|
136
|
-
}
|
|
137
|
-
);
|
|
138
|
-
};
|
|
139
299
|
const EntryValidationText = ({ action, schema, components, entry }) => {
|
|
140
300
|
const { formatMessage } = useIntl();
|
|
141
301
|
const { validate } = unstable_useDocument();
|
|
@@ -186,8 +346,6 @@ const ReleaseDetailsLayout = ({
|
|
|
186
346
|
}) => {
|
|
187
347
|
const { formatMessage } = useIntl();
|
|
188
348
|
const { releaseId } = useParams();
|
|
189
|
-
const [isPopoverVisible, setIsPopoverVisible] = React.useState(false);
|
|
190
|
-
const moreButtonRef = React.useRef(null);
|
|
191
349
|
const {
|
|
192
350
|
data,
|
|
193
351
|
isLoading: isLoadingDetails,
|
|
@@ -203,13 +361,6 @@ const ReleaseDetailsLayout = ({
|
|
|
203
361
|
const dispatch = useTypedDispatch();
|
|
204
362
|
const { trackUsage } = useTracking();
|
|
205
363
|
const release = data?.data;
|
|
206
|
-
const handleTogglePopover = () => {
|
|
207
|
-
setIsPopoverVisible((prev) => !prev);
|
|
208
|
-
};
|
|
209
|
-
const openReleaseModal = () => {
|
|
210
|
-
toggleEditReleaseModal();
|
|
211
|
-
handleTogglePopover();
|
|
212
|
-
};
|
|
213
364
|
const handlePublishRelease = async () => {
|
|
214
365
|
const response = await publishRelease({ id: releaseId });
|
|
215
366
|
if ("data" in response) {
|
|
@@ -238,13 +389,21 @@ const ReleaseDetailsLayout = ({
|
|
|
238
389
|
});
|
|
239
390
|
}
|
|
240
391
|
};
|
|
241
|
-
const openWarningConfirmDialog = () => {
|
|
242
|
-
toggleWarningSubmit();
|
|
243
|
-
handleTogglePopover();
|
|
244
|
-
};
|
|
245
392
|
const handleRefresh = () => {
|
|
246
393
|
dispatch(releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
|
|
247
394
|
};
|
|
395
|
+
const getCreatedByUser = () => {
|
|
396
|
+
if (!release?.createdBy) {
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
if (release.createdBy.username) {
|
|
400
|
+
return release.createdBy.username;
|
|
401
|
+
}
|
|
402
|
+
if (release.createdBy.firstname) {
|
|
403
|
+
return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
|
|
404
|
+
}
|
|
405
|
+
return release.createdBy.email;
|
|
406
|
+
};
|
|
248
407
|
if (isLoadingDetails) {
|
|
249
408
|
return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
|
|
250
409
|
}
|
|
@@ -266,7 +425,7 @@ const ReleaseDetailsLayout = ({
|
|
|
266
425
|
);
|
|
267
426
|
}
|
|
268
427
|
const totalEntries = release.actions.meta.count || 0;
|
|
269
|
-
const
|
|
428
|
+
const hasCreatedByUser = Boolean(getCreatedByUser());
|
|
270
429
|
return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
|
|
271
430
|
/* @__PURE__ */ jsx(
|
|
272
431
|
HeaderLayout,
|
|
@@ -284,72 +443,98 @@ const ReleaseDetailsLayout = ({
|
|
|
284
443
|
defaultMessage: "Back"
|
|
285
444
|
}) }),
|
|
286
445
|
primaryAction: !release.releasedAt && /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
287
|
-
/* @__PURE__ */
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
{
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
446
|
+
/* @__PURE__ */ jsxs(Menu.Root, { children: [
|
|
447
|
+
/* @__PURE__ */ jsx(
|
|
448
|
+
Menu.Trigger,
|
|
449
|
+
{
|
|
450
|
+
as: IconButton,
|
|
451
|
+
paddingLeft: 2,
|
|
452
|
+
paddingRight: 2,
|
|
453
|
+
"aria-label": formatMessage({
|
|
454
|
+
id: "content-releases.header.actions.open-release-actions",
|
|
455
|
+
defaultMessage: "Release edit and delete menu"
|
|
456
|
+
}),
|
|
457
|
+
icon: /* @__PURE__ */ jsx(More, {}),
|
|
458
|
+
variant: "tertiary"
|
|
459
|
+
}
|
|
460
|
+
),
|
|
461
|
+
/* @__PURE__ */ jsxs(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: [
|
|
462
|
+
/* @__PURE__ */ jsxs(
|
|
463
|
+
Flex,
|
|
464
|
+
{
|
|
465
|
+
alignItems: "center",
|
|
466
|
+
justifyContent: "center",
|
|
467
|
+
direction: "column",
|
|
468
|
+
padding: 1,
|
|
469
|
+
width: "100%",
|
|
470
|
+
children: [
|
|
471
|
+
/* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxs(
|
|
472
|
+
Flex,
|
|
473
|
+
{
|
|
474
|
+
paddingTop: 2,
|
|
475
|
+
paddingBottom: 2,
|
|
476
|
+
alignItems: "center",
|
|
477
|
+
gap: 2,
|
|
478
|
+
hasRadius: true,
|
|
479
|
+
width: "100%",
|
|
480
|
+
children: [
|
|
481
|
+
/* @__PURE__ */ jsx(PencilIcon, {}),
|
|
482
|
+
/* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
|
|
483
|
+
id: "content-releases.header.actions.edit",
|
|
484
|
+
defaultMessage: "Edit"
|
|
485
|
+
}) })
|
|
486
|
+
]
|
|
487
|
+
}
|
|
488
|
+
) }),
|
|
489
|
+
/* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canDelete, onSelect: toggleWarningSubmit, children: /* @__PURE__ */ jsxs(
|
|
490
|
+
Flex,
|
|
491
|
+
{
|
|
492
|
+
paddingTop: 2,
|
|
493
|
+
paddingBottom: 2,
|
|
494
|
+
alignItems: "center",
|
|
495
|
+
gap: 2,
|
|
496
|
+
hasRadius: true,
|
|
497
|
+
width: "100%",
|
|
498
|
+
children: [
|
|
499
|
+
/* @__PURE__ */ jsx(TrashIcon, {}),
|
|
500
|
+
/* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
|
|
501
|
+
id: "content-releases.header.actions.delete",
|
|
502
|
+
defaultMessage: "Delete"
|
|
503
|
+
}) })
|
|
504
|
+
]
|
|
505
|
+
}
|
|
506
|
+
) })
|
|
507
|
+
]
|
|
508
|
+
}
|
|
509
|
+
),
|
|
510
|
+
/* @__PURE__ */ jsxs(
|
|
511
|
+
ReleaseInfoWrapper,
|
|
512
|
+
{
|
|
513
|
+
direction: "column",
|
|
514
|
+
justifyContent: "center",
|
|
515
|
+
alignItems: "flex-start",
|
|
516
|
+
gap: 1,
|
|
517
|
+
padding: 5,
|
|
518
|
+
children: [
|
|
519
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
|
|
520
|
+
id: "content-releases.header.actions.created",
|
|
521
|
+
defaultMessage: "Created"
|
|
522
|
+
}) }),
|
|
523
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "pi", color: "neutral300", children: [
|
|
524
|
+
/* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(release.createdAt) }),
|
|
525
|
+
formatMessage(
|
|
526
|
+
{
|
|
527
|
+
id: "content-releases.header.actions.created.description",
|
|
528
|
+
defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
|
|
529
|
+
},
|
|
530
|
+
{ createdBy: getCreatedByUser(), hasCreatedByUser }
|
|
531
|
+
)
|
|
532
|
+
] })
|
|
533
|
+
]
|
|
534
|
+
}
|
|
535
|
+
)
|
|
536
|
+
] })
|
|
537
|
+
] }),
|
|
353
538
|
/* @__PURE__ */ jsx(Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
|
|
354
539
|
id: "content-releases.header.actions.refresh",
|
|
355
540
|
defaultMessage: "Refresh"
|
|
@@ -405,6 +590,9 @@ const ReleaseDetailsBody = () => {
|
|
|
405
590
|
isError: isReleaseError,
|
|
406
591
|
error: releaseError
|
|
407
592
|
} = useGetReleaseQuery({ id: releaseId });
|
|
593
|
+
const {
|
|
594
|
+
allowedActions: { canUpdate }
|
|
595
|
+
} = useRBAC(PERMISSIONS);
|
|
408
596
|
const release = releaseData?.data;
|
|
409
597
|
const selectedGroupBy = query?.groupBy || "contentType";
|
|
410
598
|
const {
|
|
@@ -511,7 +699,7 @@ const ReleaseDetailsBody = () => {
|
|
|
511
699
|
SingleSelect,
|
|
512
700
|
{
|
|
513
701
|
"aria-label": formatMessage({
|
|
514
|
-
id: "content-releases.pages.ReleaseDetails.groupBy.label",
|
|
702
|
+
id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
|
|
515
703
|
defaultMessage: "Group by"
|
|
516
704
|
}),
|
|
517
705
|
customizeContent: (value) => formatMessage(
|
|
@@ -529,7 +717,7 @@ const ReleaseDetailsBody = () => {
|
|
|
529
717
|
}
|
|
530
718
|
) }),
|
|
531
719
|
Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
|
|
532
|
-
/* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(Badge, { children: key }) }),
|
|
720
|
+
/* @__PURE__ */ jsx(Flex, { role: "separator", "aria-label": key, children: /* @__PURE__ */ jsx(Badge, { children: key }) }),
|
|
533
721
|
/* @__PURE__ */ jsx(
|
|
534
722
|
Table.Root,
|
|
535
723
|
{
|
|
@@ -618,7 +806,8 @@ const ReleaseDetailsBody = () => {
|
|
|
618
806
|
{
|
|
619
807
|
selected: type,
|
|
620
808
|
handleChange: (e) => handleChangeType(e, id, [key, actionIndex]),
|
|
621
|
-
name: `release-action-${id}-type
|
|
809
|
+
name: `release-action-${id}-type`,
|
|
810
|
+
disabled: !canUpdate
|
|
622
811
|
}
|
|
623
812
|
) }),
|
|
624
813
|
!release.releasedAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -697,11 +886,18 @@ const ReleaseDetailsPage = () => {
|
|
|
697
886
|
}
|
|
698
887
|
);
|
|
699
888
|
}
|
|
700
|
-
const
|
|
889
|
+
const releaseData = isSuccessDetails && data?.data || null;
|
|
890
|
+
const title = releaseData?.name || "";
|
|
891
|
+
const timezone = releaseData?.timezone ?? null;
|
|
892
|
+
const scheduledAt = releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;
|
|
893
|
+
const date = scheduledAt ? new Date(format(scheduledAt, "yyyy-MM-dd")) : null;
|
|
894
|
+
const time = scheduledAt ? format(scheduledAt, "HH:mm") : "";
|
|
701
895
|
const handleEditRelease = async (values) => {
|
|
702
896
|
const response = await updateRelease({
|
|
703
897
|
id: releaseId,
|
|
704
|
-
name: values.name
|
|
898
|
+
name: values.name,
|
|
899
|
+
scheduledAt: values.scheduledAt,
|
|
900
|
+
timezone: values.timezone
|
|
705
901
|
});
|
|
706
902
|
if ("data" in response) {
|
|
707
903
|
toggleNotification({
|
|
@@ -755,7 +951,14 @@ const ReleaseDetailsPage = () => {
|
|
|
755
951
|
handleClose: toggleEditReleaseModal,
|
|
756
952
|
handleSubmit: handleEditRelease,
|
|
757
953
|
isLoading: isLoadingDetails || isSubmittingForm,
|
|
758
|
-
initialValues: {
|
|
954
|
+
initialValues: {
|
|
955
|
+
name: title || "",
|
|
956
|
+
scheduledAt,
|
|
957
|
+
date,
|
|
958
|
+
time,
|
|
959
|
+
isScheduled: Boolean(scheduledAt),
|
|
960
|
+
timezone
|
|
961
|
+
}
|
|
759
962
|
}
|
|
760
963
|
),
|
|
761
964
|
/* @__PURE__ */ jsx(
|
|
@@ -835,7 +1038,13 @@ const StyledAlert = styled(Alert)`
|
|
|
835
1038
|
}
|
|
836
1039
|
`;
|
|
837
1040
|
const INITIAL_FORM_VALUES = {
|
|
838
|
-
name: ""
|
|
1041
|
+
name: "",
|
|
1042
|
+
date: null,
|
|
1043
|
+
time: "",
|
|
1044
|
+
// Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
|
|
1045
|
+
isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
|
|
1046
|
+
scheduledAt: null,
|
|
1047
|
+
timezone: null
|
|
839
1048
|
};
|
|
840
1049
|
const ReleasesPage = () => {
|
|
841
1050
|
const tabRef = React.useRef(null);
|
|
@@ -895,9 +1104,11 @@ const ReleasesPage = () => {
|
|
|
895
1104
|
}
|
|
896
1105
|
});
|
|
897
1106
|
};
|
|
898
|
-
const handleAddRelease = async (
|
|
1107
|
+
const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
|
|
899
1108
|
const response2 = await createRelease({
|
|
900
|
-
name
|
|
1109
|
+
name,
|
|
1110
|
+
scheduledAt,
|
|
1111
|
+
timezone
|
|
901
1112
|
});
|
|
902
1113
|
if ("data" in response2) {
|
|
903
1114
|
toggleNotification({
|
|
@@ -1059,4 +1270,4 @@ const App = () => {
|
|
|
1059
1270
|
export {
|
|
1060
1271
|
App
|
|
1061
1272
|
};
|
|
1062
|
-
//# sourceMappingURL=App-
|
|
1273
|
+
//# sourceMappingURL=App-ise7GunC.mjs.map
|