@strapi/content-releases 0.0.0-next.6d384ed205b7f0792d9bea79195f01b30463cfa0 → 0.0.0-next.73143c28059b343ba62d98c29672ab114562fbbc
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-WkwjSaDY.mjs → App-g3vtS2Wa.mjs} +385 -174
- package/dist/_chunks/App-g3vtS2Wa.mjs.map +1 -0
- package/dist/_chunks/{App-IQIHCiSO.js → App-lnXbSPgp.js} +383 -171
- package/dist/_chunks/App-lnXbSPgp.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-m9eTk4UF.mjs → en-WuuhP6Bn.mjs} +15 -4
- package/dist/_chunks/en-WuuhP6Bn.mjs.map +1 -0
- package/dist/_chunks/{en-r9YocBH0.js → en-gcJJ5htG.js} +15 -4
- package/dist/_chunks/en-gcJJ5htG.js.map +1 -0
- package/dist/_chunks/{index-u_da7WHb.js → index-ItlgrLcr.js} +122 -19
- package/dist/_chunks/index-ItlgrLcr.js.map +1 -0
- package/dist/_chunks/{index-CyVlvX8h.mjs → index-uGex_IIQ.mjs} +126 -23
- package/dist/_chunks/index-uGex_IIQ.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +2 -2
- package/dist/server/index.js +814 -418
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +813 -418
- package/dist/server/index.mjs.map +1 -1
- package/package.json +13 -11
- package/dist/_chunks/App-IQIHCiSO.js.map +0 -1
- package/dist/_chunks/App-WkwjSaDY.mjs.map +0 -1
- package/dist/_chunks/en-m9eTk4UF.mjs.map +0 -1
- package/dist/_chunks/en-r9YocBH0.js.map +0 -1
- package/dist/_chunks/index-CyVlvX8h.mjs.map +0 -1
- package/dist/_chunks/index-u_da7WHb.js.map +0 -1
|
@@ -1,15 +1,18 @@
|
|
|
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-uGex_IIQ.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, Box, Checkbox, 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";
|
|
@@ -17,8 +20,23 @@ import "@reduxjs/toolkit/query/react";
|
|
|
17
20
|
import "react-redux";
|
|
18
21
|
const RELEASE_SCHEMA = yup.object().shape({
|
|
19
22
|
name: yup.string().trim().required(),
|
|
20
|
-
|
|
21
|
-
|
|
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
|
+
})
|
|
22
40
|
}).required().noUnknown();
|
|
23
41
|
const ReleaseModal = ({
|
|
24
42
|
handleClose,
|
|
@@ -29,6 +47,24 @@ const ReleaseModal = ({
|
|
|
29
47
|
const { formatMessage } = useIntl();
|
|
30
48
|
const { pathname } = useLocation();
|
|
31
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
|
+
};
|
|
32
68
|
return /* @__PURE__ */ jsxs(ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
|
|
33
69
|
/* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage(
|
|
34
70
|
{
|
|
@@ -40,45 +76,134 @@ const ReleaseModal = ({
|
|
|
40
76
|
/* @__PURE__ */ jsx(
|
|
41
77
|
Formik,
|
|
42
78
|
{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
+
},
|
|
46
90
|
validationSchema: RELEASE_SCHEMA,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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(Box, { width: "max-content", children: /* @__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
|
+
] }) }),
|
|
62
196
|
/* @__PURE__ */ jsx(
|
|
63
197
|
ModalFooter,
|
|
64
198
|
{
|
|
65
199
|
startActions: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }),
|
|
66
|
-
endActions: /* @__PURE__ */ jsx(
|
|
67
|
-
Button,
|
|
200
|
+
endActions: /* @__PURE__ */ jsx(Button, { name: "submit", loading: isLoading, type: "submit", children: formatMessage(
|
|
68
201
|
{
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
{
|
|
75
|
-
id: "content-releases.modal.form.button.submit",
|
|
76
|
-
defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
|
|
77
|
-
},
|
|
78
|
-
{ isCreatingRelease }
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
)
|
|
202
|
+
id: "content-releases.modal.form.button.submit",
|
|
203
|
+
defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
|
|
204
|
+
},
|
|
205
|
+
{ isCreatingRelease }
|
|
206
|
+
) })
|
|
82
207
|
}
|
|
83
208
|
)
|
|
84
209
|
] })
|
|
@@ -86,22 +211,72 @@ const ReleaseModal = ({
|
|
|
86
211
|
)
|
|
87
212
|
] });
|
|
88
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
|
+
onTextValueChange: (timezone) => {
|
|
252
|
+
setFieldValue("timezone", timezone);
|
|
253
|
+
},
|
|
254
|
+
onClear: () => {
|
|
255
|
+
setFieldValue("timezone", "");
|
|
256
|
+
},
|
|
257
|
+
error: errors.timezone,
|
|
258
|
+
required: true,
|
|
259
|
+
children: timezoneList.map((timezone) => /* @__PURE__ */ jsx(ComboboxOption, { value: timezone.value, children: timezone.value.replace("_", " ") }, timezone.value))
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
};
|
|
89
263
|
const ReleaseInfoWrapper = styled(Flex)`
|
|
90
264
|
align-self: stretch;
|
|
91
265
|
border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
|
|
92
266
|
border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
|
|
93
267
|
border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
|
|
94
268
|
`;
|
|
95
|
-
const
|
|
96
|
-
align-self: stretch;
|
|
97
|
-
cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
|
|
98
|
-
|
|
269
|
+
const StyledMenuItem = styled(Menu.Item)`
|
|
99
270
|
svg path {
|
|
100
271
|
fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
|
|
101
272
|
}
|
|
102
273
|
span {
|
|
103
274
|
color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
|
|
104
275
|
}
|
|
276
|
+
|
|
277
|
+
&:hover {
|
|
278
|
+
background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
|
|
279
|
+
}
|
|
105
280
|
`;
|
|
106
281
|
const PencilIcon = styled(Pencil)`
|
|
107
282
|
width: ${({ theme }) => theme.spaces[3]};
|
|
@@ -120,24 +295,6 @@ const TrashIcon = styled(Trash)`
|
|
|
120
295
|
const TypographyMaxWidth = styled(Typography)`
|
|
121
296
|
max-width: 300px;
|
|
122
297
|
`;
|
|
123
|
-
const PopoverButton = ({ onClick, disabled, children }) => {
|
|
124
|
-
return /* @__PURE__ */ jsx(
|
|
125
|
-
StyledFlex,
|
|
126
|
-
{
|
|
127
|
-
paddingTop: 2,
|
|
128
|
-
paddingBottom: 2,
|
|
129
|
-
paddingLeft: 4,
|
|
130
|
-
paddingRight: 4,
|
|
131
|
-
alignItems: "center",
|
|
132
|
-
gap: 2,
|
|
133
|
-
as: "button",
|
|
134
|
-
hasRadius: true,
|
|
135
|
-
onClick,
|
|
136
|
-
disabled,
|
|
137
|
-
children
|
|
138
|
-
}
|
|
139
|
-
);
|
|
140
|
-
};
|
|
141
298
|
const EntryValidationText = ({ action, schema, components, entry }) => {
|
|
142
299
|
const { formatMessage } = useIntl();
|
|
143
300
|
const { validate } = unstable_useDocument();
|
|
@@ -186,10 +343,8 @@ const ReleaseDetailsLayout = ({
|
|
|
186
343
|
toggleWarningSubmit,
|
|
187
344
|
children
|
|
188
345
|
}) => {
|
|
189
|
-
const { formatMessage } = useIntl();
|
|
346
|
+
const { formatMessage, formatDate, formatTime } = useIntl();
|
|
190
347
|
const { releaseId } = useParams();
|
|
191
|
-
const [isPopoverVisible, setIsPopoverVisible] = React.useState(false);
|
|
192
|
-
const moreButtonRef = React.useRef(null);
|
|
193
348
|
const {
|
|
194
349
|
data,
|
|
195
350
|
isLoading: isLoadingDetails,
|
|
@@ -205,13 +360,6 @@ const ReleaseDetailsLayout = ({
|
|
|
205
360
|
const dispatch = useTypedDispatch();
|
|
206
361
|
const { trackUsage } = useTracking();
|
|
207
362
|
const release = data?.data;
|
|
208
|
-
const handleTogglePopover = () => {
|
|
209
|
-
setIsPopoverVisible((prev) => !prev);
|
|
210
|
-
};
|
|
211
|
-
const openReleaseModal = () => {
|
|
212
|
-
toggleEditReleaseModal();
|
|
213
|
-
handleTogglePopover();
|
|
214
|
-
};
|
|
215
363
|
const handlePublishRelease = async () => {
|
|
216
364
|
const response = await publishRelease({ id: releaseId });
|
|
217
365
|
if ("data" in response) {
|
|
@@ -240,10 +388,6 @@ const ReleaseDetailsLayout = ({
|
|
|
240
388
|
});
|
|
241
389
|
}
|
|
242
390
|
};
|
|
243
|
-
const openWarningConfirmDialog = () => {
|
|
244
|
-
toggleWarningSubmit();
|
|
245
|
-
handleTogglePopover();
|
|
246
|
-
};
|
|
247
391
|
const handleRefresh = () => {
|
|
248
392
|
dispatch(releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
|
|
249
393
|
};
|
|
@@ -281,89 +425,124 @@ const ReleaseDetailsLayout = ({
|
|
|
281
425
|
}
|
|
282
426
|
const totalEntries = release.actions.meta.count || 0;
|
|
283
427
|
const hasCreatedByUser = Boolean(getCreatedByUser());
|
|
428
|
+
const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
|
|
429
|
+
const isScheduled = release.scheduledAt && release.timezone;
|
|
430
|
+
const numberOfEntriesText = formatMessage(
|
|
431
|
+
{
|
|
432
|
+
id: "content-releases.pages.Details.header-subtitle",
|
|
433
|
+
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
434
|
+
},
|
|
435
|
+
{ number: totalEntries }
|
|
436
|
+
);
|
|
437
|
+
const scheduledText = isScheduled ? formatMessage(
|
|
438
|
+
{
|
|
439
|
+
id: "content-releases.pages.ReleaseDetails.header-subtitle.scheduled",
|
|
440
|
+
defaultMessage: "Scheduled for {date} at {time} ({offset})"
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
date: formatDate(new Date(release.scheduledAt), {
|
|
444
|
+
weekday: "long",
|
|
445
|
+
day: "numeric",
|
|
446
|
+
month: "long",
|
|
447
|
+
year: "numeric",
|
|
448
|
+
timeZone: release.timezone
|
|
449
|
+
}),
|
|
450
|
+
time: formatTime(new Date(release.scheduledAt), {
|
|
451
|
+
timeZone: release.timezone,
|
|
452
|
+
hourCycle: "h23"
|
|
453
|
+
}),
|
|
454
|
+
offset: getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
|
|
455
|
+
}
|
|
456
|
+
) : "";
|
|
284
457
|
return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
|
|
285
458
|
/* @__PURE__ */ jsx(
|
|
286
459
|
HeaderLayout,
|
|
287
460
|
{
|
|
288
461
|
title: release.name,
|
|
289
|
-
subtitle:
|
|
290
|
-
{
|
|
291
|
-
id: "content-releases.pages.Details.header-subtitle",
|
|
292
|
-
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
293
|
-
},
|
|
294
|
-
{ number: totalEntries }
|
|
295
|
-
),
|
|
462
|
+
subtitle: numberOfEntriesText + (IsSchedulingEnabled && isScheduled ? ` - ${scheduledText}` : ""),
|
|
296
463
|
navigationAction: /* @__PURE__ */ jsx(Link, { startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
|
|
297
464
|
id: "global.back",
|
|
298
465
|
defaultMessage: "Back"
|
|
299
466
|
}) }),
|
|
300
467
|
primaryAction: !release.releasedAt && /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
301
|
-
/* @__PURE__ */
|
|
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
|
-
|
|
365
|
-
|
|
366
|
-
|
|
468
|
+
/* @__PURE__ */ jsxs(Menu.Root, { children: [
|
|
469
|
+
/* @__PURE__ */ jsx(
|
|
470
|
+
Menu.Trigger,
|
|
471
|
+
{
|
|
472
|
+
as: IconButton,
|
|
473
|
+
paddingLeft: 2,
|
|
474
|
+
paddingRight: 2,
|
|
475
|
+
"aria-label": formatMessage({
|
|
476
|
+
id: "content-releases.header.actions.open-release-actions",
|
|
477
|
+
defaultMessage: "Release edit and delete menu"
|
|
478
|
+
}),
|
|
479
|
+
icon: /* @__PURE__ */ jsx(More, {}),
|
|
480
|
+
variant: "tertiary"
|
|
481
|
+
}
|
|
482
|
+
),
|
|
483
|
+
/* @__PURE__ */ jsxs(Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: [
|
|
484
|
+
/* @__PURE__ */ jsxs(
|
|
485
|
+
Flex,
|
|
486
|
+
{
|
|
487
|
+
alignItems: "center",
|
|
488
|
+
justifyContent: "center",
|
|
489
|
+
direction: "column",
|
|
490
|
+
padding: 1,
|
|
491
|
+
width: "100%",
|
|
492
|
+
children: [
|
|
493
|
+
/* @__PURE__ */ jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
|
|
494
|
+
/* @__PURE__ */ jsx(PencilIcon, {}),
|
|
495
|
+
/* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
|
|
496
|
+
id: "content-releases.header.actions.edit",
|
|
497
|
+
defaultMessage: "Edit"
|
|
498
|
+
}) })
|
|
499
|
+
] }) }),
|
|
500
|
+
/* @__PURE__ */ jsx(
|
|
501
|
+
StyledMenuItem,
|
|
502
|
+
{
|
|
503
|
+
disabled: !canDelete,
|
|
504
|
+
onSelect: toggleWarningSubmit,
|
|
505
|
+
variant: "danger",
|
|
506
|
+
children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
|
|
507
|
+
/* @__PURE__ */ jsx(TrashIcon, {}),
|
|
508
|
+
/* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
|
|
509
|
+
id: "content-releases.header.actions.delete",
|
|
510
|
+
defaultMessage: "Delete"
|
|
511
|
+
}) })
|
|
512
|
+
] })
|
|
513
|
+
}
|
|
514
|
+
)
|
|
515
|
+
]
|
|
516
|
+
}
|
|
517
|
+
),
|
|
518
|
+
/* @__PURE__ */ jsxs(
|
|
519
|
+
ReleaseInfoWrapper,
|
|
520
|
+
{
|
|
521
|
+
direction: "column",
|
|
522
|
+
justifyContent: "center",
|
|
523
|
+
alignItems: "flex-start",
|
|
524
|
+
gap: 1,
|
|
525
|
+
padding: 5,
|
|
526
|
+
children: [
|
|
527
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
|
|
528
|
+
id: "content-releases.header.actions.created",
|
|
529
|
+
defaultMessage: "Created"
|
|
530
|
+
}) }),
|
|
531
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "pi", color: "neutral300", children: [
|
|
532
|
+
/* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(release.createdAt) }),
|
|
533
|
+
formatMessage(
|
|
534
|
+
{
|
|
535
|
+
id: "content-releases.header.actions.created.description",
|
|
536
|
+
defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
|
|
537
|
+
},
|
|
538
|
+
{ createdBy: getCreatedByUser(), hasCreatedByUser }
|
|
539
|
+
)
|
|
540
|
+
] })
|
|
541
|
+
]
|
|
542
|
+
}
|
|
543
|
+
)
|
|
544
|
+
] })
|
|
545
|
+
] }),
|
|
367
546
|
/* @__PURE__ */ jsx(Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
|
|
368
547
|
id: "content-releases.header.actions.refresh",
|
|
369
548
|
defaultMessage: "Refresh"
|
|
@@ -419,6 +598,9 @@ const ReleaseDetailsBody = () => {
|
|
|
419
598
|
isError: isReleaseError,
|
|
420
599
|
error: releaseError
|
|
421
600
|
} = useGetReleaseQuery({ id: releaseId });
|
|
601
|
+
const {
|
|
602
|
+
allowedActions: { canUpdate }
|
|
603
|
+
} = useRBAC(PERMISSIONS);
|
|
422
604
|
const release = releaseData?.data;
|
|
423
605
|
const selectedGroupBy = query?.groupBy || "contentType";
|
|
424
606
|
const {
|
|
@@ -632,7 +814,8 @@ const ReleaseDetailsBody = () => {
|
|
|
632
814
|
{
|
|
633
815
|
selected: type,
|
|
634
816
|
handleChange: (e) => handleChangeType(e, id, [key, actionIndex]),
|
|
635
|
-
name: `release-action-${id}-type
|
|
817
|
+
name: `release-action-${id}-type`,
|
|
818
|
+
disabled: !canUpdate
|
|
636
819
|
}
|
|
637
820
|
) }),
|
|
638
821
|
!release.releasedAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -711,11 +894,18 @@ const ReleaseDetailsPage = () => {
|
|
|
711
894
|
}
|
|
712
895
|
);
|
|
713
896
|
}
|
|
714
|
-
const
|
|
897
|
+
const releaseData = isSuccessDetails && data?.data || null;
|
|
898
|
+
const title = releaseData?.name || "";
|
|
899
|
+
const timezone = releaseData?.timezone ?? null;
|
|
900
|
+
const scheduledAt = releaseData?.scheduledAt && timezone ? utcToZonedTime(releaseData.scheduledAt, timezone) : null;
|
|
901
|
+
const date = scheduledAt ? new Date(format(scheduledAt, "yyyy-MM-dd")) : null;
|
|
902
|
+
const time = scheduledAt ? format(scheduledAt, "HH:mm") : "";
|
|
715
903
|
const handleEditRelease = async (values) => {
|
|
716
904
|
const response = await updateRelease({
|
|
717
905
|
id: releaseId,
|
|
718
|
-
name: values.name
|
|
906
|
+
name: values.name,
|
|
907
|
+
scheduledAt: values.scheduledAt,
|
|
908
|
+
timezone: values.timezone
|
|
719
909
|
});
|
|
720
910
|
if ("data" in response) {
|
|
721
911
|
toggleNotification({
|
|
@@ -769,7 +959,14 @@ const ReleaseDetailsPage = () => {
|
|
|
769
959
|
handleClose: toggleEditReleaseModal,
|
|
770
960
|
handleSubmit: handleEditRelease,
|
|
771
961
|
isLoading: isLoadingDetails || isSubmittingForm,
|
|
772
|
-
initialValues: {
|
|
962
|
+
initialValues: {
|
|
963
|
+
name: title || "",
|
|
964
|
+
scheduledAt,
|
|
965
|
+
date,
|
|
966
|
+
time,
|
|
967
|
+
isScheduled: Boolean(scheduledAt),
|
|
968
|
+
timezone
|
|
969
|
+
}
|
|
773
970
|
}
|
|
774
971
|
),
|
|
775
972
|
/* @__PURE__ */ jsx(
|
|
@@ -794,6 +991,7 @@ const LinkCard = styled(Link$2)`
|
|
|
794
991
|
`;
|
|
795
992
|
const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
796
993
|
const { formatMessage } = useIntl();
|
|
994
|
+
const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
|
|
797
995
|
if (isError) {
|
|
798
996
|
return /* @__PURE__ */ jsx(AnErrorOccurred, {});
|
|
799
997
|
}
|
|
@@ -814,7 +1012,7 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
814
1012
|
}
|
|
815
1013
|
);
|
|
816
1014
|
}
|
|
817
|
-
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(
|
|
1015
|
+
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(
|
|
818
1016
|
Flex,
|
|
819
1017
|
{
|
|
820
1018
|
direction: "column",
|
|
@@ -829,7 +1027,10 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
829
1027
|
gap: 2,
|
|
830
1028
|
children: [
|
|
831
1029
|
/* @__PURE__ */ jsx(Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
|
|
832
|
-
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: formatMessage(
|
|
1030
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: IsSchedulingEnabled ? scheduledAt ? /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
|
|
1031
|
+
id: "content-releases.pages.Releases.not-scheduled",
|
|
1032
|
+
defaultMessage: "Not scheduled"
|
|
1033
|
+
}) : formatMessage(
|
|
833
1034
|
{
|
|
834
1035
|
id: "content-releases.page.Releases.release-item.entries",
|
|
835
1036
|
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
@@ -849,7 +1050,13 @@ const StyledAlert = styled(Alert)`
|
|
|
849
1050
|
}
|
|
850
1051
|
`;
|
|
851
1052
|
const INITIAL_FORM_VALUES = {
|
|
852
|
-
name: ""
|
|
1053
|
+
name: "",
|
|
1054
|
+
date: null,
|
|
1055
|
+
time: "",
|
|
1056
|
+
// Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
|
|
1057
|
+
isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
|
|
1058
|
+
scheduledAt: null,
|
|
1059
|
+
timezone: null
|
|
853
1060
|
};
|
|
854
1061
|
const ReleasesPage = () => {
|
|
855
1062
|
const tabRef = React.useRef(null);
|
|
@@ -895,8 +1102,8 @@ const ReleasesPage = () => {
|
|
|
895
1102
|
if (isLoading) {
|
|
896
1103
|
return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
|
|
897
1104
|
}
|
|
898
|
-
const
|
|
899
|
-
const hasReachedMaximumPendingReleases =
|
|
1105
|
+
const totalPendingReleases = isSuccess && response.currentData?.meta?.pendingReleasesCount || 0;
|
|
1106
|
+
const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
|
|
900
1107
|
const handleTabChange = (index) => {
|
|
901
1108
|
setQuery({
|
|
902
1109
|
...query,
|
|
@@ -909,9 +1116,11 @@ const ReleasesPage = () => {
|
|
|
909
1116
|
}
|
|
910
1117
|
});
|
|
911
1118
|
};
|
|
912
|
-
const handleAddRelease = async (
|
|
1119
|
+
const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
|
|
913
1120
|
const response2 = await createRelease({
|
|
914
|
-
name
|
|
1121
|
+
name,
|
|
1122
|
+
scheduledAt,
|
|
1123
|
+
timezone
|
|
915
1124
|
});
|
|
916
1125
|
if ("data" in response2) {
|
|
917
1126
|
toggleNotification({
|
|
@@ -943,13 +1152,10 @@ const ReleasesPage = () => {
|
|
|
943
1152
|
id: "content-releases.pages.Releases.title",
|
|
944
1153
|
defaultMessage: "Releases"
|
|
945
1154
|
}),
|
|
946
|
-
subtitle: formatMessage(
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
},
|
|
951
|
-
{ number: totalReleases }
|
|
952
|
-
),
|
|
1155
|
+
subtitle: formatMessage({
|
|
1156
|
+
id: "content-releases.pages.Releases.header-subtitle",
|
|
1157
|
+
defaultMessage: "Create and manage content updates"
|
|
1158
|
+
}),
|
|
953
1159
|
primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(
|
|
954
1160
|
Button,
|
|
955
1161
|
{
|
|
@@ -965,7 +1171,7 @@ const ReleasesPage = () => {
|
|
|
965
1171
|
}
|
|
966
1172
|
),
|
|
967
1173
|
/* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
968
|
-
|
|
1174
|
+
hasReachedMaximumPendingReleases && /* @__PURE__ */ jsx(
|
|
969
1175
|
StyledAlert,
|
|
970
1176
|
{
|
|
971
1177
|
marginBottom: 6,
|
|
@@ -1003,10 +1209,15 @@ const ReleasesPage = () => {
|
|
|
1003
1209
|
children: [
|
|
1004
1210
|
/* @__PURE__ */ jsxs(Box, { paddingBottom: 8, children: [
|
|
1005
1211
|
/* @__PURE__ */ jsxs(Tabs, { children: [
|
|
1006
|
-
/* @__PURE__ */ jsx(Tab, { children: formatMessage(
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1212
|
+
/* @__PURE__ */ jsx(Tab, { children: formatMessage(
|
|
1213
|
+
{
|
|
1214
|
+
id: "content-releases.pages.Releases.tab.pending",
|
|
1215
|
+
defaultMessage: "Pending ({count})"
|
|
1216
|
+
},
|
|
1217
|
+
{
|
|
1218
|
+
count: totalPendingReleases
|
|
1219
|
+
}
|
|
1220
|
+
) }),
|
|
1010
1221
|
/* @__PURE__ */ jsx(Tab, { children: formatMessage({
|
|
1011
1222
|
id: "content-releases.pages.Releases.tab.done",
|
|
1012
1223
|
defaultMessage: "Done"
|
|
@@ -1035,7 +1246,7 @@ const ReleasesPage = () => {
|
|
|
1035
1246
|
]
|
|
1036
1247
|
}
|
|
1037
1248
|
),
|
|
1038
|
-
|
|
1249
|
+
response.currentData?.meta?.pagination?.total ? /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
|
|
1039
1250
|
/* @__PURE__ */ jsx(
|
|
1040
1251
|
PageSizeURLQuery,
|
|
1041
1252
|
{
|
|
@@ -1051,7 +1262,7 @@ const ReleasesPage = () => {
|
|
|
1051
1262
|
}
|
|
1052
1263
|
}
|
|
1053
1264
|
)
|
|
1054
|
-
] })
|
|
1265
|
+
] }) : null
|
|
1055
1266
|
] }) }),
|
|
1056
1267
|
releaseModalShown && /* @__PURE__ */ jsx(
|
|
1057
1268
|
ReleaseModal,
|
|
@@ -1073,4 +1284,4 @@ const App = () => {
|
|
|
1073
1284
|
export {
|
|
1074
1285
|
App
|
|
1075
1286
|
};
|
|
1076
|
-
//# sourceMappingURL=App-
|
|
1287
|
+
//# sourceMappingURL=App-g3vtS2Wa.mjs.map
|