@strapi/content-releases 0.0.0-experimental.check-license → 0.0.0-next.09b9d36b22a205d90c9303f2e37134938cf76c90

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.
@@ -0,0 +1,945 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { useNotification, useAPIErrorHandler, LoadingIndicatorPage, ConfirmDialog, useRBAC, RelativeTime, CheckPermissions, useQueryParams, NoContent, Table, PageSizeURLQuery, PaginationURLQuery, AnErrorOccurred, CheckPagePermissions } from "@strapi/helper-plugin";
3
+ import { useLocation, useParams, useHistory, Redirect, Link as Link$1, Switch, Route } from "react-router-dom";
4
+ import { p as pluginId, u as useGetReleaseQuery, a as useUpdateReleaseMutation, b as useDeleteReleaseMutation, c as usePublishReleaseMutation, P as PERMISSIONS, d as useGetReleaseActionsQuery, e as useUpdateReleaseActionMutation, R as ReleaseActionOptions, f as ReleaseActionMenu, i as isAxiosError, g as useGetReleasesQuery, h as useCreateReleaseMutation } from "./index-e14e1ea9.mjs";
5
+ import * as React from "react";
6
+ import { ModalLayout, ModalHeader, Typography, ModalBody, TextInput, ModalFooter, Button, Flex, ContentLayout, Main, HeaderLayout, Link, IconButton, Popover, SingleSelect, SingleSelectOption, Badge, Tr, Td, Icon, TabGroup, Box, Tabs, Tab, Divider, TabPanels, TabPanel, EmptyStateLayout, Grid, GridItem } from "@strapi/design-system";
7
+ import { LinkButton, Link as Link$2 } from "@strapi/design-system/v2";
8
+ import { Pencil, Trash, ArrowLeft, More, CheckCircle, Plus, EmptyDocuments } from "@strapi/icons";
9
+ import { useIntl } from "react-intl";
10
+ import styled from "styled-components";
11
+ import { Formik, Form } from "formik";
12
+ import * as yup from "yup";
13
+ import "@reduxjs/toolkit/query";
14
+ import "axios";
15
+ import "@reduxjs/toolkit/query/react";
16
+ const RELEASE_SCHEMA = yup.object().shape({
17
+ name: yup.string().trim().required()
18
+ }).required().noUnknown();
19
+ const ReleaseModal = ({
20
+ handleClose,
21
+ handleSubmit,
22
+ initialValues,
23
+ isLoading = false
24
+ }) => {
25
+ const { formatMessage } = useIntl();
26
+ const { pathname } = useLocation();
27
+ const isCreatingRelease = pathname === `/plugins/${pluginId}`;
28
+ return /* @__PURE__ */ jsxs(ModalLayout, { onClose: handleClose, labelledBy: "title", children: [
29
+ /* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { id: "title", fontWeight: "bold", textColor: "neutral800", children: formatMessage(
30
+ {
31
+ id: "content-releases.modal.title",
32
+ defaultMessage: "{isCreatingRelease, select, true {New release} other {Edit release}}"
33
+ },
34
+ { isCreatingRelease }
35
+ ) }) }),
36
+ /* @__PURE__ */ jsx(
37
+ Formik,
38
+ {
39
+ validateOnChange: false,
40
+ onSubmit: handleSubmit,
41
+ initialValues,
42
+ validationSchema: RELEASE_SCHEMA,
43
+ children: ({ values, errors, handleChange }) => /* @__PURE__ */ jsxs(Form, { children: [
44
+ /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsx(
45
+ TextInput,
46
+ {
47
+ label: formatMessage({
48
+ id: "content-releases.modal.form.input.label.release-name",
49
+ defaultMessage: "Name"
50
+ }),
51
+ name: "name",
52
+ value: values.name,
53
+ error: errors.name,
54
+ onChange: handleChange,
55
+ required: true
56
+ }
57
+ ) }),
58
+ /* @__PURE__ */ jsx(
59
+ ModalFooter,
60
+ {
61
+ startActions: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", name: "cancel", children: formatMessage({ id: "cancel", defaultMessage: "Cancel" }) }),
62
+ endActions: /* @__PURE__ */ jsx(
63
+ Button,
64
+ {
65
+ name: "submit",
66
+ loading: isLoading,
67
+ disabled: !values.name || values.name === initialValues.name,
68
+ type: "submit",
69
+ children: formatMessage(
70
+ {
71
+ id: "content-releases.modal.form.button.submit",
72
+ defaultMessage: "{isCreatingRelease, select, true {Continue} other {Save}}"
73
+ },
74
+ { isCreatingRelease }
75
+ )
76
+ }
77
+ )
78
+ }
79
+ )
80
+ ] })
81
+ }
82
+ )
83
+ ] });
84
+ };
85
+ const ReleaseInfoWrapper = styled(Flex)`
86
+ align-self: stretch;
87
+ border-bottom-right-radius: ${({ theme }) => theme.borderRadius};
88
+ border-bottom-left-radius: ${({ theme }) => theme.borderRadius};
89
+ border-top: 1px solid ${({ theme }) => theme.colors.neutral150};
90
+ `;
91
+ const StyledFlex = styled(Flex)`
92
+ align-self: stretch;
93
+ cursor: ${({ disabled }) => disabled ? "not-allowed" : "pointer"};
94
+
95
+ svg path {
96
+ fill: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
97
+ }
98
+ span {
99
+ color: ${({ theme, disabled }) => disabled && theme.colors.neutral500};
100
+ }
101
+ `;
102
+ const PencilIcon = styled(Pencil)`
103
+ width: ${({ theme }) => theme.spaces[4]};
104
+ height: ${({ theme }) => theme.spaces[4]};
105
+ path {
106
+ fill: ${({ theme }) => theme.colors.neutral600};
107
+ }
108
+ `;
109
+ const TrashIcon = styled(Trash)`
110
+ width: ${({ theme }) => theme.spaces[4]};
111
+ height: ${({ theme }) => theme.spaces[4]};
112
+ path {
113
+ fill: ${({ theme }) => theme.colors.danger600};
114
+ }
115
+ `;
116
+ const PopoverButton = ({ onClick, disabled, children }) => {
117
+ return /* @__PURE__ */ jsx(
118
+ StyledFlex,
119
+ {
120
+ paddingTop: 2,
121
+ paddingBottom: 2,
122
+ paddingLeft: 4,
123
+ paddingRight: 4,
124
+ alignItems: "center",
125
+ gap: 2,
126
+ as: "button",
127
+ hasRadius: true,
128
+ onClick,
129
+ disabled,
130
+ children
131
+ }
132
+ );
133
+ };
134
+ const EntryValidationText = ({ status, action }) => {
135
+ const { formatMessage } = useIntl();
136
+ if (action == "publish") {
137
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
138
+ /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
139
+ status === "published" ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
140
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-published",
141
+ defaultMessage: "Already published"
142
+ }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
143
+ id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-publish",
144
+ defaultMessage: "Ready to publish"
145
+ }) })
146
+ ] });
147
+ }
148
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
149
+ /* @__PURE__ */ jsx(Icon, { color: "success600", as: CheckCircle }),
150
+ status === "draft" ? /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
151
+ id: "content-releases.pages.ReleaseDetails.entry-validation.already-unpublished",
152
+ defaultMessage: "Already unpublished"
153
+ }) }) : /* @__PURE__ */ jsx(Typography, { children: formatMessage({
154
+ id: "content-releases.pages.ReleaseDetails.entry-validation.ready-to-unpublish",
155
+ defaultMessage: "Ready to unpublish"
156
+ }) })
157
+ ] });
158
+ };
159
+ const ReleaseDetailsLayout = ({
160
+ toggleEditReleaseModal,
161
+ toggleWarningSubmit,
162
+ children
163
+ }) => {
164
+ const { formatMessage } = useIntl();
165
+ const { releaseId } = useParams();
166
+ const [isPopoverVisible, setIsPopoverVisible] = React.useState(false);
167
+ const moreButtonRef = React.useRef(null);
168
+ const {
169
+ data,
170
+ isLoading: isLoadingDetails,
171
+ isError,
172
+ error
173
+ } = useGetReleaseQuery({ id: releaseId });
174
+ const [publishRelease, { isLoading: isPublishing }] = usePublishReleaseMutation();
175
+ const toggleNotification = useNotification();
176
+ const { formatAPIError } = useAPIErrorHandler();
177
+ const {
178
+ allowedActions: { canUpdate, canDelete }
179
+ } = useRBAC(PERMISSIONS);
180
+ const release = data?.data;
181
+ const handleTogglePopover = () => {
182
+ setIsPopoverVisible((prev) => !prev);
183
+ };
184
+ const openReleaseModal = () => {
185
+ toggleEditReleaseModal();
186
+ handleTogglePopover();
187
+ };
188
+ const handlePublishRelease = async () => {
189
+ const response = await publishRelease({ id: releaseId });
190
+ if ("data" in response) {
191
+ toggleNotification({
192
+ type: "success",
193
+ message: formatMessage({
194
+ id: "content-releases.pages.ReleaseDetails.publish-notification-success",
195
+ defaultMessage: "Release was published successfully."
196
+ })
197
+ });
198
+ } else if (isAxiosError(response.error)) {
199
+ toggleNotification({
200
+ type: "warning",
201
+ message: formatAPIError(response.error)
202
+ });
203
+ } else {
204
+ toggleNotification({
205
+ type: "warning",
206
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
207
+ });
208
+ }
209
+ };
210
+ const openWarningConfirmDialog = () => {
211
+ toggleWarningSubmit();
212
+ handleTogglePopover();
213
+ };
214
+ if (isLoadingDetails) {
215
+ return /* @__PURE__ */ jsx(Main, { "aria-busy": isLoadingDetails, children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
216
+ }
217
+ if (isError || !release) {
218
+ return /* @__PURE__ */ jsx(
219
+ Redirect,
220
+ {
221
+ to: {
222
+ pathname: "/plugins/content-releases",
223
+ state: {
224
+ errors: [
225
+ {
226
+ code: error?.code
227
+ }
228
+ ]
229
+ }
230
+ }
231
+ }
232
+ );
233
+ }
234
+ const totalEntries = release.actions.meta.count || 0;
235
+ const createdBy = release.createdBy.lastname ? `${release.createdBy.firstname} ${release.createdBy.lastname}` : `${release.createdBy.firstname}`;
236
+ return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoadingDetails, children: [
237
+ /* @__PURE__ */ jsx(
238
+ HeaderLayout,
239
+ {
240
+ title: release.name,
241
+ subtitle: formatMessage(
242
+ {
243
+ id: "content-releases.pages.Details.header-subtitle",
244
+ defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
245
+ },
246
+ { number: totalEntries }
247
+ ),
248
+ navigationAction: /* @__PURE__ */ jsx(Link, { startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}), to: "/plugins/content-releases", children: formatMessage({
249
+ id: "global.back",
250
+ defaultMessage: "Back"
251
+ }) }),
252
+ primaryAction: !release.releasedAt && /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
253
+ /* @__PURE__ */ jsx(
254
+ IconButton,
255
+ {
256
+ label: formatMessage({
257
+ id: "content-releases.header.actions.open-release-actions",
258
+ defaultMessage: "Release actions"
259
+ }),
260
+ ref: moreButtonRef,
261
+ onClick: handleTogglePopover,
262
+ children: /* @__PURE__ */ jsx(More, {})
263
+ }
264
+ ),
265
+ isPopoverVisible && /* @__PURE__ */ jsxs(
266
+ Popover,
267
+ {
268
+ source: moreButtonRef,
269
+ placement: "bottom-end",
270
+ onDismiss: handleTogglePopover,
271
+ spacing: 4,
272
+ minWidth: "242px",
273
+ children: [
274
+ /* @__PURE__ */ jsxs(Flex, { alignItems: "center", justifyContent: "center", direction: "column", padding: 1, children: [
275
+ /* @__PURE__ */ jsxs(PopoverButton, { disabled: !canUpdate, onClick: openReleaseModal, children: [
276
+ /* @__PURE__ */ jsx(PencilIcon, {}),
277
+ /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: formatMessage({
278
+ id: "content-releases.header.actions.edit",
279
+ defaultMessage: "Edit"
280
+ }) })
281
+ ] }),
282
+ /* @__PURE__ */ jsxs(PopoverButton, { disabled: !canDelete, onClick: openWarningConfirmDialog, children: [
283
+ /* @__PURE__ */ jsx(TrashIcon, {}),
284
+ /* @__PURE__ */ jsx(Typography, { ellipsis: true, textColor: "danger600", children: formatMessage({
285
+ id: "content-releases.header.actions.delete",
286
+ defaultMessage: "Delete"
287
+ }) })
288
+ ] })
289
+ ] }),
290
+ /* @__PURE__ */ jsxs(
291
+ ReleaseInfoWrapper,
292
+ {
293
+ direction: "column",
294
+ justifyContent: "center",
295
+ alignItems: "flex-start",
296
+ gap: 1,
297
+ padding: 5,
298
+ children: [
299
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: formatMessage({
300
+ id: "content-releases.header.actions.created",
301
+ defaultMessage: "Created"
302
+ }) }),
303
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", color: "neutral300", children: [
304
+ /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(release.createdAt) }),
305
+ formatMessage(
306
+ {
307
+ id: "content-releases.header.actions.created.description",
308
+ defaultMessage: " by {createdBy}"
309
+ },
310
+ { createdBy }
311
+ )
312
+ ] })
313
+ ]
314
+ }
315
+ )
316
+ ]
317
+ }
318
+ ),
319
+ /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.publish, children: /* @__PURE__ */ jsx(
320
+ Button,
321
+ {
322
+ size: "S",
323
+ variant: "default",
324
+ onClick: handlePublishRelease,
325
+ loading: isPublishing,
326
+ disabled: release.actions.meta.count === 0,
327
+ children: formatMessage({
328
+ id: "content-releases.header.actions.publish",
329
+ defaultMessage: "Publish"
330
+ })
331
+ }
332
+ ) })
333
+ ] })
334
+ }
335
+ ),
336
+ children
337
+ ] });
338
+ };
339
+ const GROUP_BY_OPTIONS = ["contentType", "locale", "action"];
340
+ const getGroupByOptionLabel = (value) => {
341
+ if (value === "locale") {
342
+ return {
343
+ id: "content-releases.pages.ReleaseDetails.groupBy.option.locales",
344
+ defaultMessage: "Locales"
345
+ };
346
+ }
347
+ if (value === "action") {
348
+ return {
349
+ id: "content-releases.pages.ReleaseDetails.groupBy.option.actions",
350
+ defaultMessage: "Actions"
351
+ };
352
+ }
353
+ return {
354
+ id: "content-releases.pages.ReleaseDetails.groupBy.option.content-type",
355
+ defaultMessage: "Content-Types"
356
+ };
357
+ };
358
+ const ReleaseDetailsBody = () => {
359
+ const { formatMessage } = useIntl();
360
+ const { releaseId } = useParams();
361
+ const [{ query }, setQuery] = useQueryParams();
362
+ const toggleNotification = useNotification();
363
+ const { formatAPIError } = useAPIErrorHandler();
364
+ const {
365
+ data: releaseData,
366
+ isLoading: isReleaseLoading,
367
+ isError: isReleaseError,
368
+ error: releaseError
369
+ } = useGetReleaseQuery({ id: releaseId });
370
+ const release = releaseData?.data;
371
+ const selectedGroupBy = query?.groupBy || "contentType";
372
+ const {
373
+ isLoading,
374
+ isFetching,
375
+ isError,
376
+ data,
377
+ error: releaseActionsError
378
+ } = useGetReleaseActionsQuery({
379
+ ...query,
380
+ releaseId
381
+ });
382
+ const [updateReleaseAction] = useUpdateReleaseActionMutation();
383
+ const handleChangeType = async (e, actionId) => {
384
+ const response = await updateReleaseAction({
385
+ params: {
386
+ releaseId,
387
+ actionId
388
+ },
389
+ body: {
390
+ type: e.target.value
391
+ }
392
+ });
393
+ if ("error" in response) {
394
+ if (isAxiosError(response.error)) {
395
+ toggleNotification({
396
+ type: "warning",
397
+ message: formatAPIError(response.error)
398
+ });
399
+ } else {
400
+ toggleNotification({
401
+ type: "warning",
402
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
403
+ });
404
+ }
405
+ }
406
+ };
407
+ if (isLoading || isReleaseLoading) {
408
+ return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) });
409
+ }
410
+ const releaseActions = data?.data;
411
+ const releaseMeta = data?.meta;
412
+ if (isError || isReleaseError || !release || !releaseActions) {
413
+ const errorsArray = [];
414
+ if (releaseError) {
415
+ errorsArray.push({
416
+ code: releaseError.code
417
+ });
418
+ }
419
+ if (releaseActionsError) {
420
+ errorsArray.push({
421
+ code: releaseActionsError.code
422
+ });
423
+ }
424
+ return /* @__PURE__ */ jsx(
425
+ Redirect,
426
+ {
427
+ to: {
428
+ pathname: "/plugins/content-releases",
429
+ state: {
430
+ errors: errorsArray
431
+ }
432
+ }
433
+ }
434
+ );
435
+ }
436
+ if (Object.keys(releaseActions).length === 0) {
437
+ return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(
438
+ NoContent,
439
+ {
440
+ content: {
441
+ id: "content-releases.pages.Details.tab.emptyEntries",
442
+ defaultMessage: "This release is empty. Open the Content Manager, select an entry and add it to the release."
443
+ },
444
+ action: /* @__PURE__ */ jsx(
445
+ LinkButton,
446
+ {
447
+ as: Link$1,
448
+ to: {
449
+ pathname: "/content-manager"
450
+ },
451
+ style: { textDecoration: "none" },
452
+ variant: "secondary",
453
+ children: formatMessage({
454
+ id: "content-releases.page.Details.button.openContentManager",
455
+ defaultMessage: "Open the Content Manager"
456
+ })
457
+ }
458
+ )
459
+ }
460
+ ) });
461
+ }
462
+ return /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Flex, { gap: 8, direction: "column", alignItems: "stretch", children: [
463
+ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
464
+ SingleSelect,
465
+ {
466
+ "aria-label": formatMessage({
467
+ id: "content-releases.pages.ReleaseDetails.groupBy.label",
468
+ defaultMessage: "Group by"
469
+ }),
470
+ customizeContent: (value) => formatMessage(
471
+ {
472
+ id: `content-releases.pages.ReleaseDetails.groupBy.label`,
473
+ defaultMessage: `Group by {groupBy}`
474
+ },
475
+ {
476
+ groupBy: value
477
+ }
478
+ ),
479
+ value: formatMessage(getGroupByOptionLabel(selectedGroupBy)),
480
+ onChange: (value) => setQuery({ groupBy: value }),
481
+ children: GROUP_BY_OPTIONS.map((option) => /* @__PURE__ */ jsx(SingleSelectOption, { value: option, children: formatMessage(getGroupByOptionLabel(option)) }, option))
482
+ }
483
+ ) }),
484
+ Object.keys(releaseActions).map((key) => /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", alignItems: "stretch", children: [
485
+ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(Badge, { children: key }) }),
486
+ /* @__PURE__ */ jsx(
487
+ Table.Root,
488
+ {
489
+ rows: releaseActions[key].map((item) => ({
490
+ ...item,
491
+ id: Number(item.entry.id)
492
+ })),
493
+ colCount: releaseActions[key].length,
494
+ isLoading,
495
+ isFetching,
496
+ children: /* @__PURE__ */ jsxs(Table.Content, { children: [
497
+ /* @__PURE__ */ jsxs(Table.Head, { children: [
498
+ /* @__PURE__ */ jsx(
499
+ Table.HeaderCell,
500
+ {
501
+ fieldSchemaType: "string",
502
+ label: formatMessage({
503
+ id: "content-releases.page.ReleaseDetails.table.header.label.name",
504
+ defaultMessage: "name"
505
+ }),
506
+ name: "name"
507
+ }
508
+ ),
509
+ /* @__PURE__ */ jsx(
510
+ Table.HeaderCell,
511
+ {
512
+ fieldSchemaType: "string",
513
+ label: formatMessage({
514
+ id: "content-releases.page.ReleaseDetails.table.header.label.locale",
515
+ defaultMessage: "locale"
516
+ }),
517
+ name: "locale"
518
+ }
519
+ ),
520
+ /* @__PURE__ */ jsx(
521
+ Table.HeaderCell,
522
+ {
523
+ fieldSchemaType: "string",
524
+ label: formatMessage({
525
+ id: "content-releases.page.ReleaseDetails.table.header.label.content-type",
526
+ defaultMessage: "content-type"
527
+ }),
528
+ name: "content-type"
529
+ }
530
+ ),
531
+ /* @__PURE__ */ jsx(
532
+ Table.HeaderCell,
533
+ {
534
+ fieldSchemaType: "string",
535
+ label: formatMessage({
536
+ id: "content-releases.page.ReleaseDetails.table.header.label.action",
537
+ defaultMessage: "action"
538
+ }),
539
+ name: "action"
540
+ }
541
+ ),
542
+ !release.releasedAt && /* @__PURE__ */ jsx(
543
+ Table.HeaderCell,
544
+ {
545
+ fieldSchemaType: "string",
546
+ label: formatMessage({
547
+ id: "content-releases.page.ReleaseDetails.table.header.label.status",
548
+ defaultMessage: "status"
549
+ }),
550
+ name: "status"
551
+ }
552
+ )
553
+ ] }),
554
+ /* @__PURE__ */ jsx(Table.LoadingBody, {}),
555
+ /* @__PURE__ */ jsx(Table.Body, { children: releaseActions[key].map(({ id, type, entry }) => /* @__PURE__ */ jsxs(Tr, { children: [
556
+ /* @__PURE__ */ jsx(Td, { width: "25%", children: /* @__PURE__ */ jsx(Typography, { ellipsis: true, children: `${entry.contentType.mainFieldValue || entry.id}` }) }),
557
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: `${entry?.locale?.name ? entry.locale.name : "-"}` }) }),
558
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: entry.contentType.displayName || "" }) }),
559
+ /* @__PURE__ */ jsx(Td, { children: release.releasedAt ? /* @__PURE__ */ jsx(Typography, { children: formatMessage(
560
+ {
561
+ id: "content-releases.page.ReleaseDetails.table.action-published",
562
+ defaultMessage: "This entry was <b>{isPublish, select, true {published} other {unpublished}}</b>."
563
+ },
564
+ {
565
+ isPublish: type === "publish",
566
+ b: (children) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children })
567
+ }
568
+ ) }) : /* @__PURE__ */ jsx(
569
+ ReleaseActionOptions,
570
+ {
571
+ selected: type,
572
+ handleChange: (e) => handleChangeType(e, id),
573
+ name: `release-action-${id}-type`
574
+ }
575
+ ) }),
576
+ !release.releasedAt && /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(EntryValidationText, { status: entry.status, action: type }) }),
577
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(ReleaseActionMenu, { releaseId, actionId: id }) }) })
578
+ ] }, id)) })
579
+ ] })
580
+ }
581
+ )
582
+ ] }, `releases-group-${key}`)),
583
+ /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
584
+ /* @__PURE__ */ jsx(PageSizeURLQuery, { defaultValue: releaseMeta?.pagination?.pageSize.toString() }),
585
+ /* @__PURE__ */ jsx(
586
+ PaginationURLQuery,
587
+ {
588
+ pagination: {
589
+ pageCount: releaseMeta?.pagination?.pageCount || 0
590
+ }
591
+ }
592
+ )
593
+ ] })
594
+ ] }) });
595
+ };
596
+ const ReleaseDetailsPage = () => {
597
+ const { formatMessage } = useIntl();
598
+ const { releaseId } = useParams();
599
+ const toggleNotification = useNotification();
600
+ const { formatAPIError } = useAPIErrorHandler();
601
+ const { push } = useHistory();
602
+ const [releaseModalShown, setReleaseModalShown] = React.useState(false);
603
+ const [showWarningSubmit, setWarningSubmit] = React.useState(false);
604
+ const {
605
+ isLoading: isLoadingDetails,
606
+ data,
607
+ isSuccess: isSuccessDetails
608
+ } = useGetReleaseQuery({ id: releaseId });
609
+ const [updateRelease, { isLoading: isSubmittingForm }] = useUpdateReleaseMutation();
610
+ const [deleteRelease, { isLoading: isDeletingRelease }] = useDeleteReleaseMutation();
611
+ const toggleEditReleaseModal = () => {
612
+ setReleaseModalShown((prev) => !prev);
613
+ };
614
+ const toggleWarningSubmit = () => setWarningSubmit((prevState) => !prevState);
615
+ if (isLoadingDetails) {
616
+ return /* @__PURE__ */ jsx(
617
+ ReleaseDetailsLayout,
618
+ {
619
+ toggleEditReleaseModal,
620
+ toggleWarningSubmit,
621
+ children: /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) })
622
+ }
623
+ );
624
+ }
625
+ const title = isSuccessDetails && data?.data?.name || "";
626
+ const handleEditRelease = async (values) => {
627
+ const response = await updateRelease({
628
+ id: releaseId,
629
+ name: values.name
630
+ });
631
+ if ("data" in response) {
632
+ toggleNotification({
633
+ type: "success",
634
+ message: formatMessage({
635
+ id: "content-releases.modal.release-updated-notification-success",
636
+ defaultMessage: "Release updated."
637
+ })
638
+ });
639
+ } else if (isAxiosError(response.error)) {
640
+ toggleNotification({
641
+ type: "warning",
642
+ message: formatAPIError(response.error)
643
+ });
644
+ } else {
645
+ toggleNotification({
646
+ type: "warning",
647
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
648
+ });
649
+ }
650
+ toggleEditReleaseModal();
651
+ };
652
+ const handleDeleteRelease = async () => {
653
+ const response = await deleteRelease({
654
+ id: releaseId
655
+ });
656
+ if ("data" in response) {
657
+ push("/plugins/content-releases");
658
+ } else if (isAxiosError(response.error)) {
659
+ toggleNotification({
660
+ type: "warning",
661
+ message: formatAPIError(response.error)
662
+ });
663
+ } else {
664
+ toggleNotification({
665
+ type: "warning",
666
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
667
+ });
668
+ }
669
+ };
670
+ return /* @__PURE__ */ jsxs(
671
+ ReleaseDetailsLayout,
672
+ {
673
+ toggleEditReleaseModal,
674
+ toggleWarningSubmit,
675
+ children: [
676
+ /* @__PURE__ */ jsx(ReleaseDetailsBody, {}),
677
+ releaseModalShown && /* @__PURE__ */ jsx(
678
+ ReleaseModal,
679
+ {
680
+ handleClose: toggleEditReleaseModal,
681
+ handleSubmit: handleEditRelease,
682
+ isLoading: isLoadingDetails || isSubmittingForm,
683
+ initialValues: { name: title || "" }
684
+ }
685
+ ),
686
+ /* @__PURE__ */ jsx(
687
+ ConfirmDialog,
688
+ {
689
+ bodyText: {
690
+ id: "content-releases.dialog.confirmation-message",
691
+ defaultMessage: "Are you sure you want to delete this release?"
692
+ },
693
+ isOpen: showWarningSubmit,
694
+ isConfirmButtonLoading: isDeletingRelease,
695
+ onToggleDialog: toggleWarningSubmit,
696
+ onConfirm: handleDeleteRelease
697
+ }
698
+ )
699
+ ]
700
+ }
701
+ );
702
+ };
703
+ const ReleasesLayout = ({
704
+ isLoading,
705
+ totalReleases,
706
+ onClickAddRelease,
707
+ children
708
+ }) => {
709
+ const { formatMessage } = useIntl();
710
+ return /* @__PURE__ */ jsxs(Main, { "aria-busy": isLoading, children: [
711
+ /* @__PURE__ */ jsx(
712
+ HeaderLayout,
713
+ {
714
+ title: formatMessage({
715
+ id: "content-releases.pages.Releases.title",
716
+ defaultMessage: "Releases"
717
+ }),
718
+ subtitle: !isLoading && formatMessage(
719
+ {
720
+ id: "content-releases.pages.Releases.header-subtitle",
721
+ defaultMessage: "{number, plural, =0 {No releases} one {# release} other {# releases}}"
722
+ },
723
+ { number: totalReleases }
724
+ ),
725
+ primaryAction: /* @__PURE__ */ jsx(CheckPermissions, { permissions: PERMISSIONS.create, children: /* @__PURE__ */ jsx(Button, { startIcon: /* @__PURE__ */ jsx(Plus, {}), onClick: onClickAddRelease, children: formatMessage({
726
+ id: "content-releases.header.actions.add-release",
727
+ defaultMessage: "New release"
728
+ }) }) })
729
+ }
730
+ ),
731
+ children
732
+ ] });
733
+ };
734
+ const LinkCard = styled(Link$2)`
735
+ display: block;
736
+ `;
737
+ const ReleasesGrid = ({ sectionTitle, releases = [], isError = false }) => {
738
+ const { formatMessage } = useIntl();
739
+ if (isError) {
740
+ return /* @__PURE__ */ jsx(AnErrorOccurred, {});
741
+ }
742
+ if (releases?.length === 0) {
743
+ return /* @__PURE__ */ jsx(
744
+ EmptyStateLayout,
745
+ {
746
+ content: formatMessage(
747
+ {
748
+ id: "content-releases.page.Releases.tab.emptyEntries",
749
+ defaultMessage: "No releases"
750
+ },
751
+ {
752
+ target: sectionTitle
753
+ }
754
+ ),
755
+ icon: /* @__PURE__ */ jsx(EmptyDocuments, { width: "10rem" })
756
+ }
757
+ );
758
+ }
759
+ return /* @__PURE__ */ jsx(Grid, { gap: 4, children: releases.map(({ id, name, actions }) => /* @__PURE__ */ jsx(GridItem, { col: 3, s: 6, xs: 12, children: /* @__PURE__ */ jsx(LinkCard, { href: `content-releases/${id}`, isExternal: false, children: /* @__PURE__ */ jsxs(
760
+ Flex,
761
+ {
762
+ direction: "column",
763
+ justifyContent: "space-between",
764
+ padding: 4,
765
+ hasRadius: true,
766
+ background: "neutral0",
767
+ shadow: "tableShadow",
768
+ height: "100%",
769
+ width: "100%",
770
+ alignItems: "start",
771
+ gap: 2,
772
+ children: [
773
+ /* @__PURE__ */ jsx(Typography, { as: "h3", variant: "delta", fontWeight: "bold", children: name }),
774
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", children: formatMessage(
775
+ {
776
+ id: "content-releases.page.Releases.release-item.entries",
777
+ defaultMessage: "{number, plural, =0 {No entries} one {# entry} other {# entries}}"
778
+ },
779
+ { number: actions.meta.count }
780
+ ) })
781
+ ]
782
+ }
783
+ ) }) }, id)) });
784
+ };
785
+ const INITIAL_FORM_VALUES = {
786
+ name: ""
787
+ };
788
+ const ReleasesPage = () => {
789
+ const location = useLocation();
790
+ const [releaseModalShown, setReleaseModalShown] = React.useState(false);
791
+ const toggleNotification = useNotification();
792
+ const { formatMessage } = useIntl();
793
+ const { push, replace } = useHistory();
794
+ const { formatAPIError } = useAPIErrorHandler();
795
+ const [{ query }, setQuery] = useQueryParams();
796
+ const response = useGetReleasesQuery(query);
797
+ const [createRelease, { isLoading: isSubmittingForm }] = useCreateReleaseMutation();
798
+ const { isLoading, isSuccess, isError } = response;
799
+ React.useEffect(() => {
800
+ if (location?.state?.errors) {
801
+ toggleNotification({
802
+ type: "warning",
803
+ title: formatMessage({
804
+ id: "content-releases.pages.Releases.notification.error.title",
805
+ defaultMessage: "Your request could not be processed."
806
+ }),
807
+ message: formatMessage({
808
+ id: "content-releases.pages.Releases.notification.error.message",
809
+ defaultMessage: "Please try again or open another release."
810
+ })
811
+ });
812
+ replace({ state: null });
813
+ }
814
+ }, [formatMessage, location?.state?.errors, replace, toggleNotification]);
815
+ const toggleAddReleaseModal = () => {
816
+ setReleaseModalShown((prev) => !prev);
817
+ };
818
+ if (isLoading) {
819
+ return /* @__PURE__ */ jsx(ReleasesLayout, { onClickAddRelease: toggleAddReleaseModal, isLoading: true, children: /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsx(LoadingIndicatorPage, {}) }) });
820
+ }
821
+ const totalReleases = isSuccess && response.currentData?.meta?.pagination?.total || 0;
822
+ const handleTabChange = (index) => {
823
+ setQuery({
824
+ ...query,
825
+ page: 1,
826
+ pageSize: response?.currentData?.meta?.pagination?.pageSize || 16,
827
+ filters: {
828
+ releasedAt: {
829
+ $notNull: index === 0 ? false : true
830
+ }
831
+ }
832
+ });
833
+ };
834
+ const activeTab = response?.currentData?.meta?.activeTab || "pending";
835
+ const handleAddRelease = async (values) => {
836
+ const response2 = await createRelease({
837
+ name: values.name
838
+ });
839
+ if ("data" in response2) {
840
+ toggleNotification({
841
+ type: "success",
842
+ message: formatMessage({
843
+ id: "content-releases.modal.release-created-notification-success",
844
+ defaultMessage: "Release created."
845
+ })
846
+ });
847
+ push(`/plugins/content-releases/${response2.data.data.id}`);
848
+ } else if (isAxiosError(response2.error)) {
849
+ toggleNotification({
850
+ type: "warning",
851
+ message: formatAPIError(response2.error)
852
+ });
853
+ } else {
854
+ toggleNotification({
855
+ type: "warning",
856
+ message: formatMessage({ id: "notification.error", defaultMessage: "An error occurred" })
857
+ });
858
+ }
859
+ };
860
+ return /* @__PURE__ */ jsxs(ReleasesLayout, { onClickAddRelease: toggleAddReleaseModal, totalReleases, children: [
861
+ /* @__PURE__ */ jsx(ContentLayout, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
862
+ /* @__PURE__ */ jsxs(
863
+ TabGroup,
864
+ {
865
+ label: formatMessage({
866
+ id: "content-releases.pages.Releases.tab-group.label",
867
+ defaultMessage: "Releases list"
868
+ }),
869
+ variant: "simple",
870
+ initialSelectedTabIndex: ["pending", "done"].indexOf(activeTab),
871
+ onTabChange: handleTabChange,
872
+ children: [
873
+ /* @__PURE__ */ jsxs(Box, { paddingBottom: 8, children: [
874
+ /* @__PURE__ */ jsxs(Tabs, { children: [
875
+ /* @__PURE__ */ jsx(Tab, { children: formatMessage({
876
+ id: "content-releases.pages.Releases.tab.pending",
877
+ defaultMessage: "Pending"
878
+ }) }),
879
+ /* @__PURE__ */ jsx(Tab, { children: formatMessage({
880
+ id: "content-releases.pages.Releases.tab.done",
881
+ defaultMessage: "Done"
882
+ }) })
883
+ ] }),
884
+ /* @__PURE__ */ jsx(Divider, {})
885
+ ] }),
886
+ /* @__PURE__ */ jsxs(TabPanels, { children: [
887
+ /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
888
+ ReleasesGrid,
889
+ {
890
+ sectionTitle: "pending",
891
+ releases: response?.currentData?.data,
892
+ isError
893
+ }
894
+ ) }),
895
+ /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(
896
+ ReleasesGrid,
897
+ {
898
+ sectionTitle: "done",
899
+ releases: response?.currentData?.data,
900
+ isError
901
+ }
902
+ ) })
903
+ ] })
904
+ ]
905
+ }
906
+ ),
907
+ totalReleases > 0 && /* @__PURE__ */ jsxs(Flex, { paddingTop: 4, alignItems: "flex-end", justifyContent: "space-between", children: [
908
+ /* @__PURE__ */ jsx(
909
+ PageSizeURLQuery,
910
+ {
911
+ options: ["8", "16", "32", "64"],
912
+ defaultValue: response?.currentData?.meta?.pagination?.pageSize.toString()
913
+ }
914
+ ),
915
+ /* @__PURE__ */ jsx(
916
+ PaginationURLQuery,
917
+ {
918
+ pagination: {
919
+ pageCount: response?.currentData?.meta?.pagination?.pageCount || 0
920
+ }
921
+ }
922
+ )
923
+ ] })
924
+ ] }) }),
925
+ releaseModalShown && /* @__PURE__ */ jsx(
926
+ ReleaseModal,
927
+ {
928
+ handleClose: toggleAddReleaseModal,
929
+ handleSubmit: handleAddRelease,
930
+ isLoading: isSubmittingForm,
931
+ initialValues: INITIAL_FORM_VALUES
932
+ }
933
+ )
934
+ ] });
935
+ };
936
+ const App = () => {
937
+ return /* @__PURE__ */ jsx(CheckPagePermissions, { permissions: PERMISSIONS.main, children: /* @__PURE__ */ jsxs(Switch, { children: [
938
+ /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}`, component: ReleasesPage }),
939
+ /* @__PURE__ */ jsx(Route, { exact: true, path: `/plugins/${pluginId}/:releaseId`, component: ReleaseDetailsPage })
940
+ ] }) });
941
+ };
942
+ export {
943
+ App
944
+ };
945
+ //# sourceMappingURL=App-c3fca40f.mjs.map