@strapi/content-releases 0.0.0-next.6d59515520a3850456f256fb0e4c54b75054ddf4 → 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-L1jSxCiL.mjs → App-g3vtS2Wa.mjs} +524 -252
- package/dist/_chunks/App-g3vtS2Wa.mjs.map +1 -0
- package/dist/_chunks/{App-_20W9dYa.js → App-lnXbSPgp.js} +520 -247
- 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-MyLPoISH.mjs → en-WuuhP6Bn.mjs} +21 -6
- package/dist/_chunks/en-WuuhP6Bn.mjs.map +1 -0
- package/dist/_chunks/{en-gYDqKYFd.js → en-gcJJ5htG.js} +21 -6
- package/dist/_chunks/en-gcJJ5htG.js.map +1 -0
- package/dist/_chunks/{index-KJa1Rb5F.js → index-ItlgrLcr.js} +158 -32
- package/dist/_chunks/index-ItlgrLcr.js.map +1 -0
- package/dist/_chunks/{index-c4zRX_sg.mjs → index-uGex_IIQ.mjs} +163 -37
- 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 +887 -398
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +886 -398
- package/dist/server/index.mjs.map +1 -1
- package/package.json +14 -11
- 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-ItlgrLcr.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,33 +236,83 @@ 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
|
+
onTextValueChange: (timezone) => {
|
|
277
|
+
setFieldValue("timezone", timezone);
|
|
278
|
+
},
|
|
279
|
+
onClear: () => {
|
|
280
|
+
setFieldValue("timezone", "");
|
|
281
|
+
},
|
|
282
|
+
error: errors.timezone,
|
|
283
|
+
required: true,
|
|
284
|
+
children: timezoneList.map((timezone) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: timezone.value, children: timezone.value.replace("_", " ") }, timezone.value))
|
|
285
|
+
}
|
|
286
|
+
);
|
|
287
|
+
};
|
|
111
288
|
const ReleaseInfoWrapper = styled__default.default(designSystem.Flex)`
|
|
112
289
|
align-self: stretch;
|
|
113
290
|
border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
|
|
114
291
|
border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
|
|
115
292
|
border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
|
|
116
293
|
`;
|
|
117
|
-
const
|
|
118
|
-
align-self: stretch;
|
|
119
|
-
cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
|
|
120
|
-
|
|
294
|
+
const StyledMenuItem = styled__default.default(v2.Menu.Item)`
|
|
121
295
|
svg path {
|
|
122
296
|
fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
|
|
123
297
|
}
|
|
124
298
|
span {
|
|
125
299
|
color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
|
|
126
300
|
}
|
|
301
|
+
|
|
302
|
+
&:hover {
|
|
303
|
+
background: ${({ theme, variant = "neutral" }) => theme.colors[`${variant}100`]};
|
|
304
|
+
}
|
|
127
305
|
`;
|
|
128
306
|
const PencilIcon = styled__default.default(icons.Pencil)`
|
|
129
|
-
width: ${({ theme }) => theme.spaces[
|
|
130
|
-
height: ${({ theme }) => theme.spaces[
|
|
307
|
+
width: ${({ theme }) => theme.spaces[3]};
|
|
308
|
+
height: ${({ theme }) => theme.spaces[3]};
|
|
131
309
|
path {
|
|
132
310
|
fill: ${({ theme }) => theme.colors.neutral600};
|
|
133
311
|
}
|
|
134
312
|
`;
|
|
135
313
|
const TrashIcon = styled__default.default(icons.Trash)`
|
|
136
|
-
width: ${({ theme }) => theme.spaces[
|
|
137
|
-
height: ${({ theme }) => theme.spaces[
|
|
314
|
+
width: ${({ theme }) => theme.spaces[3]};
|
|
315
|
+
height: ${({ theme }) => theme.spaces[3]};
|
|
138
316
|
path {
|
|
139
317
|
fill: ${({ theme }) => theme.colors.danger600};
|
|
140
318
|
}
|
|
@@ -142,24 +320,6 @@ const TrashIcon = styled__default.default(icons.Trash)`
|
|
|
142
320
|
const TypographyMaxWidth = styled__default.default(designSystem.Typography)`
|
|
143
321
|
max-width: 300px;
|
|
144
322
|
`;
|
|
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
323
|
const EntryValidationText = ({ action, schema, components, entry }) => {
|
|
164
324
|
const { formatMessage } = reactIntl.useIntl();
|
|
165
325
|
const { validate } = strapiAdmin.unstable_useDocument();
|
|
@@ -208,10 +368,8 @@ const ReleaseDetailsLayout = ({
|
|
|
208
368
|
toggleWarningSubmit,
|
|
209
369
|
children
|
|
210
370
|
}) => {
|
|
211
|
-
const { formatMessage } = reactIntl.useIntl();
|
|
371
|
+
const { formatMessage, formatDate, formatTime } = reactIntl.useIntl();
|
|
212
372
|
const { releaseId } = reactRouterDom.useParams();
|
|
213
|
-
const [isPopoverVisible, setIsPopoverVisible] = React__namespace.useState(false);
|
|
214
|
-
const moreButtonRef = React__namespace.useRef(null);
|
|
215
373
|
const {
|
|
216
374
|
data,
|
|
217
375
|
isLoading: isLoadingDetails,
|
|
@@ -225,14 +383,8 @@ const ReleaseDetailsLayout = ({
|
|
|
225
383
|
allowedActions: { canUpdate, canDelete }
|
|
226
384
|
} = helperPlugin.useRBAC(index.PERMISSIONS);
|
|
227
385
|
const dispatch = index.useTypedDispatch();
|
|
386
|
+
const { trackUsage } = helperPlugin.useTracking();
|
|
228
387
|
const release = data?.data;
|
|
229
|
-
const handleTogglePopover = () => {
|
|
230
|
-
setIsPopoverVisible((prev) => !prev);
|
|
231
|
-
};
|
|
232
|
-
const openReleaseModal = () => {
|
|
233
|
-
toggleEditReleaseModal();
|
|
234
|
-
handleTogglePopover();
|
|
235
|
-
};
|
|
236
388
|
const handlePublishRelease = async () => {
|
|
237
389
|
const response = await publishRelease({ id: releaseId });
|
|
238
390
|
if ("data" in response) {
|
|
@@ -243,6 +395,12 @@ const ReleaseDetailsLayout = ({
|
|
|
243
395
|
defaultMessage: "Release was published successfully."
|
|
244
396
|
})
|
|
245
397
|
});
|
|
398
|
+
const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
|
|
399
|
+
trackUsage("didPublishRelease", {
|
|
400
|
+
totalEntries: totalEntries2,
|
|
401
|
+
totalPublishedEntries,
|
|
402
|
+
totalUnpublishedEntries
|
|
403
|
+
});
|
|
246
404
|
} else if (index.isAxiosError(response.error)) {
|
|
247
405
|
toggleNotification({
|
|
248
406
|
type: "warning",
|
|
@@ -255,13 +413,21 @@ const ReleaseDetailsLayout = ({
|
|
|
255
413
|
});
|
|
256
414
|
}
|
|
257
415
|
};
|
|
258
|
-
const openWarningConfirmDialog = () => {
|
|
259
|
-
toggleWarningSubmit();
|
|
260
|
-
handleTogglePopover();
|
|
261
|
-
};
|
|
262
416
|
const handleRefresh = () => {
|
|
263
417
|
dispatch(index.releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
|
|
264
418
|
};
|
|
419
|
+
const getCreatedByUser = () => {
|
|
420
|
+
if (!release?.createdBy) {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
if (release.createdBy.username) {
|
|
424
|
+
return release.createdBy.username;
|
|
425
|
+
}
|
|
426
|
+
if (release.createdBy.firstname) {
|
|
427
|
+
return `${release.createdBy.firstname} ${release.createdBy.lastname || ""}`.trim();
|
|
428
|
+
}
|
|
429
|
+
return release.createdBy.email;
|
|
430
|
+
};
|
|
265
431
|
if (isLoadingDetails) {
|
|
266
432
|
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
|
|
267
433
|
}
|
|
@@ -283,90 +449,125 @@ const ReleaseDetailsLayout = ({
|
|
|
283
449
|
);
|
|
284
450
|
}
|
|
285
451
|
const totalEntries = release.actions.meta.count || 0;
|
|
286
|
-
const
|
|
452
|
+
const hasCreatedByUser = Boolean(getCreatedByUser());
|
|
453
|
+
const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
|
|
454
|
+
const isScheduled = release.scheduledAt && release.timezone;
|
|
455
|
+
const numberOfEntriesText = formatMessage(
|
|
456
|
+
{
|
|
457
|
+
id: "content-releases.pages.Details.header-subtitle",
|
|
458
|
+
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
459
|
+
},
|
|
460
|
+
{ number: totalEntries }
|
|
461
|
+
);
|
|
462
|
+
const scheduledText = isScheduled ? formatMessage(
|
|
463
|
+
{
|
|
464
|
+
id: "content-releases.pages.ReleaseDetails.header-subtitle.scheduled",
|
|
465
|
+
defaultMessage: "Scheduled for {date} at {time} ({offset})"
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
date: formatDate(new Date(release.scheduledAt), {
|
|
469
|
+
weekday: "long",
|
|
470
|
+
day: "numeric",
|
|
471
|
+
month: "long",
|
|
472
|
+
year: "numeric",
|
|
473
|
+
timeZone: release.timezone
|
|
474
|
+
}),
|
|
475
|
+
time: formatTime(new Date(release.scheduledAt), {
|
|
476
|
+
timeZone: release.timezone,
|
|
477
|
+
hourCycle: "h23"
|
|
478
|
+
}),
|
|
479
|
+
offset: index.getTimezoneOffset(release.timezone, new Date(release.scheduledAt))
|
|
480
|
+
}
|
|
481
|
+
) : "";
|
|
287
482
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoadingDetails, children: [
|
|
288
483
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
289
484
|
designSystem.HeaderLayout,
|
|
290
485
|
{
|
|
291
486
|
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
|
-
),
|
|
487
|
+
subtitle: numberOfEntriesText + (IsSchedulingEnabled && isScheduled ? ` - ${scheduledText}` : ""),
|
|
299
488
|
navigationAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
|
|
300
489
|
id: "global.back",
|
|
301
490
|
defaultMessage: "Back"
|
|
302
491
|
}) }),
|
|
303
492
|
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
|
-
|
|
493
|
+
/* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Root, { children: [
|
|
494
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
495
|
+
v2.Menu.Trigger,
|
|
496
|
+
{
|
|
497
|
+
as: designSystem.IconButton,
|
|
498
|
+
paddingLeft: 2,
|
|
499
|
+
paddingRight: 2,
|
|
500
|
+
"aria-label": formatMessage({
|
|
501
|
+
id: "content-releases.header.actions.open-release-actions",
|
|
502
|
+
defaultMessage: "Release edit and delete menu"
|
|
503
|
+
}),
|
|
504
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.More, {}),
|
|
505
|
+
variant: "tertiary"
|
|
506
|
+
}
|
|
507
|
+
),
|
|
508
|
+
/* @__PURE__ */ jsxRuntime.jsxs(v2.Menu.Content, { top: 1, popoverPlacement: "bottom-end", children: [
|
|
509
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
510
|
+
designSystem.Flex,
|
|
511
|
+
{
|
|
512
|
+
alignItems: "center",
|
|
513
|
+
justifyContent: "center",
|
|
514
|
+
direction: "column",
|
|
515
|
+
padding: 1,
|
|
516
|
+
width: "100%",
|
|
517
|
+
children: [
|
|
518
|
+
/* @__PURE__ */ jsxRuntime.jsx(StyledMenuItem, { disabled: !canUpdate, onSelect: toggleEditReleaseModal, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
|
|
519
|
+
/* @__PURE__ */ jsxRuntime.jsx(PencilIcon, {}),
|
|
520
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: formatMessage({
|
|
521
|
+
id: "content-releases.header.actions.edit",
|
|
522
|
+
defaultMessage: "Edit"
|
|
523
|
+
}) })
|
|
524
|
+
] }) }),
|
|
525
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
526
|
+
StyledMenuItem,
|
|
527
|
+
{
|
|
528
|
+
disabled: !canDelete,
|
|
529
|
+
onSelect: toggleWarningSubmit,
|
|
530
|
+
variant: "danger",
|
|
531
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 2, hasRadius: true, width: "100%", children: [
|
|
532
|
+
/* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {}),
|
|
533
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
|
|
534
|
+
id: "content-releases.header.actions.delete",
|
|
535
|
+
defaultMessage: "Delete"
|
|
536
|
+
}) })
|
|
537
|
+
] })
|
|
538
|
+
}
|
|
539
|
+
)
|
|
540
|
+
]
|
|
541
|
+
}
|
|
542
|
+
),
|
|
543
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
544
|
+
ReleaseInfoWrapper,
|
|
545
|
+
{
|
|
546
|
+
direction: "column",
|
|
547
|
+
justifyContent: "center",
|
|
548
|
+
alignItems: "flex-start",
|
|
549
|
+
gap: 1,
|
|
550
|
+
padding: 5,
|
|
551
|
+
children: [
|
|
552
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
|
|
553
|
+
id: "content-releases.header.actions.created",
|
|
554
|
+
defaultMessage: "Created"
|
|
555
|
+
}) }),
|
|
556
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", color: "neutral300", children: [
|
|
557
|
+
/* @__PURE__ */ jsxRuntime.jsx(helperPlugin.RelativeTime, { timestamp: new Date(release.createdAt) }),
|
|
558
|
+
formatMessage(
|
|
559
|
+
{
|
|
560
|
+
id: "content-releases.header.actions.created.description",
|
|
561
|
+
defaultMessage: "{hasCreatedByUser, select, true { by {createdBy}} other { by deleted user}}"
|
|
562
|
+
},
|
|
563
|
+
{ createdBy: getCreatedByUser(), hasCreatedByUser }
|
|
564
|
+
)
|
|
565
|
+
] })
|
|
566
|
+
]
|
|
567
|
+
}
|
|
568
|
+
)
|
|
569
|
+
] })
|
|
570
|
+
] }),
|
|
370
571
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
|
|
371
572
|
id: "content-releases.header.actions.refresh",
|
|
372
573
|
defaultMessage: "Refresh"
|
|
@@ -422,6 +623,9 @@ const ReleaseDetailsBody = () => {
|
|
|
422
623
|
isError: isReleaseError,
|
|
423
624
|
error: releaseError
|
|
424
625
|
} = index.useGetReleaseQuery({ id: releaseId });
|
|
626
|
+
const {
|
|
627
|
+
allowedActions: { canUpdate }
|
|
628
|
+
} = helperPlugin.useRBAC(index.PERMISSIONS);
|
|
425
629
|
const release = releaseData?.data;
|
|
426
630
|
const selectedGroupBy = query?.groupBy || "contentType";
|
|
427
631
|
const {
|
|
@@ -435,7 +639,7 @@ const ReleaseDetailsBody = () => {
|
|
|
435
639
|
releaseId
|
|
436
640
|
});
|
|
437
641
|
const [updateReleaseAction] = index.useUpdateReleaseActionMutation();
|
|
438
|
-
const handleChangeType = async (e, actionId) => {
|
|
642
|
+
const handleChangeType = async (e, actionId, actionPath) => {
|
|
439
643
|
const response = await updateReleaseAction({
|
|
440
644
|
params: {
|
|
441
645
|
releaseId,
|
|
@@ -443,7 +647,11 @@ const ReleaseDetailsBody = () => {
|
|
|
443
647
|
},
|
|
444
648
|
body: {
|
|
445
649
|
type: e.target.value
|
|
446
|
-
}
|
|
650
|
+
},
|
|
651
|
+
query,
|
|
652
|
+
// We are passing the query params to make optimistic updates
|
|
653
|
+
actionPath
|
|
654
|
+
// We are passing the action path to found the position in the cache of the action for optimistic updates
|
|
447
655
|
});
|
|
448
656
|
if ("error" in response) {
|
|
449
657
|
if (index.isAxiosError(response.error)) {
|
|
@@ -524,7 +732,7 @@ const ReleaseDetailsBody = () => {
|
|
|
524
732
|
designSystem.SingleSelect,
|
|
525
733
|
{
|
|
526
734
|
"aria-label": formatMessage({
|
|
527
|
-
id: "content-releases.pages.ReleaseDetails.groupBy.label",
|
|
735
|
+
id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
|
|
528
736
|
defaultMessage: "Group by"
|
|
529
737
|
}),
|
|
530
738
|
customizeContent: (value) => formatMessage(
|
|
@@ -542,7 +750,7 @@ const ReleaseDetailsBody = () => {
|
|
|
542
750
|
}
|
|
543
751
|
) }),
|
|
544
752
|
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 }) }),
|
|
753
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { role: "separator", "aria-label": key, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: key }) }),
|
|
546
754
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
547
755
|
helperPlugin.Table.Root,
|
|
548
756
|
{
|
|
@@ -612,56 +820,59 @@ const ReleaseDetailsBody = () => {
|
|
|
612
820
|
)
|
|
613
821
|
] }),
|
|
614
822
|
/* @__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
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
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,
|
|
823
|
+
/* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.Body, { children: releaseActions[key].map(
|
|
824
|
+
({ id, contentType, locale, type, entry }, actionIndex) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
825
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "25%", maxWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { ellipsis: true, children: `${contentType.mainFieldValue || entry.id}` }) }),
|
|
826
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: `${locale?.name ? locale.name : "-"}` }) }),
|
|
827
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "10%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: contentType.displayName || "" }) }),
|
|
828
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", children: release.releasedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage(
|
|
829
|
+
{
|
|
830
|
+
id: "content-releases.page.ReleaseDetails.table.action-published",
|
|
831
|
+
defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
|
|
832
|
+
},
|
|
833
|
+
{
|
|
834
|
+
isPublish: type === "publish",
|
|
835
|
+
b: (children) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children })
|
|
836
|
+
}
|
|
837
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
838
|
+
index.ReleaseActionOptions,
|
|
639
839
|
{
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
840
|
+
selected: type,
|
|
841
|
+
handleChange: (e) => handleChangeType(e, id, [key, actionIndex]),
|
|
842
|
+
name: `release-action-${id}-type`,
|
|
843
|
+
disabled: !canUpdate
|
|
644
844
|
}
|
|
645
845
|
) }),
|
|
646
|
-
|
|
647
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
648
|
-
|
|
846
|
+
!release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
847
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", minWidth: "200px", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
848
|
+
EntryValidationText,
|
|
649
849
|
{
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
850
|
+
action: type,
|
|
851
|
+
schema: contentTypes?.[contentType.uid],
|
|
852
|
+
components,
|
|
853
|
+
entry
|
|
653
854
|
}
|
|
654
|
-
),
|
|
655
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
855
|
+
) }),
|
|
856
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxRuntime.jsxs(index.ReleaseActionMenu.Root, { children: [
|
|
857
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
858
|
+
index.ReleaseActionMenu.ReleaseActionEntryLinkItem,
|
|
859
|
+
{
|
|
860
|
+
contentTypeUid: contentType.uid,
|
|
861
|
+
entryId: entry.id,
|
|
862
|
+
locale: locale?.code
|
|
863
|
+
}
|
|
864
|
+
),
|
|
865
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
866
|
+
index.ReleaseActionMenu.DeleteReleaseActionItem,
|
|
867
|
+
{
|
|
868
|
+
releaseId: release.id,
|
|
869
|
+
actionId: id
|
|
870
|
+
}
|
|
871
|
+
)
|
|
872
|
+
] }) }) })
|
|
873
|
+
] })
|
|
874
|
+
] }, id)
|
|
875
|
+
) })
|
|
665
876
|
] })
|
|
666
877
|
}
|
|
667
878
|
)
|
|
@@ -708,11 +919,18 @@ const ReleaseDetailsPage = () => {
|
|
|
708
919
|
}
|
|
709
920
|
);
|
|
710
921
|
}
|
|
711
|
-
const
|
|
922
|
+
const releaseData = isSuccessDetails && data?.data || null;
|
|
923
|
+
const title = releaseData?.name || "";
|
|
924
|
+
const timezone = releaseData?.timezone ?? null;
|
|
925
|
+
const scheduledAt = releaseData?.scheduledAt && timezone ? dateFnsTz.utcToZonedTime(releaseData.scheduledAt, timezone) : null;
|
|
926
|
+
const date = scheduledAt ? new Date(format__default.default(scheduledAt, "yyyy-MM-dd")) : null;
|
|
927
|
+
const time = scheduledAt ? format__default.default(scheduledAt, "HH:mm") : "";
|
|
712
928
|
const handleEditRelease = async (values) => {
|
|
713
929
|
const response = await updateRelease({
|
|
714
930
|
id: releaseId,
|
|
715
|
-
name: values.name
|
|
931
|
+
name: values.name,
|
|
932
|
+
scheduledAt: values.scheduledAt,
|
|
933
|
+
timezone: values.timezone
|
|
716
934
|
});
|
|
717
935
|
if ("data" in response) {
|
|
718
936
|
toggleNotification({
|
|
@@ -766,7 +984,14 @@ const ReleaseDetailsPage = () => {
|
|
|
766
984
|
handleClose: toggleEditReleaseModal,
|
|
767
985
|
handleSubmit: handleEditRelease,
|
|
768
986
|
isLoading: isLoadingDetails || isSubmittingForm,
|
|
769
|
-
initialValues: {
|
|
987
|
+
initialValues: {
|
|
988
|
+
name: title || "",
|
|
989
|
+
scheduledAt,
|
|
990
|
+
date,
|
|
991
|
+
time,
|
|
992
|
+
isScheduled: Boolean(scheduledAt),
|
|
993
|
+
timezone
|
|
994
|
+
}
|
|
770
995
|
}
|
|
771
996
|
),
|
|
772
997
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -786,42 +1011,12 @@ const ReleaseDetailsPage = () => {
|
|
|
786
1011
|
}
|
|
787
1012
|
);
|
|
788
1013
|
};
|
|
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
1014
|
const LinkCard = styled__default.default(v2.Link)`
|
|
821
1015
|
display: block;
|
|
822
1016
|
`;
|
|
823
1017
|
const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
824
1018
|
const { formatMessage } = reactIntl.useIntl();
|
|
1019
|
+
const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
|
|
825
1020
|
if (isError) {
|
|
826
1021
|
return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
|
|
827
1022
|
}
|
|
@@ -842,7 +1037,7 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
842
1037
|
}
|
|
843
1038
|
);
|
|
844
1039
|
}
|
|
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(
|
|
1040
|
+
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
1041
|
designSystem.Flex,
|
|
847
1042
|
{
|
|
848
1043
|
direction: "column",
|
|
@@ -857,7 +1052,10 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
857
1052
|
gap: 2,
|
|
858
1053
|
children: [
|
|
859
1054
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
|
|
860
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", children: formatMessage(
|
|
1055
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: IsSchedulingEnabled ? scheduledAt ? /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.RelativeTime, { timestamp: new Date(scheduledAt) }) : formatMessage({
|
|
1056
|
+
id: "content-releases.pages.Releases.not-scheduled",
|
|
1057
|
+
defaultMessage: "Not scheduled"
|
|
1058
|
+
}) : formatMessage(
|
|
861
1059
|
{
|
|
862
1060
|
id: "content-releases.page.Releases.release-item.entries",
|
|
863
1061
|
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
@@ -868,8 +1066,22 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
868
1066
|
}
|
|
869
1067
|
) }) }, id)) });
|
|
870
1068
|
};
|
|
1069
|
+
const StyledAlert = styled__default.default(designSystem.Alert)`
|
|
1070
|
+
button {
|
|
1071
|
+
display: none;
|
|
1072
|
+
}
|
|
1073
|
+
p + div {
|
|
1074
|
+
margin-left: auto;
|
|
1075
|
+
}
|
|
1076
|
+
`;
|
|
871
1077
|
const INITIAL_FORM_VALUES = {
|
|
872
|
-
name: ""
|
|
1078
|
+
name: "",
|
|
1079
|
+
date: null,
|
|
1080
|
+
time: "",
|
|
1081
|
+
// Remove future flag check after Scheduling Beta release and replace with true as creating new release should include scheduling by default
|
|
1082
|
+
isScheduled: window.strapi.future.isEnabled("contentReleasesScheduling"),
|
|
1083
|
+
scheduledAt: null,
|
|
1084
|
+
timezone: null
|
|
873
1085
|
};
|
|
874
1086
|
const ReleasesPage = () => {
|
|
875
1087
|
const tabRef = React__namespace.useRef(null);
|
|
@@ -882,6 +1094,9 @@ const ReleasesPage = () => {
|
|
|
882
1094
|
const [{ query }, setQuery] = helperPlugin.useQueryParams();
|
|
883
1095
|
const response = index.useGetReleasesQuery(query);
|
|
884
1096
|
const [createRelease, { isLoading: isSubmittingForm }] = index.useCreateReleaseMutation();
|
|
1097
|
+
const { getFeature } = strapiAdmin.useLicenseLimits();
|
|
1098
|
+
const { maximumReleases = 3 } = getFeature("cms-content-releases");
|
|
1099
|
+
const { trackUsage } = helperPlugin.useTracking();
|
|
885
1100
|
const { isLoading, isSuccess, isError } = response;
|
|
886
1101
|
const activeTab = response?.currentData?.meta?.activeTab || "pending";
|
|
887
1102
|
const activeTabIndex = ["pending", "done"].indexOf(activeTab);
|
|
@@ -910,9 +1125,10 @@ const ReleasesPage = () => {
|
|
|
910
1125
|
setReleaseModalShown((prev) => !prev);
|
|
911
1126
|
};
|
|
912
1127
|
if (isLoading) {
|
|
913
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1128
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
|
|
914
1129
|
}
|
|
915
|
-
const
|
|
1130
|
+
const totalPendingReleases = isSuccess && response.currentData?.meta?.pendingReleasesCount || 0;
|
|
1131
|
+
const hasReachedMaximumPendingReleases = totalPendingReleases >= maximumReleases;
|
|
916
1132
|
const handleTabChange = (index2) => {
|
|
917
1133
|
setQuery({
|
|
918
1134
|
...query,
|
|
@@ -925,9 +1141,11 @@ const ReleasesPage = () => {
|
|
|
925
1141
|
}
|
|
926
1142
|
});
|
|
927
1143
|
};
|
|
928
|
-
const handleAddRelease = async (
|
|
1144
|
+
const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
|
|
929
1145
|
const response2 = await createRelease({
|
|
930
|
-
name
|
|
1146
|
+
name,
|
|
1147
|
+
scheduledAt,
|
|
1148
|
+
timezone
|
|
931
1149
|
});
|
|
932
1150
|
if ("data" in response2) {
|
|
933
1151
|
toggleNotification({
|
|
@@ -937,6 +1155,7 @@ const ReleasesPage = () => {
|
|
|
937
1155
|
defaultMessage: "Release created."
|
|
938
1156
|
})
|
|
939
1157
|
});
|
|
1158
|
+
trackUsage("didCreateRelease");
|
|
940
1159
|
push(`/plugins/content-releases/${response2.data.data.id}`);
|
|
941
1160
|
} else if (index.isAxiosError(response2.error)) {
|
|
942
1161
|
toggleNotification({
|
|
@@ -950,8 +1169,57 @@ const ReleasesPage = () => {
|
|
|
950
1169
|
});
|
|
951
1170
|
}
|
|
952
1171
|
};
|
|
953
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1172
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
|
|
1173
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1174
|
+
designSystem.HeaderLayout,
|
|
1175
|
+
{
|
|
1176
|
+
title: formatMessage({
|
|
1177
|
+
id: "content-releases.pages.Releases.title",
|
|
1178
|
+
defaultMessage: "Releases"
|
|
1179
|
+
}),
|
|
1180
|
+
subtitle: formatMessage({
|
|
1181
|
+
id: "content-releases.pages.Releases.header-subtitle",
|
|
1182
|
+
defaultMessage: "Create and manage content updates"
|
|
1183
|
+
}),
|
|
1184
|
+
primaryAction: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.create, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1185
|
+
designSystem.Button,
|
|
1186
|
+
{
|
|
1187
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
|
|
1188
|
+
onClick: toggleAddReleaseModal,
|
|
1189
|
+
disabled: hasReachedMaximumPendingReleases,
|
|
1190
|
+
children: formatMessage({
|
|
1191
|
+
id: "content-releases.header.actions.add-release",
|
|
1192
|
+
defaultMessage: "New release"
|
|
1193
|
+
})
|
|
1194
|
+
}
|
|
1195
|
+
) })
|
|
1196
|
+
}
|
|
1197
|
+
),
|
|
954
1198
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1199
|
+
hasReachedMaximumPendingReleases && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1200
|
+
StyledAlert,
|
|
1201
|
+
{
|
|
1202
|
+
marginBottom: 6,
|
|
1203
|
+
action: /* @__PURE__ */ jsxRuntime.jsx(v2.Link, { href: "https://strapi.io/pricing-cloud", isExternal: true, children: formatMessage({
|
|
1204
|
+
id: "content-releases.pages.Releases.max-limit-reached.action",
|
|
1205
|
+
defaultMessage: "Explore plans"
|
|
1206
|
+
}) }),
|
|
1207
|
+
title: formatMessage(
|
|
1208
|
+
{
|
|
1209
|
+
id: "content-releases.pages.Releases.max-limit-reached.title",
|
|
1210
|
+
defaultMessage: "You have reached the {number} pending {number, plural, one {release} other {releases}} limit."
|
|
1211
|
+
},
|
|
1212
|
+
{ number: maximumReleases }
|
|
1213
|
+
),
|
|
1214
|
+
onClose: () => {
|
|
1215
|
+
},
|
|
1216
|
+
closeLabel: "",
|
|
1217
|
+
children: formatMessage({
|
|
1218
|
+
id: "content-releases.pages.Releases.max-limit-reached.message",
|
|
1219
|
+
defaultMessage: "Upgrade to manage an unlimited number of releases."
|
|
1220
|
+
})
|
|
1221
|
+
}
|
|
1222
|
+
),
|
|
955
1223
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
956
1224
|
designSystem.TabGroup,
|
|
957
1225
|
{
|
|
@@ -966,10 +1234,15 @@ const ReleasesPage = () => {
|
|
|
966
1234
|
children: [
|
|
967
1235
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingBottom: 8, children: [
|
|
968
1236
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs, { children: [
|
|
969
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage(
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1237
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage(
|
|
1238
|
+
{
|
|
1239
|
+
id: "content-releases.pages.Releases.tab.pending",
|
|
1240
|
+
defaultMessage: "Pending ({count})"
|
|
1241
|
+
},
|
|
1242
|
+
{
|
|
1243
|
+
count: totalPendingReleases
|
|
1244
|
+
}
|
|
1245
|
+
) }),
|
|
973
1246
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tab, { children: formatMessage({
|
|
974
1247
|
id: "content-releases.pages.Releases.tab.done",
|
|
975
1248
|
defaultMessage: "Done"
|
|
@@ -998,7 +1271,7 @@ const ReleasesPage = () => {
|
|
|
998
1271
|
]
|
|
999
1272
|
}
|
|
1000
1273
|
),
|
|
1001
|
-
|
|
1274
|
+
response.currentData?.meta?.pagination?.total ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
|
|
1002
1275
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1003
1276
|
helperPlugin.PageSizeURLQuery,
|
|
1004
1277
|
{
|
|
@@ -1014,7 +1287,7 @@ const ReleasesPage = () => {
|
|
|
1014
1287
|
}
|
|
1015
1288
|
}
|
|
1016
1289
|
)
|
|
1017
|
-
] })
|
|
1290
|
+
] }) : null
|
|
1018
1291
|
] }) }),
|
|
1019
1292
|
releaseModalShown && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1020
1293
|
ReleaseModal,
|
|
@@ -1034,4 +1307,4 @@ const App = () => {
|
|
|
1034
1307
|
] }) });
|
|
1035
1308
|
};
|
|
1036
1309
|
exports.App = App;
|
|
1037
|
-
//# sourceMappingURL=App-
|
|
1310
|
+
//# sourceMappingURL=App-lnXbSPgp.js.map
|