@strapi/content-releases 0.0.0-next.e1ede8c55a0e1e22ce20137bf238fc374bd5dd51 → 0.0.0-next.f8af92b375dc730ba47ed2117f25df893aae696c
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-o5_WfqR-.js → App-OK4Xac-O.js} +572 -224
- package/dist/_chunks/App-OK4Xac-O.js.map +1 -0
- package/dist/_chunks/App-xAkiD42p.mjs +1292 -0
- 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-haKSQIo8.js → en-r0otWaln.js} +19 -4
- package/dist/_chunks/en-r0otWaln.js.map +1 -0
- package/dist/_chunks/{en-ngTk74JV.mjs → en-veqvqeEr.mjs} +19 -4
- package/dist/_chunks/en-veqvqeEr.mjs.map +1 -0
- package/dist/_chunks/{index-EdBmRHRU.js → index-JvA2_26n.js} +220 -54
- package/dist/_chunks/index-JvA2_26n.js.map +1 -0
- package/dist/_chunks/{index-XAQOX_IB.mjs → index-exoiSU3V.mjs} +231 -65
- package/dist/_chunks/index-exoiSU3V.mjs.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +3 -2
- package/dist/admin/index.mjs.map +1 -1
- package/dist/server/index.js +749 -302
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +749 -303
- package/dist/server/index.mjs.map +1 -1
- package/package.json +13 -9
- package/dist/_chunks/App-g2P5kbSm.mjs +0 -945
- package/dist/_chunks/App-g2P5kbSm.mjs.map +0 -1
- package/dist/_chunks/App-o5_WfqR-.js.map +0 -1
- package/dist/_chunks/en-haKSQIo8.js.map +0 -1
- package/dist/_chunks/en-ngTk74JV.mjs.map +0 -1
- package/dist/_chunks/index-EdBmRHRU.js.map +0 -1
- package/dist/_chunks/index-XAQOX_IB.mjs.map +0 -1
|
@@ -3,18 +3,23 @@ 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
|
+
const strapiAdmin = require("@strapi/admin/strapi-admin");
|
|
8
9
|
const designSystem = require("@strapi/design-system");
|
|
9
10
|
const v2 = require("@strapi/design-system/v2");
|
|
10
11
|
const icons = require("@strapi/icons");
|
|
12
|
+
const format = require("date-fns/format");
|
|
13
|
+
const dateFnsTz = require("date-fns-tz");
|
|
11
14
|
const reactIntl = require("react-intl");
|
|
12
15
|
const styled = require("styled-components");
|
|
16
|
+
const dateFns = require("date-fns");
|
|
13
17
|
const formik = require("formik");
|
|
14
18
|
const yup = require("yup");
|
|
15
19
|
require("@reduxjs/toolkit/query");
|
|
16
20
|
require("axios");
|
|
17
21
|
require("@reduxjs/toolkit/query/react");
|
|
22
|
+
require("react-redux");
|
|
18
23
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
19
24
|
function _interopNamespace(e) {
|
|
20
25
|
if (e && e.__esModule)
|
|
@@ -35,10 +40,28 @@ function _interopNamespace(e) {
|
|
|
35
40
|
return Object.freeze(n);
|
|
36
41
|
}
|
|
37
42
|
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
|
43
|
+
const format__default = /* @__PURE__ */ _interopDefault(format);
|
|
38
44
|
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
|
39
45
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
|
40
46
|
const RELEASE_SCHEMA = yup__namespace.object().shape({
|
|
41
|
-
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
|
+
})
|
|
42
65
|
}).required().noUnknown();
|
|
43
66
|
const ReleaseModal = ({
|
|
44
67
|
handleClose,
|
|
@@ -49,6 +72,24 @@ const ReleaseModal = ({
|
|
|
49
72
|
const { formatMessage } = reactIntl.useIntl();
|
|
50
73
|
const { pathname } = reactRouterDom.useLocation();
|
|
51
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
|
+
};
|
|
52
93
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
|
|
53
94
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage(
|
|
54
95
|
{
|
|
@@ -60,45 +101,134 @@ const ReleaseModal = ({
|
|
|
60
101
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
61
102
|
formik.Formik,
|
|
62
103
|
{
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
+
},
|
|
66
115
|
validationSchema: RELEASE_SCHEMA,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
+
] }) }),
|
|
82
221
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
83
222
|
designSystem.ModalFooter,
|
|
84
223
|
{
|
|
85
224
|
startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }),
|
|
86
|
-
endActions: /* @__PURE__ */ jsxRuntime.jsx(
|
|
87
|
-
designSystem.Button,
|
|
225
|
+
endActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { name: "submit", loading: isLoading, type: "submit", children: formatMessage(
|
|
88
226
|
{
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
id: "content-releases.modal.form.button.submit",
|
|
96
|
-
defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
|
|
97
|
-
},
|
|
98
|
-
{ isCreatingRelease }
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
)
|
|
227
|
+
id: "content-releases.modal.form.button.submit",
|
|
228
|
+
defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
|
|
229
|
+
},
|
|
230
|
+
{ isCreatingRelease }
|
|
231
|
+
) })
|
|
102
232
|
}
|
|
103
233
|
)
|
|
104
234
|
] })
|
|
@@ -106,16 +236,59 @@ const ReleaseModal = ({
|
|
|
106
236
|
)
|
|
107
237
|
] });
|
|
108
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
|
+
};
|
|
109
285
|
const ReleaseInfoWrapper = styled__default.default(designSystem.Flex)`
|
|
110
286
|
align-self: stretch;
|
|
111
287
|
border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
|
|
112
288
|
border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
|
|
113
289
|
border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
|
|
114
290
|
`;
|
|
115
|
-
const
|
|
116
|
-
align-self: stretch;
|
|
117
|
-
cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
|
|
118
|
-
|
|
291
|
+
const StyledMenuItem = styled__default.default(v2.Menu.Item)`
|
|
119
292
|
svg path {
|
|
120
293
|
fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
|
|
121
294
|
}
|
|
@@ -124,43 +297,46 @@ const StyledFlex = styled__default.default(designSystem.Flex)`
|
|
|
124
297
|
}
|
|
125
298
|
`;
|
|
126
299
|
const PencilIcon = styled__default.default(icons.Pencil)`
|
|
127
|
-
width: ${({ theme }) => theme.spaces[
|
|
128
|
-
height: ${({ theme }) => theme.spaces[
|
|
300
|
+
width: ${({ theme }) => theme.spaces[3]};
|
|
301
|
+
height: ${({ theme }) => theme.spaces[3]};
|
|
129
302
|
path {
|
|
130
303
|
fill: ${({ theme }) => theme.colors.neutral600};
|
|
131
304
|
}
|
|
132
305
|
`;
|
|
133
306
|
const TrashIcon = styled__default.default(icons.Trash)`
|
|
134
|
-
width: ${({ theme }) => theme.spaces[
|
|
135
|
-
height: ${({ theme }) => theme.spaces[
|
|
307
|
+
width: ${({ theme }) => theme.spaces[3]};
|
|
308
|
+
height: ${({ theme }) => theme.spaces[3]};
|
|
136
309
|
path {
|
|
137
310
|
fill: ${({ theme }) => theme.colors.danger600};
|
|
138
311
|
}
|
|
139
312
|
`;
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
paddingTop: 2,
|
|
145
|
-
paddingBottom: 2,
|
|
146
|
-
paddingLeft: 4,
|
|
147
|
-
paddingRight: 4,
|
|
148
|
-
alignItems: "center",
|
|
149
|
-
gap: 2,
|
|
150
|
-
as: "button",
|
|
151
|
-
hasRadius: true,
|
|
152
|
-
onClick,
|
|
153
|
-
disabled,
|
|
154
|
-
children
|
|
155
|
-
}
|
|
156
|
-
);
|
|
157
|
-
};
|
|
158
|
-
const EntryValidationText = ({ status, action }) => {
|
|
313
|
+
const TypographyMaxWidth = styled__default.default(designSystem.Typography)`
|
|
314
|
+
max-width: 300px;
|
|
315
|
+
`;
|
|
316
|
+
const EntryValidationText = ({ action, schema, components, entry }) => {
|
|
159
317
|
const { formatMessage } = reactIntl.useIntl();
|
|
318
|
+
const { validate } = strapiAdmin.unstable_useDocument();
|
|
319
|
+
const { errors } = validate(entry, {
|
|
320
|
+
contentType: schema,
|
|
321
|
+
components,
|
|
322
|
+
isCreatingEntry: false
|
|
323
|
+
});
|
|
324
|
+
if (Object.keys(errors).length > 0) {
|
|
325
|
+
const validationErrorsMessages = Object.entries(errors).map(
|
|
326
|
+
([key, value]) => formatMessage(
|
|
327
|
+
{ id: `${value.id}.withField`, defaultMessage: value.defaultMessage },
|
|
328
|
+
{ field: key }
|
|
329
|
+
)
|
|
330
|
+
).join(" ");
|
|
331
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
|
332
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "danger600", as: icons.CrossCircle }),
|
|
333
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
|
|
334
|
+
] });
|
|
335
|
+
}
|
|
160
336
|
if (action == "publish") {
|
|
161
337
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
|
162
338
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "success600", as: icons.CheckCircle }),
|
|
163
|
-
|
|
339
|
+
entry.publishedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
|
|
164
340
|
id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
|
|
165
341
|
defaultMessage: "Already published"
|
|
166
342
|
}) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
|
@@ -171,7 +347,7 @@ const EntryValidationText = ({ status, action }) => {
|
|
|
171
347
|
}
|
|
172
348
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
|
173
349
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Icon, { color: "success600", as: icons.CheckCircle }),
|
|
174
|
-
|
|
350
|
+
!entry.publishedAt ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
|
|
175
351
|
id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
|
|
176
352
|
defaultMessage: "Already unpublished"
|
|
177
353
|
}) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
|
@@ -185,10 +361,8 @@ const ReleaseDetailsLayout = ({
|
|
|
185
361
|
toggleWarningSubmit,
|
|
186
362
|
children
|
|
187
363
|
}) => {
|
|
188
|
-
const { formatMessage } = reactIntl.useIntl();
|
|
364
|
+
const { formatMessage, formatDate, formatTime } = reactIntl.useIntl();
|
|
189
365
|
const { releaseId } = reactRouterDom.useParams();
|
|
190
|
-
const [isPopoverVisible, setIsPopoverVisible] = React__namespace.useState(false);
|
|
191
|
-
const moreButtonRef = React__namespace.useRef(null);
|
|
192
366
|
const {
|
|
193
367
|
data,
|
|
194
368
|
isLoading: isLoadingDetails,
|
|
@@ -201,14 +375,9 @@ const ReleaseDetailsLayout = ({
|
|
|
201
375
|
const {
|
|
202
376
|
allowedActions: { canUpdate, canDelete }
|
|
203
377
|
} = helperPlugin.useRBAC(index.PERMISSIONS);
|
|
378
|
+
const dispatch = index.useTypedDispatch();
|
|
379
|
+
const { trackUsage } = helperPlugin.useTracking();
|
|
204
380
|
const release = data?.data;
|
|
205
|
-
const handleTogglePopover = () => {
|
|
206
|
-
setIsPopoverVisible((prev) => !prev);
|
|
207
|
-
};
|
|
208
|
-
const openReleaseModal = () => {
|
|
209
|
-
toggleEditReleaseModal();
|
|
210
|
-
handleTogglePopover();
|
|
211
|
-
};
|
|
212
381
|
const handlePublishRelease = async () => {
|
|
213
382
|
const response = await publishRelease({ id: releaseId });
|
|
214
383
|
if ("data" in response) {
|
|
@@ -219,6 +388,12 @@ const ReleaseDetailsLayout = ({
|
|
|
219
388
|
defaultMessage: "Release was published successfully."
|
|
220
389
|
})
|
|
221
390
|
});
|
|
391
|
+
const { totalEntries: totalEntries2, totalPublishedEntries, totalUnpublishedEntries } = response.data.meta;
|
|
392
|
+
trackUsage("didPublishRelease", {
|
|
393
|
+
totalEntries: totalEntries2,
|
|
394
|
+
totalPublishedEntries,
|
|
395
|
+
totalUnpublishedEntries
|
|
396
|
+
});
|
|
222
397
|
} else if (index.isAxiosError(response.error)) {
|
|
223
398
|
toggleNotification({
|
|
224
399
|
type: "warning",
|
|
@@ -231,9 +406,20 @@ const ReleaseDetailsLayout = ({
|
|
|
231
406
|
});
|
|
232
407
|
}
|
|
233
408
|
};
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
409
|
+
const handleRefresh = () => {
|
|
410
|
+
dispatch(index.releaseApi.util.invalidateTags([{ type: "ReleaseAction", id: "LIST" }]));
|
|
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;
|
|
237
423
|
};
|
|
238
424
|
if (isLoadingDetails) {
|
|
239
425
|
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
|
|
@@ -256,90 +442,143 @@ const ReleaseDetailsLayout = ({
|
|
|
256
442
|
);
|
|
257
443
|
}
|
|
258
444
|
const totalEntries = release.actions.meta.count || 0;
|
|
259
|
-
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
|
+
) : "";
|
|
260
475
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoadingDetails, children: [
|
|
261
476
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
262
477
|
designSystem.HeaderLayout,
|
|
263
478
|
{
|
|
264
479
|
title: release.name,
|
|
265
|
-
subtitle:
|
|
266
|
-
{
|
|
267
|
-
id: "content-releases.pages.Details.header-subtitle",
|
|
268
|
-
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
269
|
-
},
|
|
270
|
-
{ number: totalEntries }
|
|
271
|
-
),
|
|
480
|
+
subtitle: numberOfEntriesText + (IsSchedulingEnabled && isScheduled ? ` - ${scheduledText}` : ""),
|
|
272
481
|
navigationAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
|
|
273
482
|
id: "global.back",
|
|
274
483
|
defaultMessage: "Back"
|
|
275
484
|
}) }),
|
|
276
485
|
primaryAction: !release.releasedAt && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
|
277
|
-
/* @__PURE__ */ jsxRuntime.
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
{
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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
|
+
] }),
|
|
578
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { size: "S", variant: "tertiary", onClick: handleRefresh, children: formatMessage({
|
|
579
|
+
id: "content-releases.header.actions.refresh",
|
|
580
|
+
defaultMessage: "Refresh"
|
|
581
|
+
}) }),
|
|
343
582
|
/* @__PURE__ */ jsxRuntime.jsx(helperPlugin.CheckPermissions, { permissions: index.PERMISSIONS.publish, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
344
583
|
designSystem.Button,
|
|
345
584
|
{
|
|
@@ -391,6 +630,9 @@ const ReleaseDetailsBody = () => {
|
|
|
391
630
|
isError: isReleaseError,
|
|
392
631
|
error: releaseError
|
|
393
632
|
} = index.useGetReleaseQuery({ id: releaseId });
|
|
633
|
+
const {
|
|
634
|
+
allowedActions: { canUpdate }
|
|
635
|
+
} = helperPlugin.useRBAC(index.PERMISSIONS);
|
|
394
636
|
const release = releaseData?.data;
|
|
395
637
|
const selectedGroupBy = query?.groupBy || "contentType";
|
|
396
638
|
const {
|
|
@@ -404,7 +646,7 @@ const ReleaseDetailsBody = () => {
|
|
|
404
646
|
releaseId
|
|
405
647
|
});
|
|
406
648
|
const [updateReleaseAction] = index.useUpdateReleaseActionMutation();
|
|
407
|
-
const handleChangeType = async (e, actionId) => {
|
|
649
|
+
const handleChangeType = async (e, actionId, actionPath) => {
|
|
408
650
|
const response = await updateReleaseAction({
|
|
409
651
|
params: {
|
|
410
652
|
releaseId,
|
|
@@ -412,7 +654,11 @@ const ReleaseDetailsBody = () => {
|
|
|
412
654
|
},
|
|
413
655
|
body: {
|
|
414
656
|
type: e.target.value
|
|
415
|
-
}
|
|
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
|
|
416
662
|
});
|
|
417
663
|
if ("error" in response) {
|
|
418
664
|
if (index.isAxiosError(response.error)) {
|
|
@@ -433,7 +679,9 @@ const ReleaseDetailsBody = () => {
|
|
|
433
679
|
}
|
|
434
680
|
const releaseActions = data?.data;
|
|
435
681
|
const releaseMeta = data?.meta;
|
|
436
|
-
|
|
682
|
+
const contentTypes = releaseMeta?.contentTypes || {};
|
|
683
|
+
const components = releaseMeta?.components || {};
|
|
684
|
+
if (isReleaseError || !release) {
|
|
437
685
|
const errorsArray = [];
|
|
438
686
|
if (releaseError) {
|
|
439
687
|
errorsArray.push({
|
|
@@ -457,6 +705,9 @@ const ReleaseDetailsBody = () => {
|
|
|
457
705
|
}
|
|
458
706
|
);
|
|
459
707
|
}
|
|
708
|
+
if (isError || !releaseActions) {
|
|
709
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {}) });
|
|
710
|
+
}
|
|
460
711
|
if (Object.keys(releaseActions).length === 0) {
|
|
461
712
|
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
462
713
|
helperPlugin.NoContent,
|
|
@@ -488,7 +739,7 @@ const ReleaseDetailsBody = () => {
|
|
|
488
739
|
designSystem.SingleSelect,
|
|
489
740
|
{
|
|
490
741
|
"aria-label": formatMessage({
|
|
491
|
-
id: "content-releases.pages.ReleaseDetails.groupBy.label",
|
|
742
|
+
id: "content-releases.pages.ReleaseDetails.groupBy.aria-label",
|
|
492
743
|
defaultMessage: "Group by"
|
|
493
744
|
}),
|
|
494
745
|
customizeContent: (value) => formatMessage(
|
|
@@ -506,7 +757,7 @@ const ReleaseDetailsBody = () => {
|
|
|
506
757
|
}
|
|
507
758
|
) }),
|
|
508
759
|
Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
|
|
509
|
-
/* @__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 }) }),
|
|
510
761
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
511
762
|
helperPlugin.Table.Root,
|
|
512
763
|
{
|
|
@@ -576,30 +827,59 @@ const ReleaseDetailsBody = () => {
|
|
|
576
827
|
)
|
|
577
828
|
] }),
|
|
578
829
|
/* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.LoadingBody, {}),
|
|
579
|
-
/* @__PURE__ */ jsxRuntime.jsx(helperPlugin.Table.Body, { children: releaseActions[key].map(
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
{
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
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
|
+
},
|
|
840
|
+
{
|
|
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
|
|
851
|
+
}
|
|
852
|
+
) }),
|
|
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,
|
|
856
|
+
{
|
|
857
|
+
action: type,
|
|
858
|
+
schema: contentTypes?.[contentType.uid],
|
|
859
|
+
components,
|
|
860
|
+
entry
|
|
861
|
+
}
|
|
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
|
+
) })
|
|
603
883
|
] })
|
|
604
884
|
}
|
|
605
885
|
)
|
|
@@ -646,11 +926,18 @@ const ReleaseDetailsPage = () => {
|
|
|
646
926
|
}
|
|
647
927
|
);
|
|
648
928
|
}
|
|
649
|
-
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") : "";
|
|
650
935
|
const handleEditRelease = async (values) => {
|
|
651
936
|
const response = await updateRelease({
|
|
652
937
|
id: releaseId,
|
|
653
|
-
name: values.name
|
|
938
|
+
name: values.name,
|
|
939
|
+
scheduledAt: values.scheduledAt,
|
|
940
|
+
timezone: values.timezone
|
|
654
941
|
});
|
|
655
942
|
if ("data" in response) {
|
|
656
943
|
toggleNotification({
|
|
@@ -704,7 +991,14 @@ const ReleaseDetailsPage = () => {
|
|
|
704
991
|
handleClose: toggleEditReleaseModal,
|
|
705
992
|
handleSubmit: handleEditRelease,
|
|
706
993
|
isLoading: isLoadingDetails || isSubmittingForm,
|
|
707
|
-
initialValues: {
|
|
994
|
+
initialValues: {
|
|
995
|
+
name: title || "",
|
|
996
|
+
scheduledAt,
|
|
997
|
+
date,
|
|
998
|
+
time,
|
|
999
|
+
isScheduled: Boolean(scheduledAt),
|
|
1000
|
+
timezone
|
|
1001
|
+
}
|
|
708
1002
|
}
|
|
709
1003
|
),
|
|
710
1004
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -724,42 +1018,12 @@ const ReleaseDetailsPage = () => {
|
|
|
724
1018
|
}
|
|
725
1019
|
);
|
|
726
1020
|
};
|
|
727
|
-
const ReleasesLayout = ({
|
|
728
|
-
isLoading,
|
|
729
|
-
totalReleases,
|
|
730
|
-
onClickAddRelease,
|
|
731
|
-
children
|
|
732
|
-
}) => {
|
|
733
|
-
const { formatMessage } = reactIntl.useIntl();
|
|
734
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
|
|
735
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
736
|
-
designSystem.HeaderLayout,
|
|
737
|
-
{
|
|
738
|
-
title: formatMessage({
|
|
739
|
-
id: "content-releases.pages.Releases.title",
|
|
740
|
-
defaultMessage: "Releases"
|
|
741
|
-
}),
|
|
742
|
-
subtitle: !isLoading && formatMessage(
|
|
743
|
-
{
|
|
744
|
-
id: "content-releases.pages.Releases.header-subtitle",
|
|
745
|
-
defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
|
|
746
|
-
},
|
|
747
|
-
{ number: totalReleases }
|
|
748
|
-
),
|
|
749
|
-
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({
|
|
750
|
-
id: "content-releases.header.actions.add-release",
|
|
751
|
-
defaultMessage: "New release"
|
|
752
|
-
}) }) })
|
|
753
|
-
}
|
|
754
|
-
),
|
|
755
|
-
children
|
|
756
|
-
] });
|
|
757
|
-
};
|
|
758
1021
|
const LinkCard = styled__default.default(v2.Link)`
|
|
759
1022
|
display: block;
|
|
760
1023
|
`;
|
|
761
1024
|
const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
762
1025
|
const { formatMessage } = reactIntl.useIntl();
|
|
1026
|
+
const IsSchedulingEnabled = window.strapi.future.isEnabled("contentReleasesScheduling");
|
|
763
1027
|
if (isError) {
|
|
764
1028
|
return /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.AnErrorOccurred, {});
|
|
765
1029
|
}
|
|
@@ -780,7 +1044,7 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
780
1044
|
}
|
|
781
1045
|
);
|
|
782
1046
|
}
|
|
783
|
-
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(
|
|
784
1048
|
designSystem.Flex,
|
|
785
1049
|
{
|
|
786
1050
|
direction: "column",
|
|
@@ -795,7 +1059,10 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
795
1059
|
gap: 2,
|
|
796
1060
|
children: [
|
|
797
1061
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
|
|
798
|
-
/* @__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(
|
|
799
1066
|
{
|
|
800
1067
|
id: "content-releases.page.Releases.release-item.entries",
|
|
801
1068
|
defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
|
|
@@ -806,10 +1073,25 @@ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
|
|
|
806
1073
|
}
|
|
807
1074
|
) }) }, id)) });
|
|
808
1075
|
};
|
|
1076
|
+
const StyledAlert = styled__default.default(designSystem.Alert)`
|
|
1077
|
+
button {
|
|
1078
|
+
display: none;
|
|
1079
|
+
}
|
|
1080
|
+
p + div {
|
|
1081
|
+
margin-left: auto;
|
|
1082
|
+
}
|
|
1083
|
+
`;
|
|
809
1084
|
const INITIAL_FORM_VALUES = {
|
|
810
|
-
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
|
|
811
1092
|
};
|
|
812
1093
|
const ReleasesPage = () => {
|
|
1094
|
+
const tabRef = React__namespace.useRef(null);
|
|
813
1095
|
const location = reactRouterDom.useLocation();
|
|
814
1096
|
const [releaseModalShown, setReleaseModalShown] = React__namespace.useState(false);
|
|
815
1097
|
const toggleNotification = helperPlugin.useNotification();
|
|
@@ -819,7 +1101,12 @@ const ReleasesPage = () => {
|
|
|
819
1101
|
const [{ query }, setQuery] = helperPlugin.useQueryParams();
|
|
820
1102
|
const response = index.useGetReleasesQuery(query);
|
|
821
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();
|
|
822
1107
|
const { isLoading, isSuccess, isError } = response;
|
|
1108
|
+
const activeTab = response?.currentData?.meta?.activeTab || "pending";
|
|
1109
|
+
const activeTabIndex = ["pending", "done"].indexOf(activeTab);
|
|
823
1110
|
React__namespace.useEffect(() => {
|
|
824
1111
|
if (location?.state?.errors) {
|
|
825
1112
|
toggleNotification({
|
|
@@ -836,13 +1123,19 @@ const ReleasesPage = () => {
|
|
|
836
1123
|
replace({ state: null });
|
|
837
1124
|
}
|
|
838
1125
|
}, [formatMessage, location?.state?.errors, replace, toggleNotification]);
|
|
1126
|
+
React__namespace.useEffect(() => {
|
|
1127
|
+
if (tabRef.current) {
|
|
1128
|
+
tabRef.current._handlers.setSelectedTabIndex(activeTabIndex);
|
|
1129
|
+
}
|
|
1130
|
+
}, [activeTabIndex]);
|
|
839
1131
|
const toggleAddReleaseModal = () => {
|
|
840
1132
|
setReleaseModalShown((prev) => !prev);
|
|
841
1133
|
};
|
|
842
1134
|
if (isLoading) {
|
|
843
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1135
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-busy": isLoading, children: /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}) });
|
|
844
1136
|
}
|
|
845
1137
|
const totalReleases = isSuccess && response.currentData?.meta?.pagination?.total || 0;
|
|
1138
|
+
const hasReachedMaximumPendingReleases = totalReleases >= maximumReleases;
|
|
846
1139
|
const handleTabChange = (index2) => {
|
|
847
1140
|
setQuery({
|
|
848
1141
|
...query,
|
|
@@ -855,10 +1148,11 @@ const ReleasesPage = () => {
|
|
|
855
1148
|
}
|
|
856
1149
|
});
|
|
857
1150
|
};
|
|
858
|
-
const
|
|
859
|
-
const handleAddRelease = async (values) => {
|
|
1151
|
+
const handleAddRelease = async ({ name, scheduledAt, timezone }) => {
|
|
860
1152
|
const response2 = await createRelease({
|
|
861
|
-
name
|
|
1153
|
+
name,
|
|
1154
|
+
scheduledAt,
|
|
1155
|
+
timezone
|
|
862
1156
|
});
|
|
863
1157
|
if ("data" in response2) {
|
|
864
1158
|
toggleNotification({
|
|
@@ -868,6 +1162,7 @@ const ReleasesPage = () => {
|
|
|
868
1162
|
defaultMessage: "Release created."
|
|
869
1163
|
})
|
|
870
1164
|
});
|
|
1165
|
+
trackUsage("didCreateRelease");
|
|
871
1166
|
push(`/plugins/content-releases/${response2.data.data.id}`);
|
|
872
1167
|
} else if (index.isAxiosError(response2.error)) {
|
|
873
1168
|
toggleNotification({
|
|
@@ -881,8 +1176,60 @@ const ReleasesPage = () => {
|
|
|
881
1176
|
});
|
|
882
1177
|
}
|
|
883
1178
|
};
|
|
884
|
-
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
|
+
),
|
|
885
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
|
+
),
|
|
886
1233
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
887
1234
|
designSystem.TabGroup,
|
|
888
1235
|
{
|
|
@@ -891,8 +1238,9 @@ const ReleasesPage = () => {
|
|
|
891
1238
|
defaultMessage: "Releases list"
|
|
892
1239
|
}),
|
|
893
1240
|
variant: "simple",
|
|
894
|
-
initialSelectedTabIndex:
|
|
1241
|
+
initialSelectedTabIndex: activeTabIndex,
|
|
895
1242
|
onTabChange: handleTabChange,
|
|
1243
|
+
ref: tabRef,
|
|
896
1244
|
children: [
|
|
897
1245
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingBottom: 8, children: [
|
|
898
1246
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs, { children: [
|
|
@@ -964,4 +1312,4 @@ const App = () => {
|
|
|
964
1312
|
] }) });
|
|
965
1313
|
};
|
|
966
1314
|
exports.App = App;
|
|
967
|
-
//# sourceMappingURL=App-
|
|
1315
|
+
//# sourceMappingURL=App-OK4Xac-O.js.map
|