@backstage-community/plugin-announcements 0.1.1
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/CHANGELOG.md +10 -0
- package/README.md +142 -0
- package/dist/alpha/apis.esm.js +26 -0
- package/dist/alpha/apis.esm.js.map +1 -0
- package/dist/alpha/entityCards.esm.js +16 -0
- package/dist/alpha/entityCards.esm.js.map +1 -0
- package/dist/alpha/navItems.esm.js +15 -0
- package/dist/alpha/navItems.esm.js.map +1 -0
- package/dist/alpha/pages.esm.js +18 -0
- package/dist/alpha/pages.esm.js.map +1 -0
- package/dist/alpha.d.ts +11 -0
- package/dist/alpha.esm.js +23 -0
- package/dist/alpha.esm.js.map +1 -0
- package/dist/api.esm.js +117 -0
- package/dist/api.esm.js.map +1 -0
- package/dist/components/Admin/AdminPortal/AdminPortal.esm.js +51 -0
- package/dist/components/Admin/AdminPortal/AdminPortal.esm.js.map +1 -0
- package/dist/components/Admin/AnnouncementsContent/AnnouncementsContent.esm.js +199 -0
- package/dist/components/Admin/AnnouncementsContent/AnnouncementsContent.esm.js.map +1 -0
- package/dist/components/Admin/CategoriesContent/CategoriesContent.esm.js +130 -0
- package/dist/components/Admin/CategoriesContent/CategoriesContent.esm.js.map +1 -0
- package/dist/components/Admin/index.esm.js +3 -0
- package/dist/components/Admin/index.esm.js.map +1 -0
- package/dist/components/AnnouncementForm/AnnouncementForm.esm.js +123 -0
- package/dist/components/AnnouncementForm/AnnouncementForm.esm.js.map +1 -0
- package/dist/components/AnnouncementForm/CategoryInput.esm.js +79 -0
- package/dist/components/AnnouncementForm/CategoryInput.esm.js.map +1 -0
- package/dist/components/AnnouncementPage/AnnouncementPage.esm.js +59 -0
- package/dist/components/AnnouncementPage/AnnouncementPage.esm.js.map +1 -0
- package/dist/components/AnnouncementSearchResultListItem/AnnouncementSearchResultListItem.esm.js +67 -0
- package/dist/components/AnnouncementSearchResultListItem/AnnouncementSearchResultListItem.esm.js.map +1 -0
- package/dist/components/AnnouncementSearchResultListItem/index.esm.js +2 -0
- package/dist/components/AnnouncementSearchResultListItem/index.esm.js.map +1 -0
- package/dist/components/AnnouncementsCard/AnnouncementsCard.esm.js +81 -0
- package/dist/components/AnnouncementsCard/AnnouncementsCard.esm.js.map +1 -0
- package/dist/components/AnnouncementsCard/index.esm.js +2 -0
- package/dist/components/AnnouncementsCard/index.esm.js.map +1 -0
- package/dist/components/AnnouncementsPage/AnnouncementsPage.esm.js +233 -0
- package/dist/components/AnnouncementsPage/AnnouncementsPage.esm.js.map +1 -0
- package/dist/components/AnnouncementsPage/ContextMenu.esm.js +59 -0
- package/dist/components/AnnouncementsPage/ContextMenu.esm.js.map +1 -0
- package/dist/components/AnnouncementsPage/DeleteAnnouncementDialog.esm.js +25 -0
- package/dist/components/AnnouncementsPage/DeleteAnnouncementDialog.esm.js.map +1 -0
- package/dist/components/AnnouncementsPage/useDeleteAnnouncementDialogState.esm.js +29 -0
- package/dist/components/AnnouncementsPage/useDeleteAnnouncementDialogState.esm.js.map +1 -0
- package/dist/components/AnnouncementsTimeline/AnnouncementsTimeline.esm.js +55 -0
- package/dist/components/AnnouncementsTimeline/AnnouncementsTimeline.esm.js.map +1 -0
- package/dist/components/CategoriesForm/CategoriesForm.esm.js +71 -0
- package/dist/components/CategoriesForm/CategoriesForm.esm.js.map +1 -0
- package/dist/components/CategoriesPage/CategoriesPage.esm.js +113 -0
- package/dist/components/CategoriesPage/CategoriesPage.esm.js.map +1 -0
- package/dist/components/CategoriesPage/DeleteCategoryDialog.esm.js +10 -0
- package/dist/components/CategoriesPage/DeleteCategoryDialog.esm.js.map +1 -0
- package/dist/components/CategoriesPage/useDeleteCategoryDialogState.esm.js +29 -0
- package/dist/components/CategoriesPage/useDeleteCategoryDialogState.esm.js.map +1 -0
- package/dist/components/CreateAnnouncementPage/CreateAnnouncementPage.esm.js +56 -0
- package/dist/components/CreateAnnouncementPage/CreateAnnouncementPage.esm.js.map +1 -0
- package/dist/components/EditAnnouncementPage/EditAnnouncementPage.esm.js +45 -0
- package/dist/components/EditAnnouncementPage/EditAnnouncementPage.esm.js.map +1 -0
- package/dist/components/NewAnnouncementBanner/NewAnnouncementBanner.esm.js +136 -0
- package/dist/components/NewAnnouncementBanner/NewAnnouncementBanner.esm.js.map +1 -0
- package/dist/components/NewAnnouncementBanner/index.esm.js +2 -0
- package/dist/components/NewAnnouncementBanner/index.esm.js.map +1 -0
- package/dist/components/NewCategoryDialog/NewCategoryDialog.esm.js +46 -0
- package/dist/components/NewCategoryDialog/NewCategoryDialog.esm.js.map +1 -0
- package/dist/components/Router.esm.js +64 -0
- package/dist/components/Router.esm.js.map +1 -0
- package/dist/components/index.esm.js +4 -0
- package/dist/components/index.esm.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.esm.js +7 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/plugin.esm.js +83 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/routes.esm.js +33 -0
- package/dist/routes.esm.js.map +1 -0
- package/package.json +113 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import useAsync from 'react-use/lib/useAsync';
|
|
3
|
+
import { DateTime } from 'luxon';
|
|
4
|
+
import { Page, Header, Content, Progress, Link, InfoCard, MarkdownContent } from '@backstage/core-components';
|
|
5
|
+
import { useApi, useRouteRefParams, useRouteRef } from '@backstage/core-plugin-api';
|
|
6
|
+
import { parseEntityRef } from '@backstage/catalog-model';
|
|
7
|
+
import { entityRouteRef, EntityPeekAheadPopover, EntityDisplayName } from '@backstage/plugin-catalog-react';
|
|
8
|
+
import { announcementViewRouteRef, rootRouteRef } from '../../routes.esm.js';
|
|
9
|
+
import { announcementsApiRef } from '@backstage-community/plugin-announcements-react';
|
|
10
|
+
import { Grid } from '@material-ui/core';
|
|
11
|
+
import { Alert } from '@material-ui/lab';
|
|
12
|
+
|
|
13
|
+
const AnnouncementDetails = ({
|
|
14
|
+
announcement
|
|
15
|
+
}) => {
|
|
16
|
+
const announcementsLink = useRouteRef(rootRouteRef);
|
|
17
|
+
const entityLink = useRouteRef(entityRouteRef);
|
|
18
|
+
const deepLink = {
|
|
19
|
+
link: announcementsLink(),
|
|
20
|
+
title: "Back to announcements"
|
|
21
|
+
};
|
|
22
|
+
const publisherRef = parseEntityRef(announcement.publisher);
|
|
23
|
+
const subHeader = /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, "By", " ", /* @__PURE__ */ React__default.createElement(EntityPeekAheadPopover, { entityRef: announcement.publisher }, /* @__PURE__ */ React__default.createElement(Link, { to: entityLink(publisherRef) }, /* @__PURE__ */ React__default.createElement(EntityDisplayName, { entityRef: announcement.publisher, hideIcon: true }))), ", ", DateTime.fromISO(announcement.created_at).toRelative());
|
|
24
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
25
|
+
InfoCard,
|
|
26
|
+
{
|
|
27
|
+
title: announcement.title,
|
|
28
|
+
subheader: subHeader,
|
|
29
|
+
deepLink
|
|
30
|
+
},
|
|
31
|
+
/* @__PURE__ */ React__default.createElement(MarkdownContent, { content: announcement.body })
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
const AnnouncementPage = (props) => {
|
|
35
|
+
const announcementsApi = useApi(announcementsApiRef);
|
|
36
|
+
const { id } = useRouteRefParams(announcementViewRouteRef);
|
|
37
|
+
const { value, loading, error } = useAsync(
|
|
38
|
+
async () => announcementsApi.announcementByID(id)
|
|
39
|
+
);
|
|
40
|
+
let title = props.title;
|
|
41
|
+
let content;
|
|
42
|
+
if (loading) {
|
|
43
|
+
content = /* @__PURE__ */ React__default.createElement(Progress, null);
|
|
44
|
+
} else if (error) {
|
|
45
|
+
content = /* @__PURE__ */ React__default.createElement(Alert, { severity: "error" }, error.message);
|
|
46
|
+
} else {
|
|
47
|
+
title = `${value.title} \u2013 ${title}`;
|
|
48
|
+
content = /* @__PURE__ */ React__default.createElement(AnnouncementDetails, { announcement: value });
|
|
49
|
+
const lastSeen = announcementsApi.lastSeenDate();
|
|
50
|
+
const announcementCreatedAt = DateTime.fromISO(value.created_at);
|
|
51
|
+
if (announcementCreatedAt > lastSeen) {
|
|
52
|
+
announcementsApi.markLastSeenDate(announcementCreatedAt);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return /* @__PURE__ */ React__default.createElement(Page, { themeId: props.themeId }, /* @__PURE__ */ React__default.createElement(Header, { title, subtitle: props.subtitle }), /* @__PURE__ */ React__default.createElement(Content, null, /* @__PURE__ */ React__default.createElement(Grid, { container: true, justifyContent: "center", alignItems: "center" }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, sm: 6 }, content))));
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export { AnnouncementPage };
|
|
59
|
+
//# sourceMappingURL=AnnouncementPage.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnnouncementPage.esm.js","sources":["../../../src/components/AnnouncementPage/AnnouncementPage.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { ReactNode } from 'react';\nimport useAsync from 'react-use/lib/useAsync';\nimport { DateTime } from 'luxon';\nimport {\n Progress,\n Page,\n Header,\n Content,\n MarkdownContent,\n InfoCard,\n Link,\n} from '@backstage/core-components';\nimport {\n useApi,\n useRouteRef,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport {\n EntityDisplayName,\n EntityPeekAheadPopover,\n entityRouteRef,\n} from '@backstage/plugin-catalog-react';\nimport { announcementViewRouteRef, rootRouteRef } from '../../routes';\nimport { announcementsApiRef } from '@backstage-community/plugin-announcements-react';\nimport { Announcement } from '@backstage-community/plugin-announcements-common';\nimport { Grid } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\n\nconst AnnouncementDetails = ({\n announcement,\n}: {\n announcement: Announcement;\n}) => {\n const announcementsLink = useRouteRef(rootRouteRef);\n const entityLink = useRouteRef(entityRouteRef);\n const deepLink = {\n link: announcementsLink(),\n title: 'Back to announcements',\n };\n\n const publisherRef = parseEntityRef(announcement.publisher);\n const subHeader = (\n <>\n By{' '}\n <EntityPeekAheadPopover entityRef={announcement.publisher}>\n <Link to={entityLink(publisherRef)}>\n <EntityDisplayName entityRef={announcement.publisher} hideIcon />\n </Link>\n </EntityPeekAheadPopover>\n , {DateTime.fromISO(announcement.created_at).toRelative()}\n </>\n );\n\n return (\n <InfoCard\n title={announcement.title}\n subheader={subHeader}\n deepLink={deepLink}\n >\n <MarkdownContent content={announcement.body} />\n </InfoCard>\n );\n};\n\ntype AnnouncementPageProps = {\n themeId: string;\n title: string;\n subtitle?: ReactNode;\n};\n\nexport const AnnouncementPage = (props: AnnouncementPageProps) => {\n const announcementsApi = useApi(announcementsApiRef);\n const { id } = useRouteRefParams(announcementViewRouteRef);\n const { value, loading, error } = useAsync(async () =>\n announcementsApi.announcementByID(id),\n );\n\n let title = props.title;\n let content: React.ReactNode;\n\n if (loading) {\n content = <Progress />;\n } else if (error) {\n content = <Alert severity=\"error\">{error.message}</Alert>;\n } else {\n title = `${value!.title} – ${title}`;\n content = <AnnouncementDetails announcement={value!} />;\n\n const lastSeen = announcementsApi.lastSeenDate();\n const announcementCreatedAt = DateTime.fromISO(value!.created_at);\n\n if (announcementCreatedAt > lastSeen) {\n announcementsApi.markLastSeenDate(announcementCreatedAt);\n }\n }\n\n return (\n <Page themeId={props.themeId}>\n <Header title={title} subtitle={props.subtitle} />\n\n <Content>\n <Grid container justifyContent=\"center\" alignItems=\"center\">\n <Grid item sm={6}>\n {content}\n </Grid>\n </Grid>\n </Content>\n </Page>\n );\n};\n"],"names":["React"],"mappings":"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"}
|
package/dist/components/AnnouncementSearchResultListItem/AnnouncementSearchResultListItem.esm.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { DateTime } from 'luxon';
|
|
3
|
+
import { Link } from '@backstage/core-components';
|
|
4
|
+
import { HighlightedSearchResultText } from '@backstage/plugin-search-react';
|
|
5
|
+
import { useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';
|
|
6
|
+
import { makeStyles, Typography, ListItem, ListItemIcon, ListItemText, Divider } from '@material-ui/core';
|
|
7
|
+
import RecordVoiceOverIcon from '@material-ui/icons/RecordVoiceOver';
|
|
8
|
+
|
|
9
|
+
const useStyles = makeStyles({
|
|
10
|
+
createdAt: {
|
|
11
|
+
display: "block",
|
|
12
|
+
marginTop: "0.2rem",
|
|
13
|
+
marginBottom: "0.8rem",
|
|
14
|
+
fontSize: "0.8rem"
|
|
15
|
+
},
|
|
16
|
+
excerpt: {
|
|
17
|
+
lineHeight: "1.55"
|
|
18
|
+
},
|
|
19
|
+
itemText: {
|
|
20
|
+
wordBreak: "break-all"
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
const AnnouncementSearchResultListItem = ({
|
|
24
|
+
result,
|
|
25
|
+
highlight
|
|
26
|
+
}) => {
|
|
27
|
+
const classes = useStyles();
|
|
28
|
+
const { t } = useAnnouncementsTranslation();
|
|
29
|
+
if (!result) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const document = result;
|
|
33
|
+
const title = /* @__PURE__ */ React__default.createElement(Link, { noTrack: true, to: result.location }, highlight?.fields.title ? /* @__PURE__ */ React__default.createElement(
|
|
34
|
+
HighlightedSearchResultText,
|
|
35
|
+
{
|
|
36
|
+
text: highlight.fields.title,
|
|
37
|
+
preTag: highlight.preTag,
|
|
38
|
+
postTag: highlight.postTag
|
|
39
|
+
}
|
|
40
|
+
) : result.title);
|
|
41
|
+
const excerpt = /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(Typography, { component: "span", className: classes.createdAt }, `${t("announcementSearchResultListItem.published")} `, /* @__PURE__ */ React__default.createElement(Typography, { component: "span", title: document.createdAt }, DateTime.fromISO(document.createdAt).toRelative())), /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, highlight?.fields.text ? /* @__PURE__ */ React__default.createElement(
|
|
42
|
+
HighlightedSearchResultText,
|
|
43
|
+
{
|
|
44
|
+
text: highlight.fields.text,
|
|
45
|
+
preTag: highlight.preTag,
|
|
46
|
+
postTag: highlight.postTag
|
|
47
|
+
}
|
|
48
|
+
) : result.text));
|
|
49
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(ListItem, { alignItems: "center" }, /* @__PURE__ */ React__default.createElement(
|
|
50
|
+
ListItemIcon,
|
|
51
|
+
{
|
|
52
|
+
title: t("announcementSearchResultListItem.announcement")
|
|
53
|
+
},
|
|
54
|
+
/* @__PURE__ */ React__default.createElement(RecordVoiceOverIcon, null)
|
|
55
|
+
), /* @__PURE__ */ React__default.createElement(
|
|
56
|
+
ListItemText,
|
|
57
|
+
{
|
|
58
|
+
primary: title,
|
|
59
|
+
secondary: excerpt,
|
|
60
|
+
className: classes.itemText,
|
|
61
|
+
primaryTypographyProps: { variant: "h6" }
|
|
62
|
+
}
|
|
63
|
+
)), /* @__PURE__ */ React__default.createElement(Divider, { component: "li" }));
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export { AnnouncementSearchResultListItem };
|
|
67
|
+
//# sourceMappingURL=AnnouncementSearchResultListItem.esm.js.map
|
package/dist/components/AnnouncementSearchResultListItem/AnnouncementSearchResultListItem.esm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnnouncementSearchResultListItem.esm.js","sources":["../../../src/components/AnnouncementSearchResultListItem/AnnouncementSearchResultListItem.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\nimport { DateTime } from 'luxon';\nimport { Link } from '@backstage/core-components';\nimport {\n IndexableDocument,\n ResultHighlight,\n} from '@backstage/plugin-search-common';\nimport { HighlightedSearchResultText } from '@backstage/plugin-search-react';\nimport { useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';\nimport {\n makeStyles,\n ListItem,\n ListItemIcon,\n ListItemText,\n Divider,\n Typography,\n} from '@material-ui/core';\nimport RecordVoiceOverIcon from '@material-ui/icons/RecordVoiceOver';\n\nconst useStyles = makeStyles({\n createdAt: {\n display: 'block',\n marginTop: '0.2rem',\n marginBottom: '0.8rem',\n fontSize: '0.8rem',\n },\n excerpt: {\n lineHeight: '1.55',\n },\n itemText: {\n wordBreak: 'break-all',\n },\n});\n\ntype IndexableAnnouncement = IndexableDocument & {\n createdAt: string;\n};\n\nexport interface AnnouncementSearchResultProps {\n result?: IndexableDocument;\n highlight?: ResultHighlight;\n rank?: number;\n}\n\nexport const AnnouncementSearchResultListItem = ({\n result,\n highlight,\n}: AnnouncementSearchResultProps) => {\n const classes = useStyles();\n const { t } = useAnnouncementsTranslation();\n\n if (!result) {\n return null;\n }\n\n const document = result as IndexableAnnouncement;\n\n const title = (\n <Link noTrack to={result.location}>\n {highlight?.fields.title ? (\n <HighlightedSearchResultText\n text={highlight.fields.title}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.title\n )}\n </Link>\n );\n\n const excerpt = (\n <>\n <Typography component=\"span\" className={classes.createdAt}>\n {`${t('announcementSearchResultListItem.published')} `}\n <Typography component=\"span\" title={document.createdAt}>\n {DateTime.fromISO(document.createdAt).toRelative()}\n </Typography>\n </Typography>\n <>\n {highlight?.fields.text ? (\n <HighlightedSearchResultText\n text={highlight.fields.text}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.text\n )}\n </>\n </>\n );\n\n return (\n <>\n <ListItem alignItems=\"center\">\n <ListItemIcon\n title={t('announcementSearchResultListItem.announcement')}\n >\n <RecordVoiceOverIcon />\n </ListItemIcon>\n <ListItemText\n primary={title}\n secondary={excerpt}\n className={classes.itemText}\n primaryTypographyProps={{ variant: 'h6' }}\n />\n </ListItem>\n\n <Divider component=\"li\" />\n </>\n );\n};\n"],"names":["React"],"mappings":";;;;;;;;AAkCA,MAAM,YAAY,UAAW,CAAA;AAAA,EAC3B,SAAW,EAAA;AAAA,IACT,OAAS,EAAA,OAAA;AAAA,IACT,SAAW,EAAA,QAAA;AAAA,IACX,YAAc,EAAA,QAAA;AAAA,IACd,QAAU,EAAA;AAAA,GACZ;AAAA,EACA,OAAS,EAAA;AAAA,IACP,UAAY,EAAA;AAAA,GACd;AAAA,EACA,QAAU,EAAA;AAAA,IACR,SAAW,EAAA;AAAA;AAEf,CAAC,CAAA;AAYM,MAAM,mCAAmC,CAAC;AAAA,EAC/C,MAAA;AAAA,EACA;AACF,CAAqC,KAAA;AACnC,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,2BAA4B,EAAA;AAE1C,EAAA,IAAI,CAAC,MAAQ,EAAA;AACX,IAAO,OAAA,IAAA;AAAA;AAGT,EAAA,MAAM,QAAW,GAAA,MAAA;AAEjB,EAAM,MAAA,KAAA,mBACHA,cAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,OAAO,EAAA,IAAA,EAAC,IAAI,MAAO,CAAA,QAAA,EAAA,EACtB,SAAW,EAAA,MAAA,CAAO,KACjB,mBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,2BAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,UAAU,MAAO,CAAA,KAAA;AAAA,MACvB,QAAQ,SAAU,CAAA,MAAA;AAAA,MAClB,SAAS,SAAU,CAAA;AAAA;AAAA,GACrB,GAEA,OAAO,KAEX,CAAA;AAGF,EAAA,MAAM,OACJ,mBAAAA,cAAA,CAAA,aAAA,CAAAA,cAAA,CAAA,QAAA,EAAA,IAAA,kBACGA,cAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,WAAU,MAAO,EAAA,SAAA,EAAW,OAAQ,CAAA,SAAA,EAAA,EAC7C,CAAG,EAAA,CAAA,CAAE,4CAA4C,CAAC,qBAClDA,cAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,SAAU,EAAA,MAAA,EAAO,KAAO,EAAA,QAAA,CAAS,SAC1C,EAAA,EAAA,QAAA,CAAS,QAAQ,QAAS,CAAA,SAAS,CAAE,CAAA,UAAA,EACxC,CACF,CAAA,kBAEGA,cAAA,CAAA,aAAA,CAAAA,cAAA,CAAA,QAAA,EAAA,IAAA,EAAA,SAAA,EAAW,OAAO,IACjB,mBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,2BAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,UAAU,MAAO,CAAA,IAAA;AAAA,MACvB,QAAQ,SAAU,CAAA,MAAA;AAAA,MAClB,SAAS,SAAU,CAAA;AAAA;AAAA,GACrB,GAEA,MAAO,CAAA,IAEX,CACF,CAAA;AAGF,EAAA,uBAEIA,cAAA,CAAA,aAAA,CAAAA,cAAA,CAAA,QAAA,EAAA,IAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,QAAS,EAAA,EAAA,UAAA,EAAW,QACnB,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,EAAE,+CAA+C;AAAA,KAAA;AAAA,iDAEvD,mBAAoB,EAAA,IAAA;AAAA,GAEvB,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA,KAAA;AAAA,MACT,SAAW,EAAA,OAAA;AAAA,MACX,WAAW,OAAQ,CAAA,QAAA;AAAA,MACnB,sBAAA,EAAwB,EAAE,OAAA,EAAS,IAAK;AAAA;AAAA,GAE5C,CAEA,kBAAAA,cAAA,CAAA,aAAA,CAAC,OAAQ,EAAA,EAAA,SAAA,EAAU,MAAK,CAC1B,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { DateTime } from 'luxon';
|
|
3
|
+
import { usePermission } from '@backstage/plugin-permission-react';
|
|
4
|
+
import { Progress, InfoCard, Link } from '@backstage/core-components';
|
|
5
|
+
import { useApi, useRouteRef } from '@backstage/core-plugin-api';
|
|
6
|
+
import { announcementEntityPermissions } from '@backstage-community/plugin-announcements-common';
|
|
7
|
+
import { rootRouteRef, announcementViewRouteRef, announcementCreateRouteRef } from '../../routes.esm.js';
|
|
8
|
+
import { announcementsApiRef, useAnnouncementsTranslation, useAnnouncements } from '@backstage-community/plugin-announcements-react';
|
|
9
|
+
import { makeStyles, List, ListItem, ListItemIcon, ListItemText } from '@material-ui/core';
|
|
10
|
+
import { Alert } from '@material-ui/lab';
|
|
11
|
+
import NewReleasesIcon from '@material-ui/icons/NewReleases';
|
|
12
|
+
|
|
13
|
+
const useStyles = makeStyles({
|
|
14
|
+
newAnnouncementIcon: {
|
|
15
|
+
minWidth: "36px"
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
const AnnouncementsCard = ({
|
|
19
|
+
title,
|
|
20
|
+
max,
|
|
21
|
+
category,
|
|
22
|
+
active,
|
|
23
|
+
variant = "gridItem"
|
|
24
|
+
}) => {
|
|
25
|
+
const classes = useStyles();
|
|
26
|
+
const announcementsApi = useApi(announcementsApiRef);
|
|
27
|
+
const announcementsLink = useRouteRef(rootRouteRef);
|
|
28
|
+
const viewAnnouncementLink = useRouteRef(announcementViewRouteRef);
|
|
29
|
+
const createAnnouncementLink = useRouteRef(announcementCreateRouteRef);
|
|
30
|
+
const lastSeen = announcementsApi.lastSeenDate();
|
|
31
|
+
const { t } = useAnnouncementsTranslation();
|
|
32
|
+
const { announcements, loading, error } = useAnnouncements({
|
|
33
|
+
max: max || 5,
|
|
34
|
+
category,
|
|
35
|
+
active
|
|
36
|
+
});
|
|
37
|
+
const { announcementCreatePermission } = announcementEntityPermissions;
|
|
38
|
+
const { loading: loadingPermission, allowed: canAdd } = usePermission({
|
|
39
|
+
permission: announcementCreatePermission
|
|
40
|
+
});
|
|
41
|
+
if (loading) {
|
|
42
|
+
return /* @__PURE__ */ React__default.createElement(Progress, null);
|
|
43
|
+
} else if (error) {
|
|
44
|
+
return /* @__PURE__ */ React__default.createElement(Alert, { severity: "error" }, error.message);
|
|
45
|
+
}
|
|
46
|
+
const deepLink = {
|
|
47
|
+
link: announcementsLink(),
|
|
48
|
+
title: t("announcementsCard.seeAll")
|
|
49
|
+
};
|
|
50
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
51
|
+
InfoCard,
|
|
52
|
+
{
|
|
53
|
+
title: title || t("announcementsCard.announcements"),
|
|
54
|
+
variant,
|
|
55
|
+
deepLink
|
|
56
|
+
},
|
|
57
|
+
/* @__PURE__ */ React__default.createElement(List, { dense: true }, announcements.results.map((announcement) => /* @__PURE__ */ React__default.createElement(ListItem, { key: announcement.id }, /* @__PURE__ */ React__default.createElement(ListItem, null, lastSeen < DateTime.fromISO(announcement.created_at) && /* @__PURE__ */ React__default.createElement(
|
|
58
|
+
ListItemIcon,
|
|
59
|
+
{
|
|
60
|
+
className: classes.newAnnouncementIcon,
|
|
61
|
+
title: t("announcementsCard.new")
|
|
62
|
+
},
|
|
63
|
+
/* @__PURE__ */ React__default.createElement(NewReleasesIcon, null)
|
|
64
|
+
), /* @__PURE__ */ React__default.createElement(
|
|
65
|
+
ListItemText,
|
|
66
|
+
{
|
|
67
|
+
primary: /* @__PURE__ */ React__default.createElement(Link, { to: viewAnnouncementLink({ id: announcement.id }) }, announcement.title),
|
|
68
|
+
secondary: /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, DateTime.fromISO(announcement.created_at).toRelative(), announcement.category && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, ` ${t("announcementsCard.in")} `, /* @__PURE__ */ React__default.createElement(
|
|
69
|
+
Link,
|
|
70
|
+
{
|
|
71
|
+
to: `${announcementsLink()}?category=${announcement.category.slug}`
|
|
72
|
+
},
|
|
73
|
+
announcement.category.title
|
|
74
|
+
)), " ", "\u2013 ", announcement.excerpt)
|
|
75
|
+
}
|
|
76
|
+
)))), announcements.count === 0 && !loadingPermission && canAdd && /* @__PURE__ */ React__default.createElement(ListItem, null, /* @__PURE__ */ React__default.createElement(ListItemText, null, `${t("announcementsCard.noAnnouncements")} `, /* @__PURE__ */ React__default.createElement(Link, { to: createAnnouncementLink() }, t("announcementsCard.addOne")), "?")))
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export { AnnouncementsCard };
|
|
81
|
+
//# sourceMappingURL=AnnouncementsCard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnnouncementsCard.esm.js","sources":["../../../src/components/AnnouncementsCard/AnnouncementsCard.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\nimport { DateTime } from 'luxon';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport {\n InfoCard,\n InfoCardVariants,\n Link,\n Progress,\n} from '@backstage/core-components';\nimport { useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { announcementEntityPermissions } from '@backstage-community/plugin-announcements-common';\nimport {\n announcementCreateRouteRef,\n announcementViewRouteRef,\n rootRouteRef,\n} from '../../routes';\nimport {\n announcementsApiRef,\n useAnnouncements,\n useAnnouncementsTranslation,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n makeStyles,\n List,\n ListItem,\n ListItemIcon,\n ListItemText,\n} from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport NewReleasesIcon from '@material-ui/icons/NewReleases';\n\nconst useStyles = makeStyles({\n newAnnouncementIcon: {\n minWidth: '36px',\n },\n});\n\ntype AnnouncementsCardOpts = {\n title?: string;\n max?: number;\n category?: string;\n active?: boolean;\n variant?: InfoCardVariants;\n};\n\nexport const AnnouncementsCard = ({\n title,\n max,\n category,\n active,\n variant = 'gridItem',\n}: AnnouncementsCardOpts) => {\n const classes = useStyles();\n const announcementsApi = useApi(announcementsApiRef);\n const announcementsLink = useRouteRef(rootRouteRef);\n const viewAnnouncementLink = useRouteRef(announcementViewRouteRef);\n const createAnnouncementLink = useRouteRef(announcementCreateRouteRef);\n const lastSeen = announcementsApi.lastSeenDate();\n const { t } = useAnnouncementsTranslation();\n\n const { announcements, loading, error } = useAnnouncements({\n max: max || 5,\n category,\n active,\n });\n\n const { announcementCreatePermission } = announcementEntityPermissions;\n const { loading: loadingPermission, allowed: canAdd } = usePermission({\n permission: announcementCreatePermission,\n });\n\n if (loading) {\n return <Progress />;\n } else if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n const deepLink = {\n link: announcementsLink(),\n title: t('announcementsCard.seeAll'),\n };\n\n return (\n <InfoCard\n title={title || t('announcementsCard.announcements')}\n variant={variant}\n deepLink={deepLink}\n >\n <List dense>\n {announcements.results.map(announcement => (\n <ListItem key={announcement.id}>\n <ListItem>\n {lastSeen < DateTime.fromISO(announcement.created_at) && (\n <ListItemIcon\n className={classes.newAnnouncementIcon}\n title={t('announcementsCard.new')}\n >\n <NewReleasesIcon />\n </ListItemIcon>\n )}\n\n <ListItemText\n primary={\n <Link to={viewAnnouncementLink({ id: announcement.id })}>\n {announcement.title}\n </Link>\n }\n secondary={\n <>\n {DateTime.fromISO(announcement.created_at).toRelative()}\n {announcement.category && (\n <>\n {` ${t('announcementsCard.in')} `}\n <Link\n to={`${announcementsLink()}?category=${\n announcement.category.slug\n }`}\n >\n {announcement.category.title}\n </Link>\n </>\n )}{' '}\n – {announcement.excerpt}\n </>\n }\n />\n </ListItem>\n </ListItem>\n ))}\n {announcements.count === 0 && !loadingPermission && canAdd && (\n <ListItem>\n <ListItemText>\n {`${t('announcementsCard.noAnnouncements')} `}\n <Link to={createAnnouncementLink()}>\n {t('announcementsCard.addOne')}\n </Link>\n ?\n </ListItemText>\n </ListItem>\n )}\n </List>\n </InfoCard>\n );\n};\n"],"names":["React"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { useLocation } from 'react-router-dom';
|
|
3
|
+
import { usePermission } from '@backstage/plugin-permission-react';
|
|
4
|
+
import { announcementCreatePermission, announcementDeletePermission, announcementUpdatePermission } from '@backstage-community/plugin-announcements-common';
|
|
5
|
+
import { DateTime } from 'luxon';
|
|
6
|
+
import { Page, Header, Content, ContentHeader, LinkButton, Progress, ItemCardGrid, Link } from '@backstage/core-components';
|
|
7
|
+
import { useRouteRef, useApi, alertApiRef } from '@backstage/core-plugin-api';
|
|
8
|
+
import { parseEntityRef } from '@backstage/catalog-model';
|
|
9
|
+
import { entityRouteRef, EntityPeekAheadPopover, EntityDisplayName } from '@backstage/plugin-catalog-react';
|
|
10
|
+
import DeleteIcon from '@material-ui/icons/Delete';
|
|
11
|
+
import EditIcon from '@material-ui/icons/Edit';
|
|
12
|
+
import MoreVert from '@material-ui/icons/MoreVert';
|
|
13
|
+
import { announcementCreateRouteRef, rootRouteRef, announcementViewRouteRef, announcementEditRouteRef } from '../../routes.esm.js';
|
|
14
|
+
import { DeleteAnnouncementDialog } from './DeleteAnnouncementDialog.esm.js';
|
|
15
|
+
import { useDeleteAnnouncementDialogState } from './useDeleteAnnouncementDialogState.esm.js';
|
|
16
|
+
import { ContextMenu } from './ContextMenu.esm.js';
|
|
17
|
+
import { useAnnouncementsTranslation, announcementsApiRef, useAnnouncements } from '@backstage-community/plugin-announcements-react';
|
|
18
|
+
import { makeStyles, Tooltip, Card, CardHeader, CardContent, IconButton, Menu, MenuItem, ListItemIcon } from '@material-ui/core';
|
|
19
|
+
import { Alert, Pagination } from '@material-ui/lab';
|
|
20
|
+
|
|
21
|
+
const useStyles = makeStyles((theme) => {
|
|
22
|
+
return {
|
|
23
|
+
cardHeader: {
|
|
24
|
+
color: theme?.palette?.text?.primary || "#000",
|
|
25
|
+
fontSize: "1.5rem"
|
|
26
|
+
},
|
|
27
|
+
pagination: {
|
|
28
|
+
display: "flex",
|
|
29
|
+
justifyContent: "center",
|
|
30
|
+
marginTop: theme?.spacing?.(4) || 32
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
const truncate = (text, length) => {
|
|
35
|
+
return text.length > length ? `${text.substring(0, length)}...` : text;
|
|
36
|
+
};
|
|
37
|
+
const AnnouncementCard = ({
|
|
38
|
+
announcement,
|
|
39
|
+
onDelete,
|
|
40
|
+
options: { titleLength = 50 }
|
|
41
|
+
}) => {
|
|
42
|
+
const classes = useStyles();
|
|
43
|
+
const announcementsLink = useRouteRef(rootRouteRef);
|
|
44
|
+
const viewAnnouncementLink = useRouteRef(announcementViewRouteRef);
|
|
45
|
+
const editAnnouncementLink = useRouteRef(announcementEditRouteRef);
|
|
46
|
+
const entityLink = useRouteRef(entityRouteRef);
|
|
47
|
+
const { t } = useAnnouncementsTranslation();
|
|
48
|
+
const publisherRef = parseEntityRef(announcement.publisher);
|
|
49
|
+
const title = /* @__PURE__ */ React__default.createElement(
|
|
50
|
+
Tooltip,
|
|
51
|
+
{
|
|
52
|
+
title: announcement.title,
|
|
53
|
+
disableFocusListener: true,
|
|
54
|
+
"data-testid": "announcement-card-title-tooltip"
|
|
55
|
+
},
|
|
56
|
+
/* @__PURE__ */ React__default.createElement(
|
|
57
|
+
Link,
|
|
58
|
+
{
|
|
59
|
+
className: classes.cardHeader,
|
|
60
|
+
to: viewAnnouncementLink({ id: announcement.id })
|
|
61
|
+
},
|
|
62
|
+
truncate(announcement.title, titleLength)
|
|
63
|
+
)
|
|
64
|
+
);
|
|
65
|
+
const subTitle = /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, t("announcementsPage.card.by"), " ", /* @__PURE__ */ React__default.createElement(EntityPeekAheadPopover, { entityRef: announcement.publisher }, /* @__PURE__ */ React__default.createElement(Link, { to: entityLink(publisherRef) }, /* @__PURE__ */ React__default.createElement(EntityDisplayName, { entityRef: announcement.publisher, hideIcon: true }))), announcement.category && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, " ", t("announcementsPage.card.in"), " ", /* @__PURE__ */ React__default.createElement(
|
|
66
|
+
Link,
|
|
67
|
+
{
|
|
68
|
+
to: `${announcementsLink()}?category=${announcement.category.slug}`
|
|
69
|
+
},
|
|
70
|
+
announcement.category.title
|
|
71
|
+
)), ", ", DateTime.fromISO(announcement.created_at).toRelative());
|
|
72
|
+
const { loading: loadingDeletePermission, allowed: canDelete } = usePermission({ permission: announcementDeletePermission });
|
|
73
|
+
const { loading: loadingUpdatePermission, allowed: canUpdate } = usePermission({ permission: announcementUpdatePermission });
|
|
74
|
+
const AnnouncementEditMenu = () => {
|
|
75
|
+
const [open, setOpen] = React__default.useState(false);
|
|
76
|
+
const [anchorEl, setAnchorEl] = React__default.useState(
|
|
77
|
+
void 0
|
|
78
|
+
);
|
|
79
|
+
const handleOpenEditMenu = (event) => {
|
|
80
|
+
setAnchorEl(event.currentTarget);
|
|
81
|
+
setOpen(true);
|
|
82
|
+
};
|
|
83
|
+
const handleCloseEditClose = () => {
|
|
84
|
+
setAnchorEl(void 0);
|
|
85
|
+
setOpen(false);
|
|
86
|
+
};
|
|
87
|
+
const canShowMenu = !loadingUpdatePermission && canUpdate || !loadingDeletePermission && canDelete;
|
|
88
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, canShowMenu && /* @__PURE__ */ React__default.createElement(
|
|
89
|
+
IconButton,
|
|
90
|
+
{
|
|
91
|
+
"data-testid": "announcement-edit-menu",
|
|
92
|
+
"aria-label": "more",
|
|
93
|
+
onClick: handleOpenEditMenu
|
|
94
|
+
},
|
|
95
|
+
/* @__PURE__ */ React__default.createElement(MoreVert, null)
|
|
96
|
+
), /* @__PURE__ */ React__default.createElement(Menu, { anchorEl, open, onClose: handleCloseEditClose }, !loadingUpdatePermission && canUpdate && /* @__PURE__ */ React__default.createElement(
|
|
97
|
+
MenuItem,
|
|
98
|
+
{
|
|
99
|
+
"data-testid": "edit-announcement",
|
|
100
|
+
component: LinkButton,
|
|
101
|
+
to: editAnnouncementLink({ id: announcement.id })
|
|
102
|
+
},
|
|
103
|
+
/* @__PURE__ */ React__default.createElement(ListItemIcon, null, /* @__PURE__ */ React__default.createElement(EditIcon, null)),
|
|
104
|
+
t("announcementsPage.card.edit")
|
|
105
|
+
), !loadingDeletePermission && canDelete && /* @__PURE__ */ React__default.createElement(MenuItem, { onClick: onDelete }, /* @__PURE__ */ React__default.createElement(ListItemIcon, null, /* @__PURE__ */ React__default.createElement(DeleteIcon, null)), t("announcementsPage.card.delete"))));
|
|
106
|
+
};
|
|
107
|
+
return /* @__PURE__ */ React__default.createElement(Card, null, /* @__PURE__ */ React__default.createElement(
|
|
108
|
+
CardHeader,
|
|
109
|
+
{
|
|
110
|
+
action: /* @__PURE__ */ React__default.createElement(AnnouncementEditMenu, null),
|
|
111
|
+
title,
|
|
112
|
+
subheader: subTitle
|
|
113
|
+
}
|
|
114
|
+
), /* @__PURE__ */ React__default.createElement(CardContent, null, announcement.excerpt));
|
|
115
|
+
};
|
|
116
|
+
const AnnouncementsGrid = ({
|
|
117
|
+
maxPerPage,
|
|
118
|
+
category,
|
|
119
|
+
cardTitleLength,
|
|
120
|
+
active
|
|
121
|
+
}) => {
|
|
122
|
+
const classes = useStyles();
|
|
123
|
+
const announcementsApi = useApi(announcementsApiRef);
|
|
124
|
+
const alertApi = useApi(alertApiRef);
|
|
125
|
+
const [page, setPage] = React__default.useState(1);
|
|
126
|
+
const handleChange = (_event, value) => {
|
|
127
|
+
setPage(value);
|
|
128
|
+
};
|
|
129
|
+
const {
|
|
130
|
+
announcements,
|
|
131
|
+
loading,
|
|
132
|
+
error,
|
|
133
|
+
retry: refresh
|
|
134
|
+
} = useAnnouncements(
|
|
135
|
+
{
|
|
136
|
+
max: maxPerPage,
|
|
137
|
+
page,
|
|
138
|
+
category,
|
|
139
|
+
active
|
|
140
|
+
},
|
|
141
|
+
{ dependencies: [maxPerPage, page, category] }
|
|
142
|
+
);
|
|
143
|
+
const { t } = useAnnouncementsTranslation();
|
|
144
|
+
const {
|
|
145
|
+
isOpen: isDeleteDialogOpen,
|
|
146
|
+
open: openDeleteDialog,
|
|
147
|
+
close: closeDeleteDialog,
|
|
148
|
+
announcement: announcementToDelete
|
|
149
|
+
} = useDeleteAnnouncementDialogState();
|
|
150
|
+
if (loading) {
|
|
151
|
+
return /* @__PURE__ */ React__default.createElement(Progress, null);
|
|
152
|
+
} else if (error) {
|
|
153
|
+
return /* @__PURE__ */ React__default.createElement(Alert, { severity: "error" }, error.message);
|
|
154
|
+
}
|
|
155
|
+
const onCancelDelete = () => {
|
|
156
|
+
closeDeleteDialog();
|
|
157
|
+
};
|
|
158
|
+
const onConfirmDelete = async () => {
|
|
159
|
+
closeDeleteDialog();
|
|
160
|
+
try {
|
|
161
|
+
await announcementsApi.deleteAnnouncementByID(announcementToDelete.id);
|
|
162
|
+
alertApi.post({
|
|
163
|
+
message: t("announcementsPage.grid.announcementDeleted"),
|
|
164
|
+
severity: "success"
|
|
165
|
+
});
|
|
166
|
+
} catch (err) {
|
|
167
|
+
alertApi.post({ message: err.message, severity: "error" });
|
|
168
|
+
}
|
|
169
|
+
refresh();
|
|
170
|
+
};
|
|
171
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(ItemCardGrid, null, announcements.results.map((announcement) => /* @__PURE__ */ React__default.createElement(
|
|
172
|
+
AnnouncementCard,
|
|
173
|
+
{
|
|
174
|
+
key: announcement.id,
|
|
175
|
+
announcement,
|
|
176
|
+
onDelete: () => openDeleteDialog(announcement),
|
|
177
|
+
options: { titleLength: cardTitleLength }
|
|
178
|
+
}
|
|
179
|
+
))), announcements && announcements.count !== 0 && /* @__PURE__ */ React__default.createElement("div", { className: classes.pagination }, /* @__PURE__ */ React__default.createElement(
|
|
180
|
+
Pagination,
|
|
181
|
+
{
|
|
182
|
+
count: Math.ceil(announcements.count / maxPerPage),
|
|
183
|
+
page,
|
|
184
|
+
onChange: handleChange
|
|
185
|
+
}
|
|
186
|
+
)), /* @__PURE__ */ React__default.createElement(
|
|
187
|
+
DeleteAnnouncementDialog,
|
|
188
|
+
{
|
|
189
|
+
open: isDeleteDialogOpen,
|
|
190
|
+
onCancel: onCancelDelete,
|
|
191
|
+
onConfirm: onConfirmDelete
|
|
192
|
+
}
|
|
193
|
+
));
|
|
194
|
+
};
|
|
195
|
+
const AnnouncementsPage = (props) => {
|
|
196
|
+
const location = useLocation();
|
|
197
|
+
const queryParams = new URLSearchParams(location.search);
|
|
198
|
+
const newAnnouncementLink = useRouteRef(announcementCreateRouteRef);
|
|
199
|
+
const { loading: loadingCreatePermission, allowed: canCreate } = usePermission({ permission: announcementCreatePermission });
|
|
200
|
+
const { t } = useAnnouncementsTranslation();
|
|
201
|
+
const {
|
|
202
|
+
hideContextMenu,
|
|
203
|
+
hideInactive,
|
|
204
|
+
themeId,
|
|
205
|
+
title,
|
|
206
|
+
subtitle,
|
|
207
|
+
buttonOptions,
|
|
208
|
+
maxPerPage,
|
|
209
|
+
category,
|
|
210
|
+
cardOptions
|
|
211
|
+
} = props;
|
|
212
|
+
return /* @__PURE__ */ React__default.createElement(Page, { themeId }, /* @__PURE__ */ React__default.createElement(Header, { title, subtitle }, !hideContextMenu && /* @__PURE__ */ React__default.createElement(ContextMenu, null)), /* @__PURE__ */ React__default.createElement(Content, null, /* @__PURE__ */ React__default.createElement(ContentHeader, { title: "" }, !loadingCreatePermission && /* @__PURE__ */ React__default.createElement(
|
|
213
|
+
LinkButton,
|
|
214
|
+
{
|
|
215
|
+
disabled: !canCreate,
|
|
216
|
+
to: newAnnouncementLink(),
|
|
217
|
+
color: "primary",
|
|
218
|
+
variant: "contained"
|
|
219
|
+
},
|
|
220
|
+
buttonOptions ? `${t("announcementsPage.genericNew")} ${buttonOptions.name}` : t("announcementsPage.newAnnouncement")
|
|
221
|
+
)), /* @__PURE__ */ React__default.createElement(
|
|
222
|
+
AnnouncementsGrid,
|
|
223
|
+
{
|
|
224
|
+
maxPerPage: maxPerPage ?? 10,
|
|
225
|
+
category: category ?? queryParams.get("category") ?? void 0,
|
|
226
|
+
cardTitleLength: cardOptions?.titleLength,
|
|
227
|
+
active: hideInactive ? true : false
|
|
228
|
+
}
|
|
229
|
+
)));
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
export { AnnouncementsPage };
|
|
233
|
+
//# sourceMappingURL=AnnouncementsPage.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnnouncementsPage.esm.js","sources":["../../../src/components/AnnouncementsPage/AnnouncementsPage.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { ReactNode } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport {\n announcementCreatePermission,\n announcementUpdatePermission,\n announcementDeletePermission,\n Announcement,\n} from '@backstage-community/plugin-announcements-common';\nimport { DateTime } from 'luxon';\nimport {\n Page,\n Header,\n Content,\n Link,\n ItemCardGrid,\n Progress,\n ContentHeader,\n LinkButton,\n} from '@backstage/core-components';\nimport { alertApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport {\n EntityDisplayName,\n EntityPeekAheadPopover,\n entityRouteRef,\n} from '@backstage/plugin-catalog-react';\nimport DeleteIcon from '@material-ui/icons/Delete';\nimport EditIcon from '@material-ui/icons/Edit';\nimport MoreVertIcon from '@material-ui/icons/MoreVert';\nimport {\n announcementCreateRouteRef,\n announcementEditRouteRef,\n announcementViewRouteRef,\n rootRouteRef,\n} from '../../routes';\nimport { DeleteAnnouncementDialog } from './DeleteAnnouncementDialog';\nimport { useDeleteAnnouncementDialogState } from './useDeleteAnnouncementDialogState';\nimport { ContextMenu } from './ContextMenu';\nimport {\n announcementsApiRef,\n useAnnouncements,\n useAnnouncementsTranslation,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n Card,\n CardContent,\n CardHeader,\n IconButton,\n ListItemIcon,\n makeStyles,\n Menu,\n MenuItem,\n Tooltip,\n} from '@material-ui/core';\nimport { Alert, Pagination } from '@material-ui/lab';\n\nconst useStyles = makeStyles(theme => {\n return {\n cardHeader: {\n color: theme?.palette?.text?.primary || '#000',\n fontSize: '1.5rem',\n },\n pagination: {\n display: 'flex',\n justifyContent: 'center',\n marginTop: theme?.spacing?.(4) || 32,\n },\n };\n});\n/**\n * Truncate text to a given length and add ellipsis\n * @param text the text to truncate\n * @param length the length to truncate to\n * @returns the truncated text\n */\nconst truncate = (text: string, length: number) => {\n return text.length > length ? `${text.substring(0, length)}...` : text;\n};\n\nconst AnnouncementCard = ({\n announcement,\n onDelete,\n options: { titleLength = 50 },\n}: {\n announcement: Announcement;\n onDelete: () => void;\n options: AnnouncementCardProps;\n}) => {\n const classes = useStyles();\n const announcementsLink = useRouteRef(rootRouteRef);\n const viewAnnouncementLink = useRouteRef(announcementViewRouteRef);\n const editAnnouncementLink = useRouteRef(announcementEditRouteRef);\n const entityLink = useRouteRef(entityRouteRef);\n const { t } = useAnnouncementsTranslation();\n\n const publisherRef = parseEntityRef(announcement.publisher);\n const title = (\n <Tooltip\n title={announcement.title}\n disableFocusListener\n data-testid=\"announcement-card-title-tooltip\"\n >\n <Link\n className={classes.cardHeader}\n to={viewAnnouncementLink({ id: announcement.id })}\n >\n {truncate(announcement.title, titleLength)}\n </Link>\n </Tooltip>\n );\n const subTitle = (\n <>\n {t('announcementsPage.card.by')}{' '}\n <EntityPeekAheadPopover entityRef={announcement.publisher}>\n <Link to={entityLink(publisherRef)}>\n <EntityDisplayName entityRef={announcement.publisher} hideIcon />\n </Link>\n </EntityPeekAheadPopover>\n {announcement.category && (\n <>\n {' '}\n {t('announcementsPage.card.in')}{' '}\n <Link\n to={`${announcementsLink()}?category=${announcement.category.slug}`}\n >\n {announcement.category.title}\n </Link>\n </>\n )}\n , {DateTime.fromISO(announcement.created_at).toRelative()}\n </>\n );\n const { loading: loadingDeletePermission, allowed: canDelete } =\n usePermission({ permission: announcementDeletePermission });\n const { loading: loadingUpdatePermission, allowed: canUpdate } =\n usePermission({ permission: announcementUpdatePermission });\n\n const AnnouncementEditMenu = () => {\n const [open, setOpen] = React.useState(false);\n const [anchorEl, setAnchorEl] = React.useState<undefined | HTMLElement>(\n undefined,\n );\n\n const handleOpenEditMenu = (event: React.MouseEvent<HTMLButtonElement>) => {\n setAnchorEl(event.currentTarget);\n setOpen(true);\n };\n\n const handleCloseEditClose = () => {\n setAnchorEl(undefined);\n setOpen(false);\n };\n\n const canShowMenu =\n (!loadingUpdatePermission && canUpdate) ||\n (!loadingDeletePermission && canDelete);\n\n return (\n <>\n {canShowMenu && (\n <IconButton\n data-testid=\"announcement-edit-menu\"\n aria-label=\"more\"\n onClick={handleOpenEditMenu}\n >\n <MoreVertIcon />\n </IconButton>\n )}\n <Menu anchorEl={anchorEl} open={open} onClose={handleCloseEditClose}>\n {!loadingUpdatePermission && canUpdate && (\n <MenuItem\n data-testid=\"edit-announcement\"\n component={LinkButton}\n to={editAnnouncementLink({ id: announcement.id })}\n >\n <ListItemIcon>\n <EditIcon />\n </ListItemIcon>\n {t('announcementsPage.card.edit')}\n </MenuItem>\n )}\n {!loadingDeletePermission && canDelete && (\n <MenuItem onClick={onDelete}>\n <ListItemIcon>\n <DeleteIcon />\n </ListItemIcon>\n {t('announcementsPage.card.delete')}\n </MenuItem>\n )}\n </Menu>\n </>\n );\n };\n\n return (\n <Card>\n <CardHeader\n action={<AnnouncementEditMenu />}\n title={title}\n subheader={subTitle}\n />\n <CardContent>{announcement.excerpt}</CardContent>\n </Card>\n );\n};\n\nconst AnnouncementsGrid = ({\n maxPerPage,\n category,\n cardTitleLength,\n active,\n}: {\n maxPerPage: number;\n category?: string;\n cardTitleLength?: number;\n active?: boolean;\n}) => {\n const classes = useStyles();\n const announcementsApi = useApi(announcementsApiRef);\n const alertApi = useApi(alertApiRef);\n\n const [page, setPage] = React.useState(1);\n const handleChange = (_event: any, value: number) => {\n setPage(value);\n };\n\n const {\n announcements,\n loading,\n error,\n retry: refresh,\n } = useAnnouncements(\n {\n max: maxPerPage,\n page: page,\n category,\n active,\n },\n { dependencies: [maxPerPage, page, category] },\n );\n\n const { t } = useAnnouncementsTranslation();\n\n const {\n isOpen: isDeleteDialogOpen,\n open: openDeleteDialog,\n close: closeDeleteDialog,\n announcement: announcementToDelete,\n } = useDeleteAnnouncementDialogState();\n\n if (loading) {\n return <Progress />;\n } else if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n const onCancelDelete = () => {\n closeDeleteDialog();\n };\n const onConfirmDelete = async () => {\n closeDeleteDialog();\n\n try {\n await announcementsApi.deleteAnnouncementByID(announcementToDelete!.id);\n\n alertApi.post({\n message: t('announcementsPage.grid.announcementDeleted'),\n severity: 'success',\n });\n } catch (err) {\n alertApi.post({ message: (err as Error).message, severity: 'error' });\n }\n\n refresh();\n };\n\n return (\n <>\n <ItemCardGrid>\n {announcements.results.map(announcement => (\n <AnnouncementCard\n key={announcement.id}\n announcement={announcement}\n onDelete={() => openDeleteDialog(announcement)}\n options={{ titleLength: cardTitleLength }}\n />\n ))}\n </ItemCardGrid>\n\n {announcements && announcements.count !== 0 && (\n <div className={classes.pagination}>\n <Pagination\n count={Math.ceil(announcements.count / maxPerPage)}\n page={page}\n onChange={handleChange}\n />\n </div>\n )}\n\n <DeleteAnnouncementDialog\n open={isDeleteDialogOpen}\n onCancel={onCancelDelete}\n onConfirm={onConfirmDelete}\n />\n </>\n );\n};\n\ntype AnnouncementCardProps = {\n titleLength?: number;\n};\n\ntype AnnouncementCreateButtonProps = {\n name?: string;\n};\n\nexport type AnnouncementsPageProps = {\n themeId: string;\n title: string;\n subtitle?: ReactNode;\n maxPerPage?: number;\n category?: string;\n buttonOptions?: AnnouncementCreateButtonProps;\n cardOptions?: AnnouncementCardProps;\n hideContextMenu?: boolean;\n hideInactive?: boolean;\n};\n\nexport const AnnouncementsPage = (props: AnnouncementsPageProps) => {\n const location = useLocation();\n const queryParams = new URLSearchParams(location.search);\n const newAnnouncementLink = useRouteRef(announcementCreateRouteRef);\n const { loading: loadingCreatePermission, allowed: canCreate } =\n usePermission({ permission: announcementCreatePermission });\n const { t } = useAnnouncementsTranslation();\n\n const {\n hideContextMenu,\n hideInactive,\n themeId,\n title,\n subtitle,\n buttonOptions,\n maxPerPage,\n category,\n cardOptions,\n } = props;\n\n return (\n <Page themeId={themeId}>\n <Header title={title} subtitle={subtitle}>\n {!hideContextMenu && <ContextMenu />}\n </Header>\n\n <Content>\n <ContentHeader title=\"\">\n {!loadingCreatePermission && (\n <LinkButton\n disabled={!canCreate}\n to={newAnnouncementLink()}\n color=\"primary\"\n variant=\"contained\"\n >\n {buttonOptions\n ? `${t('announcementsPage.genericNew')} ${buttonOptions.name}`\n : t('announcementsPage.newAnnouncement')}\n </LinkButton>\n )}\n </ContentHeader>\n\n <AnnouncementsGrid\n maxPerPage={maxPerPage ?? 10}\n category={category ?? queryParams.get('category') ?? undefined}\n cardTitleLength={cardOptions?.titleLength}\n active={hideInactive ? true : false}\n />\n </Content>\n </Page>\n );\n};\n"],"names":["React","MoreVertIcon"],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React__default, { useState } from 'react';
|
|
2
|
+
import { useNavigate } from 'react-router-dom';
|
|
3
|
+
import { useRouteRef } from '@backstage/core-plugin-api';
|
|
4
|
+
import { announcementAdminRouteRef, categoriesListRouteRef } from '../../routes.esm.js';
|
|
5
|
+
import { useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';
|
|
6
|
+
import { makeStyles, Box, IconButton, Popover, MenuList, MenuItem, ListItemIcon, ListItemText } from '@material-ui/core';
|
|
7
|
+
import MoreVert from '@material-ui/icons/MoreVert';
|
|
8
|
+
import Description from '@material-ui/icons/Description';
|
|
9
|
+
|
|
10
|
+
const useStyles = makeStyles({
|
|
11
|
+
button: {
|
|
12
|
+
color: "white"
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
function ContextMenu() {
|
|
16
|
+
const classes = useStyles();
|
|
17
|
+
const [anchorEl, setAnchorEl] = useState();
|
|
18
|
+
const announcementsLink = useRouteRef(announcementAdminRouteRef);
|
|
19
|
+
const categoriesLink = useRouteRef(categoriesListRouteRef);
|
|
20
|
+
const navigate = useNavigate();
|
|
21
|
+
const { t } = useAnnouncementsTranslation();
|
|
22
|
+
const onOpen = (event) => {
|
|
23
|
+
setAnchorEl(event.currentTarget);
|
|
24
|
+
};
|
|
25
|
+
const onClose = () => {
|
|
26
|
+
setAnchorEl(void 0);
|
|
27
|
+
};
|
|
28
|
+
return /* @__PURE__ */ React__default.createElement(Box, { "data-testid": "announcements-context-menu" }, /* @__PURE__ */ React__default.createElement(
|
|
29
|
+
IconButton,
|
|
30
|
+
{
|
|
31
|
+
"aria-label": "more",
|
|
32
|
+
"aria-controls": "long-menu",
|
|
33
|
+
"aria-haspopup": "true",
|
|
34
|
+
onClick: onOpen,
|
|
35
|
+
"data-testid": "menu-button",
|
|
36
|
+
color: "inherit",
|
|
37
|
+
className: classes.button
|
|
38
|
+
},
|
|
39
|
+
/* @__PURE__ */ React__default.createElement(MoreVert, null)
|
|
40
|
+
), /* @__PURE__ */ React__default.createElement(
|
|
41
|
+
Popover,
|
|
42
|
+
{
|
|
43
|
+
open: Boolean(anchorEl),
|
|
44
|
+
onClose,
|
|
45
|
+
anchorEl,
|
|
46
|
+
anchorOrigin: { vertical: "bottom", horizontal: "right" },
|
|
47
|
+
transformOrigin: { vertical: "top", horizontal: "right" }
|
|
48
|
+
},
|
|
49
|
+
/* @__PURE__ */ React__default.createElement(MenuList, null, /* @__PURE__ */ React__default.createElement(MenuItem, { onClick: () => navigate(announcementsLink()) }, /* @__PURE__ */ React__default.createElement(ListItemIcon, null, /* @__PURE__ */ React__default.createElement(Description, { fontSize: "small" })), /* @__PURE__ */ React__default.createElement(ListItemText, { primary: t("announcementsPage.contextMenu.admin") })), /* @__PURE__ */ React__default.createElement(MenuItem, { onClick: () => navigate(categoriesLink()) }, /* @__PURE__ */ React__default.createElement(ListItemIcon, null, /* @__PURE__ */ React__default.createElement(Description, { fontSize: "small" })), /* @__PURE__ */ React__default.createElement(
|
|
50
|
+
ListItemText,
|
|
51
|
+
{
|
|
52
|
+
primary: t("announcementsPage.contextMenu.categories")
|
|
53
|
+
}
|
|
54
|
+
)))
|
|
55
|
+
));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { ContextMenu };
|
|
59
|
+
//# sourceMappingURL=ContextMenu.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContextMenu.esm.js","sources":["../../../src/components/AnnouncementsPage/ContextMenu.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport {\n announcementAdminRouteRef,\n categoriesListRouteRef,\n} from '../../routes';\nimport { useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';\nimport {\n makeStyles,\n Box,\n IconButton,\n Popover,\n MenuList,\n MenuItem,\n ListItemIcon,\n ListItemText,\n} from '@material-ui/core';\nimport MoreVert from '@material-ui/icons/MoreVert';\nimport Description from '@material-ui/icons/Description';\n\nconst useStyles = makeStyles({\n button: {\n color: 'white',\n },\n});\n\nexport function ContextMenu() {\n const classes = useStyles();\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement>();\n const announcementsLink = useRouteRef(announcementAdminRouteRef);\n const categoriesLink = useRouteRef(categoriesListRouteRef);\n const navigate = useNavigate();\n const { t } = useAnnouncementsTranslation();\n\n const onOpen = (event: React.SyntheticEvent<HTMLButtonElement>) => {\n setAnchorEl(event.currentTarget);\n };\n\n const onClose = () => {\n setAnchorEl(undefined);\n };\n\n return (\n <Box data-testid=\"announcements-context-menu\">\n <IconButton\n aria-label=\"more\"\n aria-controls=\"long-menu\"\n aria-haspopup=\"true\"\n onClick={onOpen}\n data-testid=\"menu-button\"\n color=\"inherit\"\n className={classes.button}\n >\n <MoreVert />\n </IconButton>\n <Popover\n open={Boolean(anchorEl)}\n onClose={onClose}\n anchorEl={anchorEl}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\n transformOrigin={{ vertical: 'top', horizontal: 'right' }}\n >\n <MenuList>\n <MenuItem onClick={() => navigate(announcementsLink())}>\n <ListItemIcon>\n <Description fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary={t('announcementsPage.contextMenu.admin')} />\n </MenuItem>\n <MenuItem onClick={() => navigate(categoriesLink())}>\n <ListItemIcon>\n <Description fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText\n primary={t('announcementsPage.contextMenu.categories')}\n />\n </MenuItem>\n </MenuList>\n </Popover>\n </Box>\n );\n}\n"],"names":["React"],"mappings":";;;;;;;;;AAoCA,MAAM,YAAY,UAAW,CAAA;AAAA,EAC3B,MAAQ,EAAA;AAAA,IACN,KAAO,EAAA;AAAA;AAEX,CAAC,CAAA;AAEM,SAAS,WAAc,GAAA;AAC5B,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,QAA4B,EAAA;AAC5D,EAAM,MAAA,iBAAA,GAAoB,YAAY,yBAAyB,CAAA;AAC/D,EAAM,MAAA,cAAA,GAAiB,YAAY,sBAAsB,CAAA;AACzD,EAAA,MAAM,WAAW,WAAY,EAAA;AAC7B,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,2BAA4B,EAAA;AAE1C,EAAM,MAAA,MAAA,GAAS,CAAC,KAAmD,KAAA;AACjE,IAAA,WAAA,CAAY,MAAM,aAAa,CAAA;AAAA,GACjC;AAEA,EAAA,MAAM,UAAU,MAAM;AACpB,IAAA,WAAA,CAAY,KAAS,CAAA,CAAA;AAAA,GACvB;AAEA,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,aAAA,EAAY,4BACf,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,YAAW,EAAA,MAAA;AAAA,MACX,eAAc,EAAA,WAAA;AAAA,MACd,eAAc,EAAA,MAAA;AAAA,MACd,OAAS,EAAA,MAAA;AAAA,MACT,aAAY,EAAA,aAAA;AAAA,MACZ,KAAM,EAAA,SAAA;AAAA,MACN,WAAW,OAAQ,CAAA;AAAA,KAAA;AAAA,iDAElB,QAAS,EAAA,IAAA;AAAA,GAEZ,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,QAAQ,QAAQ,CAAA;AAAA,MACtB,OAAA;AAAA,MACA,QAAA;AAAA,MACA,YAAc,EAAA,EAAE,QAAU,EAAA,QAAA,EAAU,YAAY,OAAQ,EAAA;AAAA,MACxD,eAAiB,EAAA,EAAE,QAAU,EAAA,KAAA,EAAO,YAAY,OAAQ;AAAA,KAAA;AAAA,iDAEvD,QACC,EAAA,IAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,YAAS,OAAS,EAAA,MAAM,SAAS,iBAAkB,EAAC,CACnD,EAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,oCACEA,cAAA,CAAA,aAAA,CAAA,WAAA,EAAA,EAAY,UAAS,OAAQ,EAAA,CAChC,mBACCA,cAAA,CAAA,aAAA,CAAA,YAAA,EAAA,EAAa,OAAS,EAAA,CAAA,CAAE,qCAAqC,CAAG,EAAA,CACnE,mBACCA,cAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,SAAS,MAAM,QAAA,CAAS,gBAAgB,CAAA,EAAA,+CAC/C,YACC,EAAA,IAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,eAAY,QAAS,EAAA,OAAA,EAAQ,CAChC,CACA,kBAAAA,cAAA,CAAA,aAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAS,EAAE,0CAA0C;AAAA;AAAA,KAEzD,CACF;AAAA,GAEJ,CAAA;AAEJ;;;;"}
|