@strapi/content-releases 0.0.0-next.287aae0bb4a682fba312332372895dbf8e032bf1 → 0.0.0-next.2a816cdadd2ece37767550b2a249c03ef2b53aeb
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-M11U5GPh.mjs → App-eVYKuxUc.mjs} +377 -159
- package/dist/_chunks/App-eVYKuxUc.mjs.map +1 -0
- package/dist/_chunks/{App-x6I6piPB.js → App-oGnTffWo.js} +375 -156
- package/dist/_chunks/App-oGnTffWo.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--WvbU-_H.js → en-r0otWaln.js} +13 -2
- package/dist/_chunks/en-r0otWaln.js.map +1 -0
- package/dist/_chunks/{en-oREbrNEq.mjs → en-veqvqeEr.mjs} +13 -2
- package/dist/_chunks/en-veqvqeEr.mjs.map +1 -0
- package/dist/_chunks/{index-Ls9Qc5Tg.mjs → index-8XT9UxC5.mjs} +101 -20
- package/dist/_chunks/index-8XT9UxC5.mjs.map +1 -0
- package/dist/_chunks/{index-M4gICzzI.js → index-ABxBBqzg.js} +97 -16
- package/dist/_chunks/index-ABxBBqzg.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +2 -2
- package/dist/server/index.js +566 -395
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +566 -395
- package/dist/server/index.mjs.map +1 -1
- package/package.json +12 -9
- package/dist/_chunks/App-M11U5GPh.mjs.map +0 -1
- package/dist/_chunks/App-x6I6piPB.js.map +0 -1
- package/dist/_chunks/en--WvbU-_H.js.map +0 -1
- package/dist/_chunks/en-oREbrNEq.mjs.map +0 -1
- package/dist/_chunks/index-Ls9Qc5Tg.mjs.map +0 -1
- package/dist/_chunks/index-M4gICzzI.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,
|
|
4
|
+
import { g as getTimezoneOffset, 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, h as ReleaseActionMenu, i as isAxiosError, r as releaseApi, j as useGetReleasesQuery, k as useCreateReleaseMutation } from "./index-8XT9UxC5.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,59 @@ const ReleaseModal = ({
|
|
|
84
211
|
)
|
|
85
212
|
] });
|
|
86
213
|
};
|
|
214
|
+
const getTimezones = (selectedDate) => {
|
|
215
|
+
const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
|
|
216
|
+
const utcOffset = getTimezoneOffset(timezone, selectedDate);
|
|
217
|
+
return { offset: utcOffset, value: `${utcOffset}-${timezone}` };
|
|
218
|
+
});
|
|
219
|
+
const systemTimezone = timezoneList.find(
|
|
220
|
+
(timezone) => timezone.value.split("-")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
221
|
+
);
|
|
222
|
+
return { timezoneList, systemTimezone };
|
|
223
|
+
};
|
|
224
|
+
const TimezoneComponent = ({ timezoneOptions }) => {
|
|
225
|
+
const { values, errors, setFieldValue } = useFormikContext();
|
|
226
|
+
const { formatMessage } = useIntl();
|
|
227
|
+
const [timezoneList, setTimezoneList] = React.useState(timezoneOptions);
|
|
228
|
+
React.useEffect(() => {
|
|
229
|
+
if (values.date) {
|
|
230
|
+
const { timezoneList: timezoneList2 } = getTimezones(new Date(values.date));
|
|
231
|
+
setTimezoneList(timezoneList2);
|
|
232
|
+
const updatedTimezone = values.timezone && timezoneList2.find((tz) => tz.value.split("-")[1] === values.timezone.split("-")[1]);
|
|
233
|
+
if (updatedTimezone) {
|
|
234
|
+
setFieldValue("timezone", updatedTimezone.value);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}, [setFieldValue, values.date, values.timezone]);
|
|
238
|
+
return /* @__PURE__ */ jsx(
|
|
239
|
+
Combobox,
|
|
240
|
+
{
|
|
241
|
+
label: formatMessage({
|
|
242
|
+
id: "content-releases.modal.form.input.label.timezone",
|
|
243
|
+
defaultMessage: "Timezone"
|
|
244
|
+
}),
|
|
245
|
+
name: "timezone",
|
|
246
|
+
value: values.timezone || void 0,
|
|
247
|
+
textValue: values.timezone ? values.timezone.replace("-", " ") : void 0,
|
|
248
|
+
onChange: (timezone) => {
|
|
249
|
+
setFieldValue("timezone", timezone);
|
|
250
|
+
},
|
|
251
|
+
onClear: () => {
|
|
252
|
+
setFieldValue("timezone", "");
|
|
253
|
+
},
|
|
254
|
+
error: errors.timezone,
|
|
255
|
+
required: true,
|
|
256
|
+
children: timezoneList.map((timezone) => /* @__PURE__ */ jsx(ComboboxOption, { value: timezone.value, children: timezone.value.replace("-", " ") }, timezone.value))
|
|
257
|
+
}
|
|
258
|
+
);
|
|
259
|
+
};
|
|
87
260
|
const ReleaseInfoWrapper = styled(Flex)`
|
|
88
261
|
align-self: stretch;
|
|
89
262
|
border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
|
|
90
263
|
border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
|
|
91
264
|
border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
|
|
92
265
|
`;
|
|
93
|
-
const
|
|
94
|
-
align-self: stretch;
|
|
95
|
-
cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
|
|
96
|
-
|
|
266
|
+
const StyledMenuItem = styled(Menu.Item)`
|
|
97
267
|
svg path {
|
|
98
268
|
fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
|
|
99
269
|
}
|
|
@@ -118,24 +288,6 @@ const TrashIcon = styled(Trash)`
|
|
|
118
288
|
const TypographyMaxWidth = styled(Typography)`
|
|
119
289
|
max-width: 300px;
|
|
120
290
|
`;
|
|
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
291
|
const EntryValidationText = ({ action, schema, components, entry }) => {
|
|
140
292
|
const { formatMessage } = useIntl();
|
|
141
293
|
const { validate } = unstable_useDocument();
|
|
@@ -184,10 +336,8 @@ const ReleaseDetailsLayout = ({
|
|
|
184
336
|
toggleWarningSubmit,
|
|
185
337
|
children
|
|
186
338
|
}) => {
|
|
187
|
-
const { formatMessage } = useIntl();
|
|
339
|
+
const { formatMessage, formatDate, formatTime } = useIntl();
|
|
188
340
|
const { releaseId } = useParams();
|
|
189
|
-
const [isPopoverVisible, setIsPopoverVisible] = React.useState(false);
|
|
190
|
-
const moreButtonRef = React.useRef(null);
|
|
191
341
|
const {
|
|
192
342
|
data,
|
|
193
343
|
isLoading: isLoadingDetails,
|
|
@@ -203,13 +353,6 @@ const ReleaseDetailsLayout = ({
|
|
|
203
353
|
const dispatch = useTypedDispatch();
|
|
204
354
|
const { trackUsage } = useTracking();
|
|
205
355
|
const release = data?.data;
|
|
206
|
-
const handleTogglePopover = () => {
|
|
207
|
-
setIsPopoverVisible((prev) => !prev);
|
|
208
|
-
};
|
|
209
|
-
const openReleaseModal = () => {
|
|
210
|
-
toggleEditReleaseModal();
|
|
211
|
-
handleTogglePopover();
|
|
212
|
-
};
|
|
213
356
|
const handlePublishRelease = async () => {
|
|
214
357
|
const response = await publishRelease({ id: releaseId });
|
|
215
358
|
if ("data" in response) {
|
|
@@ -238,10 +381,6 @@ const ReleaseDetailsLayout = ({
|
|
|
238
381
|
});
|
|
239
382
|
}
|
|
240
383
|
};
|
|
241
|
-
const openWarningConfirmDialog = () => {
|
|
242
|
-
toggleWarningSubmit();
|
|
243
|
-
handleTogglePopover();
|
|
244
|
-
};
|
|
245
384
|
const handleRefresh = () => {
|
|
246
385
|
dispatch(releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
|
|
247
386
|
};
|
|
@@ -279,89 +418,138 @@ const ReleaseDetailsLayout = ({
|
|
|
279
418
|
}
|
|
280
419
|
const totalEntries = release.actions.meta.count || 0;
|
|
281
420
|
const hasCreatedByUser = Boolean(getCreatedByUser());
|
|
421
|
+
const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
|
|
422
|
+
const isScheduled = release.scheduledAt && release.timezone;
|
|
423
|
+
const numberOfEntriesText = formatMessage(
|
|
424
|
+
{
|
|
425
|
+
id: "content-releases.pages.Details.header-subtitle",
|
|
426
|
+
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
427
|
+
},
|
|
428
|
+
{ number: totalEntries }
|
|
429
|
+
);
|
|
430
|
+
const scheduledText = isScheduled ? formatMessage(
|
|
431
|
+
{
|
|
432
|
+
id: "content-releases.pages.ReleaseDetails.header-subtitle.scheduled",
|
|
433
|
+
defaultMessage: "Scheduled for {date} at {time} ({offset})"
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
date: formatDate(new Date(release.scheduledAt), {
|
|
437
|
+
weekday: "long",
|
|
438
|
+
day: "numeric",
|
|
439
|
+
month: "long",
|
|
440
|
+
year: "numeric",
|
|
441
|
+
timeZone: release.timezone
|
|
442
|
+
}),
|
|
443
|
+
time: formatTime(new Date(release.scheduledAt), {
|
|
444
|
+
hour12: false,
|
|
445
|
+
timeZone: release.timezone
|
|
446
|
+
}),
|
|
447
|
+
offset: getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
|
|
448
|
+
}
|
|
449
|
+
) : "";
|
|
282
450
|
return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
|
|
283
451
|
/* @__PURE__ */ jsx(
|
|
284
452
|
HeaderLayout,
|
|
285
453
|
{
|
|
286
454
|
title: release.name,
|
|
287
|
-
subtitle:
|
|
288
|
-
{
|
|
289
|
-
id: "content-releases.pages.Details.header-subtitle",
|
|
290
|
-
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
291
|
-
},
|
|
292
|
-
{ number: totalEntries }
|
|
293
|
-
),
|
|
455
|
+
subtitle: numberOfEntriesText + (IsSchedulingEnabled && isScheduled ? `- ${scheduledText}` : ""),
|
|
294
456
|
navigationAction: /* @__PURE__ */ jsx(Link, { startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
|
|
295
457
|
id: "global.back",
|
|
296
458
|
defaultMessage: "Back"
|
|
297
459
|
}) }),
|
|
298
460
|
primaryAction: !release.releasedAt && /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
299
|
-
/* @__PURE__ */
|
|
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
|
-
{
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
461
|
+
/* @__PURE__ */ jsxs(Menu.Root, { children: [
|
|
462
|
+
/* @__PURE__ */ jsx(
|
|
463
|
+
Menu.Trigger,
|
|
464
|
+
{
|
|
465
|
+
as: IconButton,
|
|
466
|
+
paddingLeft: 2,
|
|
467
|
+
paddingRight: 2,
|
|
468
|
+
"aria-label": formatMessage({
|
|
469
|
+
id: "content-releases.header.actions.open-release-actions",
|
|
470
|
+
defaultMessage: "Release edit and delete menu"
|
|
471
|
+
}),
|
|
472
|
+
icon: /* @__PURE__ */ jsx(More, {}),
|
|
473
|
+
variant: "tertiary"
|
|
474
|
+
}
|
|
475
|
+
),
|
|
476
|
+
/* @__PURE__ */ jsxs(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: [
|
|
477
|
+
/* @__PURE__ */ jsxs(
|
|
478
|
+
Flex,
|
|
479
|
+
{
|
|
480
|
+
alignItems: "center",
|
|
481
|
+
justifyContent: "center",
|
|
482
|
+
direction: "column",
|
|
483
|
+
padding: 1,
|
|
484
|
+
width: "100%",
|
|
485
|
+
children: [
|
|
486
|
+
/* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxs(
|
|
487
|
+
Flex,
|
|
488
|
+
{
|
|
489
|
+
paddingTop: 2,
|
|
490
|
+
paddingBottom: 2,
|
|
491
|
+
alignItems: "center",
|
|
492
|
+
gap: 2,
|
|
493
|
+
hasRadius: true,
|
|
494
|
+
width: "100%",
|
|
495
|
+
children: [
|
|
496
|
+
/* @__PURE__ */ jsx(PencilIcon, {}),
|
|
497
|
+
/* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
|
|
498
|
+
id: "content-releases.header.actions.edit",
|
|
499
|
+
defaultMessage: "Edit"
|
|
500
|
+
}) })
|
|
501
|
+
]
|
|
502
|
+
}
|
|
503
|
+
) }),
|
|
504
|
+
/* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canDelete, onSelect: toggleWarningSubmit, children: /* @__PURE__ */ jsxs(
|
|
505
|
+
Flex,
|
|
506
|
+
{
|
|
507
|
+
paddingTop: 2,
|
|
508
|
+
paddingBottom: 2,
|
|
509
|
+
alignItems: "center",
|
|
510
|
+
gap: 2,
|
|
511
|
+
hasRadius: true,
|
|
512
|
+
width: "100%",
|
|
513
|
+
children: [
|
|
514
|
+
/* @__PURE__ */ jsx(TrashIcon, {}),
|
|
515
|
+
/* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
|
|
516
|
+
id: "content-releases.header.actions.delete",
|
|
517
|
+
defaultMessage: "Delete"
|
|
518
|
+
}) })
|
|
519
|
+
]
|
|
520
|
+
}
|
|
521
|
+
) })
|
|
522
|
+
]
|
|
523
|
+
}
|
|
524
|
+
),
|
|
525
|
+
/* @__PURE__ */ jsxs(
|
|
526
|
+
ReleaseInfoWrapper,
|
|
527
|
+
{
|
|
528
|
+
direction: "column",
|
|
529
|
+
justifyContent: "center",
|
|
530
|
+
alignItems: "flex-start",
|
|
531
|
+
gap: 1,
|
|
532
|
+
padding: 5,
|
|
533
|
+
children: [
|
|
534
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
|
|
535
|
+
id: "content-releases.header.actions.created",
|
|
536
|
+
defaultMessage: "Created"
|
|
537
|
+
}) }),
|
|
538
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "pi", color: "neutral300", children: [
|
|
539
|
+
/* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(release.createdAt) }),
|
|
540
|
+
formatMessage(
|
|
541
|
+
{
|
|
542
|
+
id: "content-releases.header.actions.created.description",
|
|
543
|
+
defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
|
|
544
|
+
},
|
|
545
|
+
{ createdBy: getCreatedByUser(), hasCreatedByUser }
|
|
546
|
+
)
|
|
547
|
+
] })
|
|
548
|
+
]
|
|
549
|
+
}
|
|
550
|
+
)
|
|
551
|
+
] })
|
|
552
|
+
] }),
|
|
365
553
|
/* @__PURE__ */ jsx(Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
|
|
366
554
|
id: "content-releases.header.actions.refresh",
|
|
367
555
|
defaultMessage: "Refresh"
|
|
@@ -417,6 +605,9 @@ const ReleaseDetailsBody = () => {
|
|
|
417
605
|
isError: isReleaseError,
|
|
418
606
|
error: releaseError
|
|
419
607
|
} = useGetReleaseQuery({ id: releaseId });
|
|
608
|
+
const {
|
|
609
|
+
allowedActions: { canUpdate }
|
|
610
|
+
} = useRBAC(PERMISSIONS);
|
|
420
611
|
const release = releaseData?.data;
|
|
421
612
|
const selectedGroupBy = query?.groupBy || "contentType";
|
|
422
613
|
const {
|
|
@@ -523,7 +714,7 @@ const ReleaseDetailsBody = () => {
|
|
|
523
714
|
SingleSelect,
|
|
524
715
|
{
|
|
525
716
|
"aria-label": formatMessage({
|
|
526
|
-
id: "content-releases.pages.ReleaseDetails.groupBy.label",
|
|
717
|
+
id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
|
|
527
718
|
defaultMessage: "Group by"
|
|
528
719
|
}),
|
|
529
720
|
customizeContent: (value) => formatMessage(
|
|
@@ -541,7 +732,7 @@ const ReleaseDetailsBody = () => {
|
|
|
541
732
|
}
|
|
542
733
|
) }),
|
|
543
734
|
Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
|
|
544
|
-
/* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(Badge, { children: key }) }),
|
|
735
|
+
/* @__PURE__ */ jsx(Flex, { role: "separator", "aria-label": key, children: /* @__PURE__ */ jsx(Badge, { children: key }) }),
|
|
545
736
|
/* @__PURE__ */ jsx(
|
|
546
737
|
Table.Root,
|
|
547
738
|
{
|
|
@@ -630,7 +821,8 @@ const ReleaseDetailsBody = () => {
|
|
|
630
821
|
{
|
|
631
822
|
selected: type,
|
|
632
823
|
handleChange: (e) => handleChangeType(e, id, [key, actionIndex]),
|
|
633
|
-
name: `release-action-${id}-type
|
|
824
|
+
name: `release-action-${id}-type`,
|
|
825
|
+
disabled: !canUpdate
|
|
634
826
|
}
|
|
635
827
|
) }),
|
|
636
828
|
!release.releasedAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -709,11 +901,18 @@ const ReleaseDetailsPage = () => {
|
|
|
709
901
|
}
|
|
710
902
|
);
|
|
711
903
|
}
|
|
712
|
-
const
|
|
904
|
+
const releaseData = isSuccessDetails && data?.data || null;
|
|
905
|
+
const title = releaseData?.name || "";
|
|
906
|
+
const timezone = releaseData?.timezone ?? null;
|
|
907
|
+
const scheduledAt = releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;
|
|
908
|
+
const date = scheduledAt ? new Date(format(scheduledAt, "yyyy-MM-dd")) : null;
|
|
909
|
+
const time = scheduledAt ? format(scheduledAt, "HH:mm") : "";
|
|
713
910
|
const handleEditRelease = async (values) => {
|
|
714
911
|
const response = await updateRelease({
|
|
715
912
|
id: releaseId,
|
|
716
|
-
name: values.name
|
|
913
|
+
name: values.name,
|
|
914
|
+
scheduledAt: values.scheduledAt,
|
|
915
|
+
timezone: values.timezone
|
|
717
916
|
});
|
|
718
917
|
if ("data" in response) {
|
|
719
918
|
toggleNotification({
|
|
@@ -767,7 +966,14 @@ const ReleaseDetailsPage = () => {
|
|
|
767
966
|
handleClose: toggleEditReleaseModal,
|
|
768
967
|
handleSubmit: handleEditRelease,
|
|
769
968
|
isLoading: isLoadingDetails || isSubmittingForm,
|
|
770
|
-
initialValues: {
|
|
969
|
+
initialValues: {
|
|
970
|
+
name: title || "",
|
|
971
|
+
scheduledAt,
|
|
972
|
+
date,
|
|
973
|
+
time,
|
|
974
|
+
isScheduled: Boolean(scheduledAt),
|
|
975
|
+
timezone
|
|
976
|
+
}
|
|
771
977
|
}
|
|
772
978
|
),
|
|
773
979
|
/* @__PURE__ */ jsx(
|
|
@@ -792,6 +998,7 @@ const LinkCard = styled(Link$2)`
|
|
|
792
998
|
`;
|
|
793
999
|
const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
794
1000
|
const { formatMessage } = useIntl();
|
|
1001
|
+
const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
|
|
795
1002
|
if (isError) {
|
|
796
1003
|
return /* @__PURE__ */ jsx(AnErrorOccurred, {});
|
|
797
1004
|
}
|
|
@@ -812,7 +1019,7 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
812
1019
|
}
|
|
813
1020
|
);
|
|
814
1021
|
}
|
|
815
|
-
return /* @__PURE__ */ jsx(Grid, { gap: 4, children: releases.map(({ id, name, actions }) => /* @__PURE__ */ jsx(GridItem, { col: 3, s: 6, xs: 12, children: /* @__PURE__ */ jsx(LinkCard, { href: `content-releases/${id}`, isExternal: false, children: /* @__PURE__ */ jsxs(
|
|
1022
|
+
return /* @__PURE__ */ jsx(Grid, { gap: 4, children: releases.map(({ id, name, actions, scheduledAt }) => /* @__PURE__ */ jsx(GridItem, { col: 3, s: 6, xs: 12, children: /* @__PURE__ */ jsx(LinkCard, { href: `content-releases/${id}`, isExternal: false, children: /* @__PURE__ */ jsxs(
|
|
816
1023
|
Flex,
|
|
817
1024
|
{
|
|
818
1025
|
direction: "column",
|
|
@@ -827,7 +1034,10 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
827
1034
|
gap: 2,
|
|
828
1035
|
children: [
|
|
829
1036
|
/* @__PURE__ */ jsx(Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
|
|
830
|
-
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: formatMessage(
|
|
1037
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: IsSchedulingEnabled ? scheduledAt ? /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
|
|
1038
|
+
id: "content-releases.pages.Releases.not-scheduled",
|
|
1039
|
+
defaultMessage: "Not scheduled"
|
|
1040
|
+
}) : formatMessage(
|
|
831
1041
|
{
|
|
832
1042
|
id: "content-releases.page.Releases.release-item.entries",
|
|
833
1043
|
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
@@ -847,7 +1057,13 @@ const StyledAlert = styled(Alert)`
|
|
|
847
1057
|
}
|
|
848
1058
|
`;
|
|
849
1059
|
const INITIAL_FORM_VALUES = {
|
|
850
|
-
name: ""
|
|
1060
|
+
name: "",
|
|
1061
|
+
date: null,
|
|
1062
|
+
time: "",
|
|
1063
|
+
// Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
|
|
1064
|
+
isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
|
|
1065
|
+
scheduledAt: null,
|
|
1066
|
+
timezone: null
|
|
851
1067
|
};
|
|
852
1068
|
const ReleasesPage = () => {
|
|
853
1069
|
const tabRef = React.useRef(null);
|
|
@@ -907,9 +1123,11 @@ const ReleasesPage = () => {
|
|
|
907
1123
|
}
|
|
908
1124
|
});
|
|
909
1125
|
};
|
|
910
|
-
const handleAddRelease = async (
|
|
1126
|
+
const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
|
|
911
1127
|
const response2 = await createRelease({
|
|
912
|
-
name
|
|
1128
|
+
name,
|
|
1129
|
+
scheduledAt,
|
|
1130
|
+
timezone
|
|
913
1131
|
});
|
|
914
1132
|
if ("data" in response2) {
|
|
915
1133
|
toggleNotification({
|
|
@@ -1071,4 +1289,4 @@ const App = () => {
|
|
|
1071
1289
|
export {
|
|
1072
1290
|
App
|
|
1073
1291
|
};
|
|
1074
|
-
//# sourceMappingURL=App-
|
|
1292
|
+
//# sourceMappingURL=App-eVYKuxUc.mjs.map
|