@strapi/content-releases 0.0.0-next.3844395bef7efa05c25c6d4337306935905bc653 → 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-L1jSxCiL.mjs → App-ise7GunC.mjs} +493 -235
- package/dist/_chunks/App-ise7GunC.mjs.map +1 -0
- package/dist/_chunks/{App-_20W9dYa.js → App-w2Zq-wj5.js} +489 -230
- 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-gYDqKYFd.js → en-7P4i1cWH.js} +14 -3
- package/dist/_chunks/en-7P4i1cWH.js.map +1 -0
- package/dist/_chunks/{en-MyLPoISH.mjs → en-pb1wUzhy.mjs} +14 -3
- package/dist/_chunks/en-pb1wUzhy.mjs.map +1 -0
- package/dist/_chunks/{index-c4zRX_sg.mjs → index-D-Yjf60c.mjs} +89 -26
- package/dist/_chunks/index-D-Yjf60c.mjs.map +1 -0
- package/dist/_chunks/{index-KJa1Rb5F.js → index-Q8Pv7enO.js} +88 -25
- 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 +597 -382
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +597 -382
- package/dist/server/index.mjs.map +1 -1
- package/package.json +12 -9
- package/dist/_chunks/App-L1jSxCiL.mjs.map +0 -1
- package/dist/_chunks/App-_20W9dYa.js.map +0 -1
- package/dist/_chunks/en-MyLPoISH.mjs.map +0 -1
- package/dist/_chunks/en-gYDqKYFd.js.map +0 -1
- package/dist/_chunks/index-KJa1Rb5F.js.map +0 -1
- package/dist/_chunks/index-c4zRX_sg.mjs.map +0 -1
|
@@ -1,22 +1,42 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useNotification, useAPIErrorHandler, LoadingIndicatorPage, ConfirmDialog, useRBAC, RelativeTime, CheckPermissions, useQueryParams, AnErrorOccurred, NoContent, Table, PageSizeURLQuery, PaginationURLQuery, CheckPagePermissions } from "@strapi/helper-plugin";
|
|
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
|
-
import { unstable_useDocument } 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";
|
|
6
|
+
import { unstable_useDocument, useLicenseLimits } from "@strapi/admin/strapi-admin";
|
|
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,
|
|
@@ -201,14 +359,8 @@ const ReleaseDetailsLayout = ({
|
|
|
201
359
|
allowedActions: { canUpdate, canDelete }
|
|
202
360
|
} = useRBAC(PERMISSIONS);
|
|
203
361
|
const dispatch = useTypedDispatch();
|
|
362
|
+
const { trackUsage } = useTracking();
|
|
204
363
|
const release = data?.data;
|
|
205
|
-
const handleTogglePopover = () => {
|
|
206
|
-
setIsPopoverVisible((prev) => !prev);
|
|
207
|
-
};
|
|
208
|
-
const openReleaseModal = () => {
|
|
209
|
-
toggleEditReleaseModal();
|
|
210
|
-
handleTogglePopover();
|
|
211
|
-
};
|
|
212
364
|
const handlePublishRelease = async () => {
|
|
213
365
|
const response = await publishRelease({ id: releaseId });
|
|
214
366
|
if ("data" in response) {
|
|
@@ -219,6 +371,12 @@ const ReleaseDetailsLayout = ({
|
|
|
219
371
|
defaultMessage: "Release was published successfully."
|
|
220
372
|
})
|
|
221
373
|
});
|
|
374
|
+
const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
|
|
375
|
+
trackUsage("didPublishRelease", {
|
|
376
|
+
totalEntries: totalEntries2,
|
|
377
|
+
totalPublishedEntries,
|
|
378
|
+
totalUnpublishedEntries
|
|
379
|
+
});
|
|
222
380
|
} else if (isAxiosError(response.error)) {
|
|
223
381
|
toggleNotification({
|
|
224
382
|
type: "warning",
|
|
@@ -231,13 +389,21 @@ const ReleaseDetailsLayout = ({
|
|
|
231
389
|
});
|
|
232
390
|
}
|
|
233
391
|
};
|
|
234
|
-
const openWarningConfirmDialog = () => {
|
|
235
|
-
toggleWarningSubmit();
|
|
236
|
-
handleTogglePopover();
|
|
237
|
-
};
|
|
238
392
|
const handleRefresh = () => {
|
|
239
393
|
dispatch(releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
|
|
240
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
|
+
};
|
|
241
407
|
if (isLoadingDetails) {
|
|
242
408
|
return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
|
|
243
409
|
}
|
|
@@ -259,7 +425,7 @@ const ReleaseDetailsLayout = ({
|
|
|
259
425
|
);
|
|
260
426
|
}
|
|
261
427
|
const totalEntries = release.actions.meta.count || 0;
|
|
262
|
-
const
|
|
428
|
+
const hasCreatedByUser = Boolean(getCreatedByUser());
|
|
263
429
|
return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
|
|
264
430
|
/* @__PURE__ */ jsx(
|
|
265
431
|
HeaderLayout,
|
|
@@ -277,72 +443,98 @@ const ReleaseDetailsLayout = ({
|
|
|
277
443
|
defaultMessage: "Back"
|
|
278
444
|
}) }),
|
|
279
445
|
primaryAction: !release.releasedAt && /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
280
|
-
/* @__PURE__ */
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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
|
-
|
|
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
|
+
] }),
|
|
346
538
|
/* @__PURE__ */ jsx(Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
|
|
347
539
|
id: "content-releases.header.actions.refresh",
|
|
348
540
|
defaultMessage: "Refresh"
|
|
@@ -398,6 +590,9 @@ const ReleaseDetailsBody = () => {
|
|
|
398
590
|
isError: isReleaseError,
|
|
399
591
|
error: releaseError
|
|
400
592
|
} = useGetReleaseQuery({ id: releaseId });
|
|
593
|
+
const {
|
|
594
|
+
allowedActions: { canUpdate }
|
|
595
|
+
} = useRBAC(PERMISSIONS);
|
|
401
596
|
const release = releaseData?.data;
|
|
402
597
|
const selectedGroupBy = query?.groupBy || "contentType";
|
|
403
598
|
const {
|
|
@@ -411,7 +606,7 @@ const ReleaseDetailsBody = () => {
|
|
|
411
606
|
releaseId
|
|
412
607
|
});
|
|
413
608
|
const [updateReleaseAction] = useUpdateReleaseActionMutation();
|
|
414
|
-
const handleChangeType = async (e, actionId) => {
|
|
609
|
+
const handleChangeType = async (e, actionId, actionPath) => {
|
|
415
610
|
const response = await updateReleaseAction({
|
|
416
611
|
params: {
|
|
417
612
|
releaseId,
|
|
@@ -419,7 +614,11 @@ const ReleaseDetailsBody = () => {
|
|
|
419
614
|
},
|
|
420
615
|
body: {
|
|
421
616
|
type: e.target.value
|
|
422
|
-
}
|
|
617
|
+
},
|
|
618
|
+
query,
|
|
619
|
+
// We are passing the query params to make optimistic updates
|
|
620
|
+
actionPath
|
|
621
|
+
// We are passing the action path to found the position in the cache of the action for optimistic updates
|
|
423
622
|
});
|
|
424
623
|
if ("error" in response) {
|
|
425
624
|
if (isAxiosError(response.error)) {
|
|
@@ -500,7 +699,7 @@ const ReleaseDetailsBody = () => {
|
|
|
500
699
|
SingleSelect,
|
|
501
700
|
{
|
|
502
701
|
"aria-label": formatMessage({
|
|
503
|
-
id: "content-releases.pages.ReleaseDetails.groupBy.label",
|
|
702
|
+
id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
|
|
504
703
|
defaultMessage: "Group by"
|
|
505
704
|
}),
|
|
506
705
|
customizeContent: (value) => formatMessage(
|
|
@@ -518,7 +717,7 @@ const ReleaseDetailsBody = () => {
|
|
|
518
717
|
}
|
|
519
718
|
) }),
|
|
520
719
|
Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
|
|
521
|
-
/* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(Badge, { children: key }) }),
|
|
720
|
+
/* @__PURE__ */ jsx(Flex, { role: "separator", "aria-label": key, children: /* @__PURE__ */ jsx(Badge, { children: key }) }),
|
|
522
721
|
/* @__PURE__ */ jsx(
|
|
523
722
|
Table.Root,
|
|
524
723
|
{
|
|
@@ -588,56 +787,59 @@ const ReleaseDetailsBody = () => {
|
|
|
588
787
|
)
|
|
589
788
|
] }),
|
|
590
789
|
/* @__PURE__ */ jsx(Table.LoadingBody, {}),
|
|
591
|
-
/* @__PURE__ */ jsx(Table.Body, { children: releaseActions[key].map(
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
{
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
isPublish: type === "publish",
|
|
602
|
-
b: (children) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children })
|
|
603
|
-
}
|
|
604
|
-
) }) : /* @__PURE__ */ jsx(
|
|
605
|
-
ReleaseActionOptions,
|
|
606
|
-
{
|
|
607
|
-
selected: type,
|
|
608
|
-
handleChange: (e) => handleChangeType(e, id),
|
|
609
|
-
name: `release-action-${id}-type`
|
|
610
|
-
}
|
|
611
|
-
) }),
|
|
612
|
-
!release.releasedAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
613
|
-
/* @__PURE__ */ jsx(Td, { width: "20%", minWidth: "200px", children: /* @__PURE__ */ jsx(
|
|
614
|
-
EntryValidationText,
|
|
790
|
+
/* @__PURE__ */ jsx(Table.Body, { children: releaseActions[key].map(
|
|
791
|
+
({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxs(Tr, { children: [
|
|
792
|
+
/* @__PURE__ */ jsx(Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
|
|
793
|
+
/* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
|
|
794
|
+
/* @__PURE__ */ jsx(Td, { width: "10%", children: /* @__PURE__ */ jsx(Typography, { children: contentType.displayName || "" }) }),
|
|
795
|
+
/* @__PURE__ */ jsx(Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsx(Typography, { children: formatMessage(
|
|
796
|
+
{
|
|
797
|
+
id: "content-releases.page.ReleaseDetails.table.action-published",
|
|
798
|
+
defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
|
|
799
|
+
},
|
|
615
800
|
{
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
801
|
+
isPublish: type === "publish",
|
|
802
|
+
b: (children) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children })
|
|
803
|
+
}
|
|
804
|
+
) }) : /* @__PURE__ */ jsx(
|
|
805
|
+
ReleaseActionOptions,
|
|
806
|
+
{
|
|
807
|
+
selected: type,
|
|
808
|
+
handleChange: (e) => handleChangeType(e, id, [key, actionIndex]),
|
|
809
|
+
name: `release-action-${id}-type`,
|
|
810
|
+
disabled: !canUpdate
|
|
620
811
|
}
|
|
621
812
|
) }),
|
|
622
|
-
|
|
623
|
-
/* @__PURE__ */ jsx(
|
|
624
|
-
|
|
625
|
-
{
|
|
626
|
-
contentTypeUid: contentType.uid,
|
|
627
|
-
entryId: entry.id,
|
|
628
|
-
locale: locale?.code
|
|
629
|
-
}
|
|
630
|
-
),
|
|
631
|
-
/* @__PURE__ */ jsx(
|
|
632
|
-
ReleaseActionMenu.DeleteReleaseActionItem,
|
|
813
|
+
!release.releasedAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
814
|
+
/* @__PURE__ */ jsx(Td, { width: "20%", minWidth: "200px", children: /* @__PURE__ */ jsx(
|
|
815
|
+
EntryValidationText,
|
|
633
816
|
{
|
|
634
|
-
|
|
635
|
-
|
|
817
|
+
action: type,
|
|
818
|
+
schema: contentTypes?.[contentType.uid],
|
|
819
|
+
components,
|
|
820
|
+
entry
|
|
636
821
|
}
|
|
637
|
-
)
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
822
|
+
) }),
|
|
823
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxs(ReleaseActionMenu.Root, { children: [
|
|
824
|
+
/* @__PURE__ */ jsx(
|
|
825
|
+
ReleaseActionMenu.ReleaseActionEntryLinkItem,
|
|
826
|
+
{
|
|
827
|
+
contentTypeUid: contentType.uid,
|
|
828
|
+
entryId: entry.id,
|
|
829
|
+
locale: locale?.code
|
|
830
|
+
}
|
|
831
|
+
),
|
|
832
|
+
/* @__PURE__ */ jsx(
|
|
833
|
+
ReleaseActionMenu.DeleteReleaseActionItem,
|
|
834
|
+
{
|
|
835
|
+
releaseId: release.id,
|
|
836
|
+
actionId: id
|
|
837
|
+
}
|
|
838
|
+
)
|
|
839
|
+
] }) }) })
|
|
840
|
+
] })
|
|
841
|
+
] }, id)
|
|
842
|
+
) })
|
|
641
843
|
] })
|
|
642
844
|
}
|
|
643
845
|
)
|
|
@@ -684,11 +886,18 @@ const ReleaseDetailsPage = () => {
|
|
|
684
886
|
}
|
|
685
887
|
);
|
|
686
888
|
}
|
|
687
|
-
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") : "";
|
|
688
895
|
const handleEditRelease = async (values) => {
|
|
689
896
|
const response = await updateRelease({
|
|
690
897
|
id: releaseId,
|
|
691
|
-
name: values.name
|
|
898
|
+
name: values.name,
|
|
899
|
+
scheduledAt: values.scheduledAt,
|
|
900
|
+
timezone: values.timezone
|
|
692
901
|
});
|
|
693
902
|
if ("data" in response) {
|
|
694
903
|
toggleNotification({
|
|
@@ -742,7 +951,14 @@ const ReleaseDetailsPage = () => {
|
|
|
742
951
|
handleClose: toggleEditReleaseModal,
|
|
743
952
|
handleSubmit: handleEditRelease,
|
|
744
953
|
isLoading: isLoadingDetails || isSubmittingForm,
|
|
745
|
-
initialValues: {
|
|
954
|
+
initialValues: {
|
|
955
|
+
name: title || "",
|
|
956
|
+
scheduledAt,
|
|
957
|
+
date,
|
|
958
|
+
time,
|
|
959
|
+
isScheduled: Boolean(scheduledAt),
|
|
960
|
+
timezone
|
|
961
|
+
}
|
|
746
962
|
}
|
|
747
963
|
),
|
|
748
964
|
/* @__PURE__ */ jsx(
|
|
@@ -762,37 +978,6 @@ const ReleaseDetailsPage = () => {
|
|
|
762
978
|
}
|
|
763
979
|
);
|
|
764
980
|
};
|
|
765
|
-
const ReleasesLayout = ({
|
|
766
|
-
isLoading,
|
|
767
|
-
totalReleases,
|
|
768
|
-
onClickAddRelease,
|
|
769
|
-
children
|
|
770
|
-
}) => {
|
|
771
|
-
const { formatMessage } = useIntl();
|
|
772
|
-
return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoading, children: [
|
|
773
|
-
/* @__PURE__ */ jsx(
|
|
774
|
-
HeaderLayout,
|
|
775
|
-
{
|
|
776
|
-
title: formatMessage({
|
|
777
|
-
id: "content-releases.pages.Releases.title",
|
|
778
|
-
defaultMessage: "Releases"
|
|
779
|
-
}),
|
|
780
|
-
subtitle: !isLoading && formatMessage(
|
|
781
|
-
{
|
|
782
|
-
id: "content-releases.pages.Releases.header-subtitle",
|
|
783
|
-
defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
|
|
784
|
-
},
|
|
785
|
-
{ number: totalReleases }
|
|
786
|
-
),
|
|
787
|
-
primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(Button, { startIcon: /* @__PURE__ */ jsx(Plus, {}), onClick: onClickAddRelease, children: formatMessage({
|
|
788
|
-
id: "content-releases.header.actions.add-release",
|
|
789
|
-
defaultMessage: "New release"
|
|
790
|
-
}) }) })
|
|
791
|
-
}
|
|
792
|
-
),
|
|
793
|
-
children
|
|
794
|
-
] });
|
|
795
|
-
};
|
|
796
981
|
const LinkCard = styled(Link$2)`
|
|
797
982
|
display: block;
|
|
798
983
|
`;
|
|
@@ -844,8 +1029,22 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
844
1029
|
}
|
|
845
1030
|
) }) }, id)) });
|
|
846
1031
|
};
|
|
1032
|
+
const StyledAlert = styled(Alert)`
|
|
1033
|
+
button {
|
|
1034
|
+
display: none;
|
|
1035
|
+
}
|
|
1036
|
+
p + div {
|
|
1037
|
+
margin-left: auto;
|
|
1038
|
+
}
|
|
1039
|
+
`;
|
|
847
1040
|
const INITIAL_FORM_VALUES = {
|
|
848
|
-
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
|
|
849
1048
|
};
|
|
850
1049
|
const ReleasesPage = () => {
|
|
851
1050
|
const tabRef = React.useRef(null);
|
|
@@ -858,6 +1057,9 @@ const ReleasesPage = () => {
|
|
|
858
1057
|
const [{ query }, setQuery] = useQueryParams();
|
|
859
1058
|
const response = useGetReleasesQuery(query);
|
|
860
1059
|
const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();
|
|
1060
|
+
const { getFeature } = useLicenseLimits();
|
|
1061
|
+
const { maximumReleases = 3 } = getFeature("cms-content-releases");
|
|
1062
|
+
const { trackUsage } = useTracking();
|
|
861
1063
|
const { isLoading, isSuccess, isError } = response;
|
|
862
1064
|
const activeTab = response?.currentData?.meta?.activeTab || "pending";
|
|
863
1065
|
const activeTabIndex = ["pending", "done"].indexOf(activeTab);
|
|
@@ -886,9 +1088,10 @@ const ReleasesPage = () => {
|
|
|
886
1088
|
setReleaseModalShown((prev) => !prev);
|
|
887
1089
|
};
|
|
888
1090
|
if (isLoading) {
|
|
889
|
-
return /* @__PURE__ */ jsx(
|
|
1091
|
+
return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
|
|
890
1092
|
}
|
|
891
1093
|
const totalReleases = isSuccess && response.currentData?.meta?.pagination?.total || 0;
|
|
1094
|
+
const hasReachedMaximumPendingReleases = totalReleases >= maximumReleases;
|
|
892
1095
|
const handleTabChange = (index) => {
|
|
893
1096
|
setQuery({
|
|
894
1097
|
...query,
|
|
@@ -901,9 +1104,11 @@ const ReleasesPage = () => {
|
|
|
901
1104
|
}
|
|
902
1105
|
});
|
|
903
1106
|
};
|
|
904
|
-
const handleAddRelease = async (
|
|
1107
|
+
const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
|
|
905
1108
|
const response2 = await createRelease({
|
|
906
|
-
name
|
|
1109
|
+
name,
|
|
1110
|
+
scheduledAt,
|
|
1111
|
+
timezone
|
|
907
1112
|
});
|
|
908
1113
|
if ("data" in response2) {
|
|
909
1114
|
toggleNotification({
|
|
@@ -913,6 +1118,7 @@ const ReleasesPage = () => {
|
|
|
913
1118
|
defaultMessage: "Release created."
|
|
914
1119
|
})
|
|
915
1120
|
});
|
|
1121
|
+
trackUsage("didCreateRelease");
|
|
916
1122
|
push(`/plugins/content-releases/${response2.data.data.id}`);
|
|
917
1123
|
} else if (isAxiosError(response2.error)) {
|
|
918
1124
|
toggleNotification({
|
|
@@ -926,8 +1132,60 @@ const ReleasesPage = () => {
|
|
|
926
1132
|
});
|
|
927
1133
|
}
|
|
928
1134
|
};
|
|
929
|
-
return /* @__PURE__ */ jsxs(
|
|
1135
|
+
return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoading, children: [
|
|
1136
|
+
/* @__PURE__ */ jsx(
|
|
1137
|
+
HeaderLayout,
|
|
1138
|
+
{
|
|
1139
|
+
title: formatMessage({
|
|
1140
|
+
id: "content-releases.pages.Releases.title",
|
|
1141
|
+
defaultMessage: "Releases"
|
|
1142
|
+
}),
|
|
1143
|
+
subtitle: formatMessage(
|
|
1144
|
+
{
|
|
1145
|
+
id: "content-releases.pages.Releases.header-subtitle",
|
|
1146
|
+
defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
|
|
1147
|
+
},
|
|
1148
|
+
{ number: totalReleases }
|
|
1149
|
+
),
|
|
1150
|
+
primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(
|
|
1151
|
+
Button,
|
|
1152
|
+
{
|
|
1153
|
+
startIcon: /* @__PURE__ */ jsx(Plus, {}),
|
|
1154
|
+
onClick: toggleAddReleaseModal,
|
|
1155
|
+
disabled: hasReachedMaximumPendingReleases,
|
|
1156
|
+
children: formatMessage({
|
|
1157
|
+
id: "content-releases.header.actions.add-release",
|
|
1158
|
+
defaultMessage: "New release"
|
|
1159
|
+
})
|
|
1160
|
+
}
|
|
1161
|
+
) })
|
|
1162
|
+
}
|
|
1163
|
+
),
|
|
930
1164
|
/* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1165
|
+
activeTab === "pending" && hasReachedMaximumPendingReleases && /* @__PURE__ */ jsx(
|
|
1166
|
+
StyledAlert,
|
|
1167
|
+
{
|
|
1168
|
+
marginBottom: 6,
|
|
1169
|
+
action: /* @__PURE__ */ jsx(Link$2, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
|
|
1170
|
+
id: "content-releases.pages.Releases.max-limit-reached.action",
|
|
1171
|
+
defaultMessage: "Explore plans"
|
|
1172
|
+
}) }),
|
|
1173
|
+
title: formatMessage(
|
|
1174
|
+
{
|
|
1175
|
+
id: "content-releases.pages.Releases.max-limit-reached.title",
|
|
1176
|
+
defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
|
|
1177
|
+
},
|
|
1178
|
+
{ number: maximumReleases }
|
|
1179
|
+
),
|
|
1180
|
+
onClose: () => {
|
|
1181
|
+
},
|
|
1182
|
+
closeLabel: "",
|
|
1183
|
+
children: formatMessage({
|
|
1184
|
+
id: "content-releases.pages.Releases.max-limit-reached.message",
|
|
1185
|
+
defaultMessage: "Upgrade to manage an unlimited number of releases."
|
|
1186
|
+
})
|
|
1187
|
+
}
|
|
1188
|
+
),
|
|
931
1189
|
/* @__PURE__ */ jsxs(
|
|
932
1190
|
TabGroup,
|
|
933
1191
|
{
|
|
@@ -1012,4 +1270,4 @@ const App = () => {
|
|
|
1012
1270
|
export {
|
|
1013
1271
|
App
|
|
1014
1272
|
};
|
|
1015
|
-
//# sourceMappingURL=App-
|
|
1273
|
+
//# sourceMappingURL=App-ise7GunC.mjs.map
|