@strapi/content-releases 0.0.0-next.6d59515520a3850456f256fb0e4c54b75054ddf4 → 0.0.0-next.898f8ae81b2cb3f89bd012e9db20a2d9b78a48d2
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-_20W9dYa.js → App-OK4Xac-O.js} +518 -240
- package/dist/_chunks/App-OK4Xac-O.js.map +1 -0
- package/dist/_chunks/{App-L1jSxCiL.mjs → App-xAkiD42p.mjs} +522 -245
- package/dist/_chunks/App-xAkiD42p.mjs.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-r0otWaln.js} +18 -4
- package/dist/_chunks/en-r0otWaln.js.map +1 -0
- package/dist/_chunks/{en-MyLPoISH.mjs → en-veqvqeEr.mjs} +18 -4
- package/dist/_chunks/en-veqvqeEr.mjs.map +1 -0
- package/dist/_chunks/{index-KJa1Rb5F.js → index-JvA2_26n.js} +134 -27
- package/dist/_chunks/index-JvA2_26n.js.map +1 -0
- package/dist/_chunks/{index-c4zRX_sg.mjs → index-exoiSU3V.mjs} +139 -32
- package/dist/_chunks/index-exoiSU3V.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +2 -2
- 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
|
@@ -3,14 +3,17 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const helperPlugin = require("@strapi/helper-plugin");
|
|
5
5
|
const reactRouterDom = require("react-router-dom");
|
|
6
|
-
const index = require("./index-
|
|
6
|
+
const index = require("./index-JvA2_26n.js");
|
|
7
7
|
const React = require("react");
|
|
8
8
|
const strapiAdmin = require("@strapi/admin/strapi-admin");
|
|
9
9
|
const designSystem = require("@strapi/design-system");
|
|
10
10
|
const v2 = require("@strapi/design-system/v2");
|
|
11
11
|
const icons = require("@strapi/icons");
|
|
12
|
+
const format = require("date-fns/format");
|
|
13
|
+
const dateFnsTz = require("date-fns-tz");
|
|
12
14
|
const reactIntl = require("react-intl");
|
|
13
15
|
const styled = require("styled-components");
|
|
16
|
+
const dateFns = require("date-fns");
|
|
14
17
|
const formik = require("formik");
|
|
15
18
|
const yup = require("yup");
|
|
16
19
|
require("@reduxjs/toolkit/query");
|
|
@@ -37,10 +40,28 @@ function _interopNamespace(e) {
|
|
|
37
40
|
return Object.freeze(n);
|
|
38
41
|
}
|
|
39
42
|
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
|
43
|
+
const format__default = /* @__PURE__ */ _interopDefault(format);
|
|
40
44
|
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
|
41
45
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
|
42
46
|
const RELEASE_SCHEMA = yup__namespace.object().shape({
|
|
43
|
-
name: yup__namespace.string().trim().required()
|
|
47
|
+
name: yup__namespace.string().trim().required(),
|
|
48
|
+
scheduledAt: yup__namespace.string().nullable(),
|
|
49
|
+
isScheduled: yup__namespace.boolean().optional(),
|
|
50
|
+
time: yup__namespace.string().when("isScheduled", {
|
|
51
|
+
is: true,
|
|
52
|
+
then: yup__namespace.string().trim().required(),
|
|
53
|
+
otherwise: yup__namespace.string().nullable()
|
|
54
|
+
}),
|
|
55
|
+
timezone: yup__namespace.string().when("isScheduled", {
|
|
56
|
+
is: true,
|
|
57
|
+
then: yup__namespace.string().required().nullable(),
|
|
58
|
+
otherwise: yup__namespace.string().nullable()
|
|
59
|
+
}),
|
|
60
|
+
date: yup__namespace.string().when("isScheduled", {
|
|
61
|
+
is: true,
|
|
62
|
+
then: yup__namespace.string().required().nullable(),
|
|
63
|
+
otherwise: yup__namespace.string().nullable()
|
|
64
|
+
})
|
|
44
65
|
}).required().noUnknown();
|
|
45
66
|
const ReleaseModal = ({
|
|
46
67
|
handleClose,
|
|
@@ -51,6 +72,24 @@ const ReleaseModal = ({
|
|
|
51
72
|
const { formatMessage } = reactIntl.useIntl();
|
|
52
73
|
const { pathname } = reactRouterDom.useLocation();
|
|
53
74
|
const isCreatingRelease = pathname === `/plugins/${index.pluginId}`;
|
|
75
|
+
const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
|
|
76
|
+
const { timezoneList, systemTimezone = { value: "UTC+00:00-Africa/Abidjan " } } = getTimezones(
|
|
77
|
+
initialValues.scheduledAt ? new Date(initialValues.scheduledAt) : /* @__PURE__ */ new Date()
|
|
78
|
+
);
|
|
79
|
+
const getScheduledTimestamp = (values) => {
|
|
80
|
+
const { date, time, timezone } = values;
|
|
81
|
+
if (!date || !time || !timezone)
|
|
82
|
+
return null;
|
|
83
|
+
const formattedDate = dateFns.parse(time, "HH:mm", new Date(date));
|
|
84
|
+
const timezoneWithoutOffset = timezone.split("_")[1];
|
|
85
|
+
return dateFnsTz.zonedTimeToUtc(formattedDate, timezoneWithoutOffset);
|
|
86
|
+
};
|
|
87
|
+
const getTimezoneWithOffset = () => {
|
|
88
|
+
const currentTimezone = timezoneList.find(
|
|
89
|
+
(timezone) => timezone.value.split("_")[1] === initialValues.timezone
|
|
90
|
+
);
|
|
91
|
+
return currentTimezone?.value || systemTimezone.value;
|
|
92
|
+
};
|
|
54
93
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
|
|
55
94
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage(
|
|
56
95
|
{
|
|
@@ -62,45 +101,134 @@ const ReleaseModal = ({
|
|
|
62
101
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
63
102
|
formik.Formik,
|
|
64
103
|
{
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
104
|
+
onSubmit: (values) => {
|
|
105
|
+
handleSubmit({
|
|
106
|
+
...values,
|
|
107
|
+
timezone: values.timezone ? values.timezone.split("_")[1] : null,
|
|
108
|
+
scheduledAt: values.isScheduled ? getScheduledTimestamp(values) : null
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
initialValues: {
|
|
112
|
+
...initialValues,
|
|
113
|
+
timezone: initialValues.timezone ? getTimezoneWithOffset() : systemTimezone.value
|
|
114
|
+
},
|
|
68
115
|
validationSchema: RELEASE_SCHEMA,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
116
|
+
validateOnChange: false,
|
|
117
|
+
children: ({ values, errors, handleChange, setFieldValue }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
|
|
118
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
|
|
119
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
120
|
+
designSystem.TextInput,
|
|
121
|
+
{
|
|
122
|
+
label: formatMessage({
|
|
123
|
+
id: "content-releases.modal.form.input.label.release-name",
|
|
124
|
+
defaultMessage: "Name"
|
|
125
|
+
}),
|
|
126
|
+
name: "name",
|
|
127
|
+
value: values.name,
|
|
128
|
+
error: errors.name,
|
|
129
|
+
onChange: handleChange,
|
|
130
|
+
required: true
|
|
131
|
+
}
|
|
132
|
+
),
|
|
133
|
+
IsSchedulingEnabled && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
134
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { width: "max-content", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
135
|
+
designSystem.Checkbox,
|
|
136
|
+
{
|
|
137
|
+
name: "isScheduled",
|
|
138
|
+
value: values.isScheduled,
|
|
139
|
+
onChange: (event) => {
|
|
140
|
+
setFieldValue("isScheduled", event.target.checked);
|
|
141
|
+
if (!event.target.checked) {
|
|
142
|
+
setFieldValue("date", null);
|
|
143
|
+
setFieldValue("time", "");
|
|
144
|
+
setFieldValue("timezone", null);
|
|
145
|
+
} else {
|
|
146
|
+
setFieldValue("date", initialValues.date);
|
|
147
|
+
setFieldValue("time", initialValues.time);
|
|
148
|
+
setFieldValue(
|
|
149
|
+
"timezone",
|
|
150
|
+
initialValues.timezone ?? systemTimezone?.value
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
155
|
+
designSystem.Typography,
|
|
156
|
+
{
|
|
157
|
+
textColor: values.isScheduled ? "primary600" : "neutral800",
|
|
158
|
+
fontWeight: values.isScheduled ? "semiBold" : "regular",
|
|
159
|
+
children: formatMessage({
|
|
160
|
+
id: "modal.form.input.label.schedule-release",
|
|
161
|
+
defaultMessage: "Schedule release"
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
) }),
|
|
167
|
+
values.isScheduled && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
168
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, alignItems: "start", children: [
|
|
169
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
170
|
+
designSystem.DatePicker,
|
|
171
|
+
{
|
|
172
|
+
label: formatMessage({
|
|
173
|
+
id: "content-releases.modal.form.input.label.date",
|
|
174
|
+
defaultMessage: "Date"
|
|
175
|
+
}),
|
|
176
|
+
name: "date",
|
|
177
|
+
error: errors.date,
|
|
178
|
+
onChange: (date) => {
|
|
179
|
+
const isoFormatDate = date ? dateFns.formatISO(date, { representation: "date" }) : null;
|
|
180
|
+
setFieldValue("date", isoFormatDate);
|
|
181
|
+
},
|
|
182
|
+
clearLabel: formatMessage({
|
|
183
|
+
id: "content-releases.modal.form.input.clearLabel",
|
|
184
|
+
defaultMessage: "Clear"
|
|
185
|
+
}),
|
|
186
|
+
onClear: () => {
|
|
187
|
+
setFieldValue("date", null);
|
|
188
|
+
},
|
|
189
|
+
selectedDate: values.date || void 0,
|
|
190
|
+
required: true
|
|
191
|
+
}
|
|
192
|
+
) }),
|
|
193
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
194
|
+
designSystem.TimePicker,
|
|
195
|
+
{
|
|
196
|
+
label: formatMessage({
|
|
197
|
+
id: "content-releases.modal.form.input.label.time",
|
|
198
|
+
defaultMessage: "Time"
|
|
199
|
+
}),
|
|
200
|
+
name: "time",
|
|
201
|
+
error: errors.time,
|
|
202
|
+
onChange: (time) => {
|
|
203
|
+
setFieldValue("time", time);
|
|
204
|
+
},
|
|
205
|
+
clearLabel: formatMessage({
|
|
206
|
+
id: "content-releases.modal.form.input.clearLabel",
|
|
207
|
+
defaultMessage: "Clear"
|
|
208
|
+
}),
|
|
209
|
+
onClear: () => {
|
|
210
|
+
setFieldValue("time", "");
|
|
211
|
+
},
|
|
212
|
+
value: values.time || void 0,
|
|
213
|
+
required: true
|
|
214
|
+
}
|
|
215
|
+
) })
|
|
216
|
+
] }),
|
|
217
|
+
/* @__PURE__ */ jsxRuntime.jsx(TimezoneComponent, { timezoneOptions: timezoneList })
|
|
218
|
+
] })
|
|
219
|
+
] })
|
|
220
|
+
] }) }),
|
|
84
221
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
85
222
|
designSystem.ModalFooter,
|
|
86
223
|
{
|
|
87
224
|
startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }),
|
|
88
|
-
endActions: /* @__PURE__ */ jsxRuntime.jsx(
|
|
89
|
-
designSystem.Button,
|
|
225
|
+
endActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { name: "submit", loading: isLoading, type: "submit", children: formatMessage(
|
|
90
226
|
{
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
{
|
|
97
|
-
id: "content-releases.modal.form.button.submit",
|
|
98
|
-
defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
|
|
99
|
-
},
|
|
100
|
-
{ isCreatingRelease }
|
|
101
|
-
)
|
|
102
|
-
}
|
|
103
|
-
)
|
|
227
|
+
id: "content-releases.modal.form.button.submit",
|
|
228
|
+
defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
|
|
229
|
+
},
|
|
230
|
+
{ isCreatingRelease }
|
|
231
|
+
) })
|
|
104
232
|
}
|
|
105
233
|
)
|
|
106
234
|
] })
|
|
@@ -108,16 +236,59 @@ const ReleaseModal = ({
|
|
|
108
236
|
)
|
|
109
237
|
] });
|
|
110
238
|
};
|
|
239
|
+
const getTimezones = (selectedDate) => {
|
|
240
|
+
const timezoneList = Intl.supportedValuesOf("timeZone").map((timezone) => {
|
|
241
|
+
const utcOffset = index.getTimezoneOffset(timezone, selectedDate);
|
|
242
|
+
return { offset: utcOffset, value: `${utcOffset}_${timezone}` };
|
|
243
|
+
});
|
|
244
|
+
const systemTimezone = timezoneList.find(
|
|
245
|
+
(timezone) => timezone.value.split("_")[1] === Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
246
|
+
);
|
|
247
|
+
return { timezoneList, systemTimezone };
|
|
248
|
+
};
|
|
249
|
+
const TimezoneComponent = ({ timezoneOptions }) => {
|
|
250
|
+
const { values, errors, setFieldValue } = formik.useFormikContext();
|
|
251
|
+
const { formatMessage } = reactIntl.useIntl();
|
|
252
|
+
const [timezoneList, setTimezoneList] = React__namespace.useState(timezoneOptions);
|
|
253
|
+
React__namespace.useEffect(() => {
|
|
254
|
+
if (values.date) {
|
|
255
|
+
const { timezoneList: timezoneList2 } = getTimezones(new Date(values.date));
|
|
256
|
+
setTimezoneList(timezoneList2);
|
|
257
|
+
const updatedTimezone = values.timezone && timezoneList2.find((tz) => tz.value.split("_")[1] === values.timezone.split("_")[1]);
|
|
258
|
+
if (updatedTimezone) {
|
|
259
|
+
setFieldValue("timezone", updatedTimezone.value);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}, [setFieldValue, values.date, values.timezone]);
|
|
263
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
264
|
+
designSystem.Combobox,
|
|
265
|
+
{
|
|
266
|
+
label: formatMessage({
|
|
267
|
+
id: "content-releases.modal.form.input.label.timezone",
|
|
268
|
+
defaultMessage: "Timezone"
|
|
269
|
+
}),
|
|
270
|
+
name: "timezone",
|
|
271
|
+
value: values.timezone || void 0,
|
|
272
|
+
textValue: values.timezone ? values.timezone.replace("_", " ") : void 0,
|
|
273
|
+
onChange: (timezone) => {
|
|
274
|
+
setFieldValue("timezone", timezone);
|
|
275
|
+
},
|
|
276
|
+
onClear: () => {
|
|
277
|
+
setFieldValue("timezone", "");
|
|
278
|
+
},
|
|
279
|
+
error: errors.timezone,
|
|
280
|
+
required: true,
|
|
281
|
+
children: timezoneList.map((timezone) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: timezone.value, children: timezone.value.replace("_", " ") }, timezone.value))
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
};
|
|
111
285
|
const ReleaseInfoWrapper = styled__default.default(designSystem.Flex)`
|
|
112
286
|
align-self: stretch;
|
|
113
287
|
border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
|
|
114
288
|
border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
|
|
115
289
|
border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
|
|
116
290
|
`;
|
|
117
|
-
const
|
|
118
|
-
align-self: stretch;
|
|
119
|
-
cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
|
|
120
|
-
|
|
291
|
+
const StyledMenuItem = styled__default.default(v2.Menu.Item)`
|
|
121
292
|
svg path {
|
|
122
293
|
fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
|
|
123
294
|
}
|
|
@@ -126,15 +297,15 @@ const StyledFlex = styled__default.default(designSystem.Flex)`
|
|
|
126
297
|
}
|
|
127
298
|
`;
|
|
128
299
|
const PencilIcon = styled__default.default(icons.Pencil)`
|
|
129
|
-
width: ${({ theme }) => theme.spaces[
|
|
130
|
-
height: ${({ theme }) => theme.spaces[
|
|
300
|
+
width: ${({ theme }) => theme.spaces[3]};
|
|
301
|
+
height: ${({ theme }) => theme.spaces[3]};
|
|
131
302
|
path {
|
|
132
303
|
fill: ${({ theme }) => theme.colors.neutral600};
|
|
133
304
|
}
|
|
134
305
|
`;
|
|
135
306
|
const TrashIcon = styled__default.default(icons.Trash)`
|
|
136
|
-
width: ${({ theme }) => theme.spaces[
|
|
137
|
-
height: ${({ theme }) => theme.spaces[
|
|
307
|
+
width: ${({ theme }) => theme.spaces[3]};
|
|
308
|
+
height: ${({ theme }) => theme.spaces[3]};
|
|
138
309
|
path {
|
|
139
310
|
fill: ${({ theme }) => theme.colors.danger600};
|
|
140
311
|
}
|
|
@@ -142,24 +313,6 @@ const TrashIcon = styled__default.default(icons.Trash)`
|
|
|
142
313
|
const TypographyMaxWidth = styled__default.default(designSystem.Typography)`
|
|
143
314
|
max-width: 300px;
|
|
144
315
|
`;
|
|
145
|
-
const PopoverButton = ({ onClick, disabled, children }) => {
|
|
146
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
147
|
-
StyledFlex,
|
|
148
|
-
{
|
|
149
|
-
paddingTop: 2,
|
|
150
|
-
paddingBottom: 2,
|
|
151
|
-
paddingLeft: 4,
|
|
152
|
-
paddingRight: 4,
|
|
153
|
-
alignItems: "center",
|
|
154
|
-
gap: 2,
|
|
155
|
-
as: "button",
|
|
156
|
-
hasRadius: true,
|
|
157
|
-
onClick,
|
|
158
|
-
disabled,
|
|
159
|
-
children
|
|
160
|
-
}
|
|
161
|
-
);
|
|
162
|
-
};
|
|
163
316
|
const EntryValidationText = ({ action, schema, components, entry }) => {
|
|
164
317
|
const { formatMessage } = reactIntl.useIntl();
|
|
165
318
|
const { validate } = strapiAdmin.unstable_useDocument();
|
|
@@ -208,10 +361,8 @@ const ReleaseDetailsLayout = ({
|
|
|
208
361
|
toggleWarningSubmit,
|
|
209
362
|
children
|
|
210
363
|
}) => {
|
|
211
|
-
const { formatMessage } = reactIntl.useIntl();
|
|
364
|
+
const { formatMessage, formatDate, formatTime } = reactIntl.useIntl();
|
|
212
365
|
const { releaseId } = reactRouterDom.useParams();
|
|
213
|
-
const [isPopoverVisible, setIsPopoverVisible] = React__namespace.useState(false);
|
|
214
|
-
const moreButtonRef = React__namespace.useRef(null);
|
|
215
366
|
const {
|
|
216
367
|
data,
|
|
217
368
|
isLoading: isLoadingDetails,
|
|
@@ -225,14 +376,8 @@ const ReleaseDetailsLayout = ({
|
|
|
225
376
|
allowedActions: { canUpdate, canDelete }
|
|
226
377
|
} = helperPlugin.useRBAC(index.PERMISSIONS);
|
|
227
378
|
const dispatch = index.useTypedDispatch();
|
|
379
|
+
const { trackUsage } = helperPlugin.useTracking();
|
|
228
380
|
const release = data?.data;
|
|
229
|
-
const handleTogglePopover = () => {
|
|
230
|
-
setIsPopoverVisible((prev) => !prev);
|
|
231
|
-
};
|
|
232
|
-
const openReleaseModal = () => {
|
|
233
|
-
toggleEditReleaseModal();
|
|
234
|
-
handleTogglePopover();
|
|
235
|
-
};
|
|
236
381
|
const handlePublishRelease = async () => {
|
|
237
382
|
const response = await publishRelease({ id: releaseId });
|
|
238
383
|
if ("data" in response) {
|
|
@@ -243,6 +388,12 @@ const ReleaseDetailsLayout = ({
|
|
|
243
388
|
defaultMessage: "Release was published successfully."
|
|
244
389
|
})
|
|
245
390
|
});
|
|
391
|
+
const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
|
|
392
|
+
trackUsage("didPublishRelease", {
|
|
393
|
+
totalEntries: totalEntries2,
|
|
394
|
+
totalPublishedEntries,
|
|
395
|
+
totalUnpublishedEntries
|
|
396
|
+
});
|
|
246
397
|
} else if (index.isAxiosError(response.error)) {
|
|
247
398
|
toggleNotification({
|
|
248
399
|
type: "warning",
|
|
@@ -255,13 +406,21 @@ const ReleaseDetailsLayout = ({
|
|
|
255
406
|
});
|
|
256
407
|
}
|
|
257
408
|
};
|
|
258
|
-
const openWarningConfirmDialog = () => {
|
|
259
|
-
toggleWarningSubmit();
|
|
260
|
-
handleTogglePopover();
|
|
261
|
-
};
|
|
262
409
|
const handleRefresh = () => {
|
|
263
410
|
dispatch(index.releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
|
|
264
411
|
};
|
|
412
|
+
const getCreatedByUser = () => {
|
|
413
|
+
if (!release?.createdBy) {
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
if (release.createdBy.username) {
|
|
417
|
+
return release.createdBy.username;
|
|
418
|
+
}
|
|
419
|
+
if (release.createdBy.firstname) {
|
|
420
|
+
return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
|
|
421
|
+
}
|
|
422
|
+
return release.createdBy.email;
|
|
423
|
+
};
|
|
265
424
|
if (isLoadingDetails) {
|
|
266
425
|
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
|
|
267
426
|
}
|
|
@@ -283,90 +442,139 @@ const ReleaseDetailsLayout = ({
|
|
|
283
442
|
);
|
|
284
443
|
}
|
|
285
444
|
const totalEntries = release.actions.meta.count || 0;
|
|
286
|
-
const
|
|
445
|
+
const hasCreatedByUser = Boolean(getCreatedByUser());
|
|
446
|
+
const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
|
|
447
|
+
const isScheduled = release.scheduledAt && release.timezone;
|
|
448
|
+
const numberOfEntriesText = formatMessage(
|
|
449
|
+
{
|
|
450
|
+
id: "content-releases.pages.Details.header-subtitle",
|
|
451
|
+
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
452
|
+
},
|
|
453
|
+
{ number: totalEntries }
|
|
454
|
+
);
|
|
455
|
+
const scheduledText = isScheduled ? formatMessage(
|
|
456
|
+
{
|
|
457
|
+
id: "content-releases.pages.ReleaseDetails.header-subtitle.scheduled",
|
|
458
|
+
defaultMessage: "Scheduled for {date} at {time} ({offset})"
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
date: formatDate(new Date(release.scheduledAt), {
|
|
462
|
+
weekday: "long",
|
|
463
|
+
day: "numeric",
|
|
464
|
+
month: "long",
|
|
465
|
+
year: "numeric",
|
|
466
|
+
timeZone: release.timezone
|
|
467
|
+
}),
|
|
468
|
+
time: formatTime(new Date(release.scheduledAt), {
|
|
469
|
+
timeZone: release.timezone,
|
|
470
|
+
hourCycle: "h23"
|
|
471
|
+
}),
|
|
472
|
+
offset: index.getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
|
|
473
|
+
}
|
|
474
|
+
) : "";
|
|
287
475
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoadingDetails, children: [
|
|
288
476
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
289
477
|
designSystem.HeaderLayout,
|
|
290
478
|
{
|
|
291
479
|
title: release.name,
|
|
292
|
-
subtitle:
|
|
293
|
-
{
|
|
294
|
-
id: "content-releases.pages.Details.header-subtitle",
|
|
295
|
-
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
296
|
-
},
|
|
297
|
-
{ number: totalEntries }
|
|
298
|
-
),
|
|
480
|
+
subtitle: numberOfEntriesText + (IsSchedulingEnabled && isScheduled ? ` - ${scheduledText}` : ""),
|
|
299
481
|
navigationAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
|
|
300
482
|
id: "global.back",
|
|
301
483
|
defaultMessage: "Back"
|
|
302
484
|
}) }),
|
|
303
485
|
primaryAction: !release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
|
304
|
-
/* @__PURE__ */ jsxRuntime.
|
|
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
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
486
|
+
/* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Root, { children: [
|
|
487
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
488
|
+
v2.Menu.Trigger,
|
|
489
|
+
{
|
|
490
|
+
as: designSystem.IconButton,
|
|
491
|
+
paddingLeft: 2,
|
|
492
|
+
paddingRight: 2,
|
|
493
|
+
"aria-label": formatMessage({
|
|
494
|
+
id: "content-releases.header.actions.open-release-actions",
|
|
495
|
+
defaultMessage: "Release edit and delete menu"
|
|
496
|
+
}),
|
|
497
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {}),
|
|
498
|
+
variant: "tertiary"
|
|
499
|
+
}
|
|
500
|
+
),
|
|
501
|
+
/* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: [
|
|
502
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
503
|
+
designSystem.Flex,
|
|
504
|
+
{
|
|
505
|
+
alignItems: "center",
|
|
506
|
+
justifyContent: "center",
|
|
507
|
+
direction: "column",
|
|
508
|
+
padding: 1,
|
|
509
|
+
width: "100%",
|
|
510
|
+
children: [
|
|
511
|
+
/* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
512
|
+
designSystem.Flex,
|
|
513
|
+
{
|
|
514
|
+
paddingTop: 2,
|
|
515
|
+
paddingBottom: 2,
|
|
516
|
+
alignItems: "center",
|
|
517
|
+
gap: 2,
|
|
518
|
+
hasRadius: true,
|
|
519
|
+
width: "100%",
|
|
520
|
+
children: [
|
|
521
|
+
/* @__PURE__ */ jsxRuntime.jsx(PencilIcon, {}),
|
|
522
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: formatMessage({
|
|
523
|
+
id: "content-releases.header.actions.edit",
|
|
524
|
+
defaultMessage: "Edit"
|
|
525
|
+
}) })
|
|
526
|
+
]
|
|
527
|
+
}
|
|
528
|
+
) }),
|
|
529
|
+
/* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canDelete, onSelect: toggleWarningSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
530
|
+
designSystem.Flex,
|
|
531
|
+
{
|
|
532
|
+
paddingTop: 2,
|
|
533
|
+
paddingBottom: 2,
|
|
534
|
+
alignItems: "center",
|
|
535
|
+
gap: 2,
|
|
536
|
+
hasRadius: true,
|
|
537
|
+
width: "100%",
|
|
538
|
+
children: [
|
|
539
|
+
/* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {}),
|
|
540
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
|
|
541
|
+
id: "content-releases.header.actions.delete",
|
|
542
|
+
defaultMessage: "Delete"
|
|
543
|
+
}) })
|
|
544
|
+
]
|
|
545
|
+
}
|
|
546
|
+
) })
|
|
547
|
+
]
|
|
548
|
+
}
|
|
549
|
+
),
|
|
550
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
551
|
+
ReleaseInfoWrapper,
|
|
552
|
+
{
|
|
553
|
+
direction: "column",
|
|
554
|
+
justifyContent: "center",
|
|
555
|
+
alignItems: "flex-start",
|
|
556
|
+
gap: 1,
|
|
557
|
+
padding: 5,
|
|
558
|
+
children: [
|
|
559
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
|
|
560
|
+
id: "content-releases.header.actions.created",
|
|
561
|
+
defaultMessage: "Created"
|
|
562
|
+
}) }),
|
|
563
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", color: "neutral300", children: [
|
|
564
|
+
/* @__PURE__ */ jsxRuntime.jsx(helperPlugin.RelativeTime, { timestamp: new Date(release.createdAt) }),
|
|
565
|
+
formatMessage(
|
|
566
|
+
{
|
|
567
|
+
id: "content-releases.header.actions.created.description",
|
|
568
|
+
defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
|
|
569
|
+
},
|
|
570
|
+
{ createdBy: getCreatedByUser(), hasCreatedByUser }
|
|
571
|
+
)
|
|
572
|
+
] })
|
|
573
|
+
]
|
|
574
|
+
}
|
|
575
|
+
)
|
|
576
|
+
] })
|
|
577
|
+
] }),
|
|
370
578
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
|
|
371
579
|
id: "content-releases.header.actions.refresh",
|
|
372
580
|
defaultMessage: "Refresh"
|
|
@@ -422,6 +630,9 @@ const ReleaseDetailsBody = () => {
|
|
|
422
630
|
isError: isReleaseError,
|
|
423
631
|
error: releaseError
|
|
424
632
|
} = index.useGetReleaseQuery({ id: releaseId });
|
|
633
|
+
const {
|
|
634
|
+
allowedActions: { canUpdate }
|
|
635
|
+
} = helperPlugin.useRBAC(index.PERMISSIONS);
|
|
425
636
|
const release = releaseData?.data;
|
|
426
637
|
const selectedGroupBy = query?.groupBy || "contentType";
|
|
427
638
|
const {
|
|
@@ -435,7 +646,7 @@ const ReleaseDetailsBody = () => {
|
|
|
435
646
|
releaseId
|
|
436
647
|
});
|
|
437
648
|
const [updateReleaseAction] = index.useUpdateReleaseActionMutation();
|
|
438
|
-
const handleChangeType = async (e, actionId) => {
|
|
649
|
+
const handleChangeType = async (e, actionId, actionPath) => {
|
|
439
650
|
const response = await updateReleaseAction({
|
|
440
651
|
params: {
|
|
441
652
|
releaseId,
|
|
@@ -443,7 +654,11 @@ const ReleaseDetailsBody = () => {
|
|
|
443
654
|
},
|
|
444
655
|
body: {
|
|
445
656
|
type: e.target.value
|
|
446
|
-
}
|
|
657
|
+
},
|
|
658
|
+
query,
|
|
659
|
+
// We are passing the query params to make optimistic updates
|
|
660
|
+
actionPath
|
|
661
|
+
// We are passing the action path to found the position in the cache of the action for optimistic updates
|
|
447
662
|
});
|
|
448
663
|
if ("error" in response) {
|
|
449
664
|
if (index.isAxiosError(response.error)) {
|
|
@@ -524,7 +739,7 @@ const ReleaseDetailsBody = () => {
|
|
|
524
739
|
designSystem.SingleSelect,
|
|
525
740
|
{
|
|
526
741
|
"aria-label": formatMessage({
|
|
527
|
-
id: "content-releases.pages.ReleaseDetails.groupBy.label",
|
|
742
|
+
id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
|
|
528
743
|
defaultMessage: "Group by"
|
|
529
744
|
}),
|
|
530
745
|
customizeContent: (value) => formatMessage(
|
|
@@ -542,7 +757,7 @@ const ReleaseDetailsBody = () => {
|
|
|
542
757
|
}
|
|
543
758
|
) }),
|
|
544
759
|
Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
|
|
545
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: key }) }),
|
|
760
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { role: "separator", "aria-label": key, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: key }) }),
|
|
546
761
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
547
762
|
helperPlugin.Table.Root,
|
|
548
763
|
{
|
|
@@ -612,56 +827,59 @@ const ReleaseDetailsBody = () => {
|
|
|
612
827
|
)
|
|
613
828
|
] }),
|
|
614
829
|
/* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.LoadingBody, {}),
|
|
615
|
-
/* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.Body, { children: releaseActions[key].map(
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
{
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
isPublish: type === "publish",
|
|
626
|
-
b: (children) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children })
|
|
627
|
-
}
|
|
628
|
-
) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
629
|
-
index.ReleaseActionOptions,
|
|
630
|
-
{
|
|
631
|
-
selected: type,
|
|
632
|
-
handleChange: (e) => handleChangeType(e, id),
|
|
633
|
-
name: `release-action-${id}-type`
|
|
634
|
-
}
|
|
635
|
-
) }),
|
|
636
|
-
!release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
637
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", minWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
638
|
-
EntryValidationText,
|
|
830
|
+
/* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.Body, { children: releaseActions[key].map(
|
|
831
|
+
({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
832
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
|
|
833
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
|
|
834
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: contentType.displayName || "" }) }),
|
|
835
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage(
|
|
836
|
+
{
|
|
837
|
+
id: "content-releases.page.ReleaseDetails.table.action-published",
|
|
838
|
+
defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
|
|
839
|
+
},
|
|
639
840
|
{
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
841
|
+
isPublish: type === "publish",
|
|
842
|
+
b: (children) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children })
|
|
843
|
+
}
|
|
844
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
845
|
+
index.ReleaseActionOptions,
|
|
846
|
+
{
|
|
847
|
+
selected: type,
|
|
848
|
+
handleChange: (e) => handleChangeType(e, id, [key, actionIndex]),
|
|
849
|
+
name: `release-action-${id}-type`,
|
|
850
|
+
disabled: !canUpdate
|
|
644
851
|
}
|
|
645
852
|
) }),
|
|
646
|
-
|
|
647
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
648
|
-
|
|
649
|
-
{
|
|
650
|
-
contentTypeUid: contentType.uid,
|
|
651
|
-
entryId: entry.id,
|
|
652
|
-
locale: locale?.code
|
|
653
|
-
}
|
|
654
|
-
),
|
|
655
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
656
|
-
index.ReleaseActionMenu.DeleteReleaseActionItem,
|
|
853
|
+
!release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
854
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", minWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
855
|
+
EntryValidationText,
|
|
657
856
|
{
|
|
658
|
-
|
|
659
|
-
|
|
857
|
+
action: type,
|
|
858
|
+
schema: contentTypes?.[contentType.uid],
|
|
859
|
+
components,
|
|
860
|
+
entry
|
|
660
861
|
}
|
|
661
|
-
)
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
862
|
+
) }),
|
|
863
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxRuntime.jsxs(index.ReleaseActionMenu.Root, { children: [
|
|
864
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
865
|
+
index.ReleaseActionMenu.ReleaseActionEntryLinkItem,
|
|
866
|
+
{
|
|
867
|
+
contentTypeUid: contentType.uid,
|
|
868
|
+
entryId: entry.id,
|
|
869
|
+
locale: locale?.code
|
|
870
|
+
}
|
|
871
|
+
),
|
|
872
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
873
|
+
index.ReleaseActionMenu.DeleteReleaseActionItem,
|
|
874
|
+
{
|
|
875
|
+
releaseId: release.id,
|
|
876
|
+
actionId: id
|
|
877
|
+
}
|
|
878
|
+
)
|
|
879
|
+
] }) }) })
|
|
880
|
+
] })
|
|
881
|
+
] }, id)
|
|
882
|
+
) })
|
|
665
883
|
] })
|
|
666
884
|
}
|
|
667
885
|
)
|
|
@@ -708,11 +926,18 @@ const ReleaseDetailsPage = () => {
|
|
|
708
926
|
}
|
|
709
927
|
);
|
|
710
928
|
}
|
|
711
|
-
const
|
|
929
|
+
const releaseData = isSuccessDetails && data?.data || null;
|
|
930
|
+
const title = releaseData?.name || "";
|
|
931
|
+
const timezone = releaseData?.timezone ?? null;
|
|
932
|
+
const scheduledAt = releaseData?.scheduledAt && timezone ? dateFnsTz.utcToZonedTime(releaseData.scheduledAt, timezone) : null;
|
|
933
|
+
const date = scheduledAt ? new Date(format__default.default(scheduledAt, "yyyy-MM-dd")) : null;
|
|
934
|
+
const time = scheduledAt ? format__default.default(scheduledAt, "HH:mm") : "";
|
|
712
935
|
const handleEditRelease = async (values) => {
|
|
713
936
|
const response = await updateRelease({
|
|
714
937
|
id: releaseId,
|
|
715
|
-
name: values.name
|
|
938
|
+
name: values.name,
|
|
939
|
+
scheduledAt: values.scheduledAt,
|
|
940
|
+
timezone: values.timezone
|
|
716
941
|
});
|
|
717
942
|
if ("data" in response) {
|
|
718
943
|
toggleNotification({
|
|
@@ -766,7 +991,14 @@ const ReleaseDetailsPage = () => {
|
|
|
766
991
|
handleClose: toggleEditReleaseModal,
|
|
767
992
|
handleSubmit: handleEditRelease,
|
|
768
993
|
isLoading: isLoadingDetails || isSubmittingForm,
|
|
769
|
-
initialValues: {
|
|
994
|
+
initialValues: {
|
|
995
|
+
name: title || "",
|
|
996
|
+
scheduledAt,
|
|
997
|
+
date,
|
|
998
|
+
time,
|
|
999
|
+
isScheduled: Boolean(scheduledAt),
|
|
1000
|
+
timezone
|
|
1001
|
+
}
|
|
770
1002
|
}
|
|
771
1003
|
),
|
|
772
1004
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -786,42 +1018,12 @@ const ReleaseDetailsPage = () => {
|
|
|
786
1018
|
}
|
|
787
1019
|
);
|
|
788
1020
|
};
|
|
789
|
-
const ReleasesLayout = ({
|
|
790
|
-
isLoading,
|
|
791
|
-
totalReleases,
|
|
792
|
-
onClickAddRelease,
|
|
793
|
-
children
|
|
794
|
-
}) => {
|
|
795
|
-
const { formatMessage } = reactIntl.useIntl();
|
|
796
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
|
|
797
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
798
|
-
designSystem.HeaderLayout,
|
|
799
|
-
{
|
|
800
|
-
title: formatMessage({
|
|
801
|
-
id: "content-releases.pages.Releases.title",
|
|
802
|
-
defaultMessage: "Releases"
|
|
803
|
-
}),
|
|
804
|
-
subtitle: !isLoading && formatMessage(
|
|
805
|
-
{
|
|
806
|
-
id: "content-releases.pages.Releases.header-subtitle",
|
|
807
|
-
defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
|
|
808
|
-
},
|
|
809
|
-
{ number: totalReleases }
|
|
810
|
-
),
|
|
811
|
-
primaryAction: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.create, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}), onClick: onClickAddRelease, children: formatMessage({
|
|
812
|
-
id: "content-releases.header.actions.add-release",
|
|
813
|
-
defaultMessage: "New release"
|
|
814
|
-
}) }) })
|
|
815
|
-
}
|
|
816
|
-
),
|
|
817
|
-
children
|
|
818
|
-
] });
|
|
819
|
-
};
|
|
820
1021
|
const LinkCard = styled__default.default(v2.Link)`
|
|
821
1022
|
display: block;
|
|
822
1023
|
`;
|
|
823
1024
|
const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
824
1025
|
const { formatMessage } = reactIntl.useIntl();
|
|
1026
|
+
const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
|
|
825
1027
|
if (isError) {
|
|
826
1028
|
return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
|
|
827
1029
|
}
|
|
@@ -842,7 +1044,7 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
842
1044
|
}
|
|
843
1045
|
);
|
|
844
1046
|
}
|
|
845
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid, { gap: 4, children: releases.map(({ id, name, actions }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.GridItem, { col: 3, s: 6, xs: 12, children: /* @__PURE__ */ jsxRuntime.jsx(LinkCard, { href: `content-releases/${id}`, isExternal: false, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1047
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid, { gap: 4, children: releases.map(({ id, name, actions, scheduledAt }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.GridItem, { col: 3, s: 6, xs: 12, children: /* @__PURE__ */ jsxRuntime.jsx(LinkCard, { href: `content-releases/${id}`, isExternal: false, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
846
1048
|
designSystem.Flex,
|
|
847
1049
|
{
|
|
848
1050
|
direction: "column",
|
|
@@ -857,7 +1059,10 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
857
1059
|
gap: 2,
|
|
858
1060
|
children: [
|
|
859
1061
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
|
|
860
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", children: formatMessage(
|
|
1062
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: IsSchedulingEnabled ? scheduledAt ? /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
|
|
1063
|
+
id: "content-releases.pages.Releases.not-scheduled",
|
|
1064
|
+
defaultMessage: "Not scheduled"
|
|
1065
|
+
}) : formatMessage(
|
|
861
1066
|
{
|
|
862
1067
|
id: "content-releases.page.Releases.release-item.entries",
|
|
863
1068
|
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
@@ -868,8 +1073,22 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
868
1073
|
}
|
|
869
1074
|
) }) }, id)) });
|
|
870
1075
|
};
|
|
1076
|
+
const StyledAlert = styled__default.default(designSystem.Alert)`
|
|
1077
|
+
button {
|
|
1078
|
+
display: none;
|
|
1079
|
+
}
|
|
1080
|
+
p + div {
|
|
1081
|
+
margin-left: auto;
|
|
1082
|
+
}
|
|
1083
|
+
`;
|
|
871
1084
|
const INITIAL_FORM_VALUES = {
|
|
872
|
-
name: ""
|
|
1085
|
+
name: "",
|
|
1086
|
+
date: null,
|
|
1087
|
+
time: "",
|
|
1088
|
+
// Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
|
|
1089
|
+
isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
|
|
1090
|
+
scheduledAt: null,
|
|
1091
|
+
timezone: null
|
|
873
1092
|
};
|
|
874
1093
|
const ReleasesPage = () => {
|
|
875
1094
|
const tabRef = React__namespace.useRef(null);
|
|
@@ -882,6 +1101,9 @@ const ReleasesPage = () => {
|
|
|
882
1101
|
const [{ query }, setQuery] = helperPlugin.useQueryParams();
|
|
883
1102
|
const response = index.useGetReleasesQuery(query);
|
|
884
1103
|
const [createRelease, { isLoading: isSubmittingForm }] = index.useCreateReleaseMutation();
|
|
1104
|
+
const { getFeature } = strapiAdmin.useLicenseLimits();
|
|
1105
|
+
const { maximumReleases = 3 } = getFeature("cms-content-releases");
|
|
1106
|
+
const { trackUsage } = helperPlugin.useTracking();
|
|
885
1107
|
const { isLoading, isSuccess, isError } = response;
|
|
886
1108
|
const activeTab = response?.currentData?.meta?.activeTab || "pending";
|
|
887
1109
|
const activeTabIndex = ["pending", "done"].indexOf(activeTab);
|
|
@@ -910,9 +1132,10 @@ const ReleasesPage = () => {
|
|
|
910
1132
|
setReleaseModalShown((prev) => !prev);
|
|
911
1133
|
};
|
|
912
1134
|
if (isLoading) {
|
|
913
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1135
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
|
|
914
1136
|
}
|
|
915
1137
|
const totalReleases = isSuccess && response.currentData?.meta?.pagination?.total || 0;
|
|
1138
|
+
const hasReachedMaximumPendingReleases = totalReleases >= maximumReleases;
|
|
916
1139
|
const handleTabChange = (index2) => {
|
|
917
1140
|
setQuery({
|
|
918
1141
|
...query,
|
|
@@ -925,9 +1148,11 @@ const ReleasesPage = () => {
|
|
|
925
1148
|
}
|
|
926
1149
|
});
|
|
927
1150
|
};
|
|
928
|
-
const handleAddRelease = async (
|
|
1151
|
+
const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
|
|
929
1152
|
const response2 = await createRelease({
|
|
930
|
-
name
|
|
1153
|
+
name,
|
|
1154
|
+
scheduledAt,
|
|
1155
|
+
timezone
|
|
931
1156
|
});
|
|
932
1157
|
if ("data" in response2) {
|
|
933
1158
|
toggleNotification({
|
|
@@ -937,6 +1162,7 @@ const ReleasesPage = () => {
|
|
|
937
1162
|
defaultMessage: "Release created."
|
|
938
1163
|
})
|
|
939
1164
|
});
|
|
1165
|
+
trackUsage("didCreateRelease");
|
|
940
1166
|
push(`/plugins/content-releases/${response2.data.data.id}`);
|
|
941
1167
|
} else if (index.isAxiosError(response2.error)) {
|
|
942
1168
|
toggleNotification({
|
|
@@ -950,8 +1176,60 @@ const ReleasesPage = () => {
|
|
|
950
1176
|
});
|
|
951
1177
|
}
|
|
952
1178
|
};
|
|
953
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1179
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
|
|
1180
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1181
|
+
designSystem.HeaderLayout,
|
|
1182
|
+
{
|
|
1183
|
+
title: formatMessage({
|
|
1184
|
+
id: "content-releases.pages.Releases.title",
|
|
1185
|
+
defaultMessage: "Releases"
|
|
1186
|
+
}),
|
|
1187
|
+
subtitle: formatMessage(
|
|
1188
|
+
{
|
|
1189
|
+
id: "content-releases.pages.Releases.header-subtitle",
|
|
1190
|
+
defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
|
|
1191
|
+
},
|
|
1192
|
+
{ number: totalReleases }
|
|
1193
|
+
),
|
|
1194
|
+
primaryAction: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.create, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1195
|
+
designSystem.Button,
|
|
1196
|
+
{
|
|
1197
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
|
|
1198
|
+
onClick: toggleAddReleaseModal,
|
|
1199
|
+
disabled: hasReachedMaximumPendingReleases,
|
|
1200
|
+
children: formatMessage({
|
|
1201
|
+
id: "content-releases.header.actions.add-release",
|
|
1202
|
+
defaultMessage: "New release"
|
|
1203
|
+
})
|
|
1204
|
+
}
|
|
1205
|
+
) })
|
|
1206
|
+
}
|
|
1207
|
+
),
|
|
954
1208
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1209
|
+
activeTab === "pending" && hasReachedMaximumPendingReleases && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1210
|
+
StyledAlert,
|
|
1211
|
+
{
|
|
1212
|
+
marginBottom: 6,
|
|
1213
|
+
action: /* @__PURE__ */ jsxRuntime.jsx(v2.Link, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
|
|
1214
|
+
id: "content-releases.pages.Releases.max-limit-reached.action",
|
|
1215
|
+
defaultMessage: "Explore plans"
|
|
1216
|
+
}) }),
|
|
1217
|
+
title: formatMessage(
|
|
1218
|
+
{
|
|
1219
|
+
id: "content-releases.pages.Releases.max-limit-reached.title",
|
|
1220
|
+
defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
|
|
1221
|
+
},
|
|
1222
|
+
{ number: maximumReleases }
|
|
1223
|
+
),
|
|
1224
|
+
onClose: () => {
|
|
1225
|
+
},
|
|
1226
|
+
closeLabel: "",
|
|
1227
|
+
children: formatMessage({
|
|
1228
|
+
id: "content-releases.pages.Releases.max-limit-reached.message",
|
|
1229
|
+
defaultMessage: "Upgrade to manage an unlimited number of releases."
|
|
1230
|
+
})
|
|
1231
|
+
}
|
|
1232
|
+
),
|
|
955
1233
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
956
1234
|
designSystem.TabGroup,
|
|
957
1235
|
{
|
|
@@ -1034,4 +1312,4 @@ const App = () => {
|
|
|
1034
1312
|
] }) });
|
|
1035
1313
|
};
|
|
1036
1314
|
exports.App = App;
|
|
1037
|
-
//# sourceMappingURL=App-
|
|
1315
|
+
//# sourceMappingURL=App-OK4Xac-O.js.map
|