@backstage-community/plugin-announcements 1.4.0 → 2.1.0
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 +56 -0
- package/dist/{alpha/Router.esm.js → Router.esm.js} +14 -7
- package/dist/Router.esm.js.map +1 -0
- package/dist/alpha/components/admin/announcements/AnnouncementForm/AnnouncementForm.esm.js +312 -0
- package/dist/alpha/components/admin/announcements/AnnouncementForm/AnnouncementForm.esm.js.map +1 -0
- package/dist/alpha/components/admin/announcements/AnnouncementForm/OnBehalfTeamDropdown.esm.js +72 -0
- package/dist/alpha/components/admin/announcements/AnnouncementForm/OnBehalfTeamDropdown.esm.js.map +1 -0
- package/dist/alpha/components/admin/announcements/AnnouncementsContent.esm.js +11 -44
- package/dist/alpha/components/admin/announcements/AnnouncementsContent.esm.js.map +1 -1
- package/dist/alpha/components/admin/announcements/AnnouncementsTable.esm.js +15 -1
- package/dist/alpha/components/admin/announcements/AnnouncementsTable.esm.js.map +1 -1
- package/dist/alpha/components/admin/categories/CategoriesContent.esm.js +2 -2
- package/dist/alpha/components/admin/categories/CategoriesContent.esm.js.map +1 -1
- package/dist/alpha/components/admin/categories/{CreateCatagoryDialog.esm.js → CreateCategoryDialog.esm.js} +3 -3
- package/dist/alpha/components/admin/categories/{CreateCatagoryDialog.esm.js.map → CreateCategoryDialog.esm.js.map} +1 -1
- package/dist/alpha/components/announcements/AnnouncementsFilterBar.esm.js +6 -2
- package/dist/alpha/components/announcements/AnnouncementsFilterBar.esm.js.map +1 -1
- package/dist/alpha/components/announcements/ViewAnnouncementPage.esm.js +0 -30
- package/dist/alpha/components/announcements/ViewAnnouncementPage.esm.js.map +1 -1
- package/dist/alpha/components/shared/CategorySelectInput/CategorySelectInput.esm.js +4 -3
- package/dist/alpha/components/shared/CategorySelectInput/CategorySelectInput.esm.js.map +1 -1
- package/dist/alpha/components/shared/TagsSelectInput/TagsSelectInput.esm.js +4 -3
- package/dist/alpha/components/shared/TagsSelectInput/TagsSelectInput.esm.js.map +1 -1
- package/dist/alpha/pages.esm.js +1 -1
- package/dist/alpha/pages.esm.js.map +1 -1
- package/dist/alpha/search.esm.js +5 -3
- package/dist/alpha/search.esm.js.map +1 -1
- package/dist/alpha.d.ts +2 -2
- package/dist/index.d.ts +1 -80
- package/dist/index.esm.js +1 -1
- package/dist/plugin.esm.js +2 -18
- package/dist/plugin.esm.js.map +1 -1
- package/package.json +12 -12
- package/dist/alpha/Router.esm.js.map +0 -1
- package/dist/components/Admin/AdminPortal/AdminPortal.esm.js +0 -65
- package/dist/components/Admin/AdminPortal/AdminPortal.esm.js.map +0 -1
- package/dist/components/Admin/AnnouncementsContent/AnnouncementForm/AnnouncementForm.esm.js +0 -244
- package/dist/components/Admin/AnnouncementsContent/AnnouncementForm/AnnouncementForm.esm.js.map +0 -1
- package/dist/components/Admin/AnnouncementsContent/AnnouncementForm/CategoryInput.esm.js +0 -82
- package/dist/components/Admin/AnnouncementsContent/AnnouncementForm/CategoryInput.esm.js.map +0 -1
- package/dist/components/Admin/AnnouncementsContent/AnnouncementForm/OnBehalfTeamDropdown.esm.js +0 -81
- package/dist/components/Admin/AnnouncementsContent/AnnouncementForm/OnBehalfTeamDropdown.esm.js.map +0 -1
- package/dist/components/Admin/AnnouncementsContent/AnnouncementForm/TagsInput.esm.js +0 -100
- package/dist/components/Admin/AnnouncementsContent/AnnouncementForm/TagsInput.esm.js.map +0 -1
- package/dist/components/Admin/AnnouncementsContent/AnnouncementsContent.esm.js +0 -305
- package/dist/components/Admin/AnnouncementsContent/AnnouncementsContent.esm.js.map +0 -1
- package/dist/components/Admin/CategoriesContent/CategoriesContent.esm.js +0 -143
- package/dist/components/Admin/CategoriesContent/CategoriesContent.esm.js.map +0 -1
- package/dist/components/Admin/TagsContent/TagsContent.esm.js +0 -158
- package/dist/components/Admin/TagsContent/TagsContent.esm.js.map +0 -1
- package/dist/components/Admin/index.esm.js +0 -3
- package/dist/components/Admin/index.esm.js.map +0 -1
- package/dist/components/Admin/shared/DeleteDialog/DeleteDialog.esm.js +0 -30
- package/dist/components/Admin/shared/DeleteDialog/DeleteDialog.esm.js.map +0 -1
- package/dist/components/Admin/shared/DeleteDialog/useDeleteDialogState.esm.js +0 -29
- package/dist/components/Admin/shared/DeleteDialog/useDeleteDialogState.esm.js.map +0 -1
- package/dist/components/Admin/shared/TitleForm/TitleForm.esm.js +0 -71
- package/dist/components/Admin/shared/TitleForm/TitleForm.esm.js.map +0 -1
- package/dist/components/AnnouncementPage/AnnouncementPage.esm.js +0 -99
- package/dist/components/AnnouncementPage/AnnouncementPage.esm.js.map +0 -1
- package/dist/components/AnnouncementsPage/AnnouncementsPage.esm.js +0 -197
- package/dist/components/AnnouncementsPage/AnnouncementsPage.esm.js.map +0 -1
- package/dist/components/AnnouncementsPage/ContextMenu.esm.js +0 -60
- package/dist/components/AnnouncementsPage/ContextMenu.esm.js.map +0 -1
- package/dist/components/AnnouncementsTimeline/AnnouncementsTimeline.esm.js +0 -75
- package/dist/components/AnnouncementsTimeline/AnnouncementsTimeline.esm.js.map +0 -1
- package/dist/components/Router.esm.js +0 -75
- package/dist/components/Router.esm.js.map +0 -1
- package/dist/components/index.esm.js +0 -5
- package/dist/components/index.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,61 @@
|
|
|
1
1
|
# @backstage-community/plugin-announcements
|
|
2
2
|
|
|
3
|
+
## 2.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 99b4b52: Backstage version bump to v1.47.2
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 1a71b9a: The On Behalf Of form component is now rewritten with `@backstage/ui`. The announcements table will now display the on behalf of group alongside publisher if present.
|
|
12
|
+
- 3e53912: The tags select component in the announcements form has been swapped with our new `@backstage/ui` select implementation
|
|
13
|
+
- 44a0337: The category selection in the announcements form has been refactored to use the new `CategorySelectInput` and `CreateCategoryDialog` components written with `@backstage/ui`. Category creation is now handled through the same mechanism as the categories table.
|
|
14
|
+
- 64a82b0: Updates all non-date related text inputs to use the `TextField` from `@backstage/ui`.
|
|
15
|
+
- 6f6d4c8: Switch components in the announcements form have been migrated to use `@backstage/ui`. The "Send notifications" label now includes support for translations.
|
|
16
|
+
- 41f738e: Updates the announcements form to use `@backstage/ui` for the following components:
|
|
17
|
+
|
|
18
|
+
- Box
|
|
19
|
+
- Button
|
|
20
|
+
- InfoCard -> Card, CardBody, CardHeader
|
|
21
|
+
- Grid
|
|
22
|
+
- Typography -> Text
|
|
23
|
+
- Paper -> _removed_
|
|
24
|
+
- Divider -> _removed_
|
|
25
|
+
|
|
26
|
+
These are minor changes that do not affect the functionality of the announcements form.
|
|
27
|
+
|
|
28
|
+
- Updated dependencies [44a0337]
|
|
29
|
+
- Updated dependencies [6f6d4c8]
|
|
30
|
+
- Updated dependencies [99b4b52]
|
|
31
|
+
- @backstage-community/plugin-announcements-react@0.20.0
|
|
32
|
+
- @backstage-community/plugin-announcements-common@0.17.0
|
|
33
|
+
|
|
34
|
+
## 2.0.0
|
|
35
|
+
|
|
36
|
+
### Major Changes
|
|
37
|
+
|
|
38
|
+
- ad6eb1b: Refactor legacy announcements frontend to use the new (NFS) components built with `@backstage/ui`.
|
|
39
|
+
|
|
40
|
+
## Breaking Changes
|
|
41
|
+
|
|
42
|
+
- `AnnouncementsPage` **no longer supports** the following props:
|
|
43
|
+
|
|
44
|
+
- `themeId`
|
|
45
|
+
- `subtitle`
|
|
46
|
+
- `hideContextMenu`
|
|
47
|
+
- `cardOptions`
|
|
48
|
+
- `buttonOptions`
|
|
49
|
+
- `hideInactive`
|
|
50
|
+
|
|
51
|
+
If your app passed any of these props, you must remove them (or migrate to new equivalents if/when they are reintroduced by the NFS implementation).
|
|
52
|
+
|
|
53
|
+
- `AdminPortal` is now implemented via the new announcements admin page and no longer supports customization via props such as `themeId`, `title`, `subtitle`, or `defaultInactive`.
|
|
54
|
+
|
|
55
|
+
### Patch Changes
|
|
56
|
+
|
|
57
|
+
- 89bf3ae: Updated the Search components for the New Frontend System to use the `RecordVoiceOverIcon` to match the existing experince
|
|
58
|
+
|
|
3
59
|
## 1.4.0
|
|
4
60
|
|
|
5
61
|
### Minor Changes
|
|
@@ -2,12 +2,16 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { Routes, Route } from 'react-router-dom';
|
|
3
3
|
import { RequirePermission } from '@backstage/plugin-permission-react';
|
|
4
4
|
import { announcementCreatePermission } from '@backstage-community/plugin-announcements-common';
|
|
5
|
-
import { AnnouncementsAdminPage } from './components/admin/AnnouncementsAdminPage.esm.js';
|
|
6
|
-
import { AnnouncementsContent } from './components/admin/announcements/AnnouncementsContent.esm.js';
|
|
7
|
-
import { CategoriesContent } from './components/admin/categories/CategoriesContent.esm.js';
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
5
|
+
import { AnnouncementsAdminPage } from './alpha/components/admin/AnnouncementsAdminPage.esm.js';
|
|
6
|
+
import { AnnouncementsContent } from './alpha/components/admin/announcements/AnnouncementsContent.esm.js';
|
|
7
|
+
import { CategoriesContent } from './alpha/components/admin/categories/CategoriesContent.esm.js';
|
|
8
|
+
import '@backstage-community/plugin-announcements-react';
|
|
9
|
+
import 'react';
|
|
10
|
+
import '@backstage/ui';
|
|
11
|
+
import { TagsContent } from './alpha/components/admin/tags/TagsContent.esm.js';
|
|
12
|
+
import { AnnouncementsPage } from './alpha/components/announcements/AnnouncementsPage.esm.js';
|
|
13
|
+
import { ViewAnnouncementPage } from './alpha/components/announcements/ViewAnnouncementPage.esm.js';
|
|
14
|
+
import { compatWrapper } from '@backstage/core-compat-api';
|
|
11
15
|
|
|
12
16
|
const Router = (props) => {
|
|
13
17
|
const propsWithDefaults = {
|
|
@@ -62,6 +66,9 @@ const Router = (props) => {
|
|
|
62
66
|
)
|
|
63
67
|
] });
|
|
64
68
|
};
|
|
69
|
+
const OldFrontendSystemCompatibleRouter = (props) => {
|
|
70
|
+
return compatWrapper(/* @__PURE__ */ jsx(Router, { ...props }));
|
|
71
|
+
};
|
|
65
72
|
|
|
66
|
-
export { Router };
|
|
73
|
+
export { OldFrontendSystemCompatibleRouter, Router };
|
|
67
74
|
//# sourceMappingURL=Router.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Router.esm.js","sources":["../src/Router.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { Routes, Route } from 'react-router-dom';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\nimport { announcementCreatePermission } from '@backstage-community/plugin-announcements-common';\nimport {\n AnnouncementsAdminPage,\n AnnouncementsContent,\n CategoriesContent,\n TagsContent,\n AnnouncementsPage,\n AnnouncementsPageProps,\n ViewAnnouncementPage,\n} from './alpha/components';\nimport { MarkdownRendererTypeProps } from './components';\n\nimport { compatWrapper } from '@backstage/core-compat-api';\n\ntype RouterProps = {\n title?: string;\n category?: string;\n hideStartAt?: boolean;\n markdownRenderer?: MarkdownRendererTypeProps;\n defaultInactive?: boolean;\n};\n\nexport const Router = (props: RouterProps) => {\n const propsWithDefaults: AnnouncementsPageProps = {\n title: 'Announcements',\n hideStartAt: false,\n markdownRenderer: 'backstage',\n ...props,\n };\n\n return (\n <Routes>\n <Route path=\"/\" element={<AnnouncementsPage {...propsWithDefaults} />} />\n <Route\n path=\"/view/:id\"\n element={\n <ViewAnnouncementPage\n markdownRenderer={propsWithDefaults.markdownRenderer}\n title={propsWithDefaults.title}\n />\n }\n />\n <Route\n path=\"/admin\"\n element={\n <RequirePermission permission={announcementCreatePermission}>\n <AnnouncementsAdminPage\n title={props.title}\n defaultInactive={props.defaultInactive}\n />\n </RequirePermission>\n }\n >\n <Route\n path=\"\"\n element={\n <AnnouncementsContent\n formDefaults={{ defaultInactive: props.defaultInactive }}\n />\n }\n />\n <Route path=\"categories\" element={<CategoriesContent />} />\n <Route path=\"tags\" element={<TagsContent />} />\n </Route>\n </Routes>\n );\n};\n\nexport const OldFrontendSystemCompatibleRouter = (props: RouterProps) => {\n return compatWrapper(<Router {...props} />);\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAuCa,MAAA,MAAA,GAAS,CAAC,KAAuB,KAAA;AAC5C,EAAA,MAAM,iBAA4C,GAAA;AAAA,IAChD,KAAO,EAAA,eAAA;AAAA,IACP,WAAa,EAAA,KAAA;AAAA,IACb,gBAAkB,EAAA,WAAA;AAAA,IAClB,GAAG;AAAA,GACL;AAEA,EAAA,4BACG,MACC,EAAA,EAAA,QAAA,EAAA;AAAA,oBAAC,GAAA,CAAA,KAAA,EAAA,EAAM,MAAK,GAAI,EAAA,OAAA,sBAAU,iBAAmB,EAAA,EAAA,GAAG,mBAAmB,CAAI,EAAA,CAAA;AAAA,oBACvE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,IAAK,EAAA,WAAA;AAAA,QACL,OACE,kBAAA,GAAA;AAAA,UAAC,oBAAA;AAAA,UAAA;AAAA,YACC,kBAAkB,iBAAkB,CAAA,gBAAA;AAAA,YACpC,OAAO,iBAAkB,CAAA;AAAA;AAAA;AAC3B;AAAA,KAEJ;AAAA,oBACA,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,IAAK,EAAA,QAAA;AAAA,QACL,OACE,kBAAA,GAAA,CAAC,iBAAkB,EAAA,EAAA,UAAA,EAAY,4BAC7B,EAAA,QAAA,kBAAA,GAAA;AAAA,UAAC,sBAAA;AAAA,UAAA;AAAA,YACC,OAAO,KAAM,CAAA,KAAA;AAAA,YACb,iBAAiB,KAAM,CAAA;AAAA;AAAA,SAE3B,EAAA,CAAA;AAAA,QAGF,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,IAAK,EAAA,EAAA;AAAA,cACL,OACE,kBAAA,GAAA;AAAA,gBAAC,oBAAA;AAAA,gBAAA;AAAA,kBACC,YAAc,EAAA,EAAE,eAAiB,EAAA,KAAA,CAAM,eAAgB;AAAA;AAAA;AACzD;AAAA,WAEJ;AAAA,8BACC,KAAM,EAAA,EAAA,IAAA,EAAK,cAAa,OAAS,kBAAA,GAAA,CAAC,qBAAkB,CAAI,EAAA,CAAA;AAAA,8BACxD,KAAM,EAAA,EAAA,IAAA,EAAK,QAAO,OAAS,kBAAA,GAAA,CAAC,eAAY,CAAI,EAAA;AAAA;AAAA;AAAA;AAC/C,GACF,EAAA,CAAA;AAEJ;AAEa,MAAA,iCAAA,GAAoC,CAAC,KAAuB,KAAA;AACvE,EAAA,OAAO,aAAc,iBAAA,GAAA,CAAC,MAAQ,EAAA,EAAA,GAAG,OAAO,CAAE,CAAA;AAC5C;;;;"}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import MDEditor from '@uiw/react-md-editor';
|
|
4
|
+
import { DateTime } from 'luxon';
|
|
5
|
+
import slugify from 'slugify';
|
|
6
|
+
import { useApi, identityApiRef, alertApiRef } from '@backstage/core-plugin-api';
|
|
7
|
+
import { Card, CardHeader, Text, CardBody, Box, Grid, TextField, Flex, Button, Switch } from '@backstage/ui';
|
|
8
|
+
import { RiAddLine, RiSave2Line } from '@remixicon/react';
|
|
9
|
+
import { announcementsApiRef, useAnnouncementsTranslation, useCategories, useTags } from '@backstage-community/plugin-announcements-react';
|
|
10
|
+
import '@backstage/frontend-plugin-api';
|
|
11
|
+
import '../../../../../routes.esm.js';
|
|
12
|
+
import '@backstage/plugin-catalog-react';
|
|
13
|
+
import 'react-router-dom';
|
|
14
|
+
import { CategorySelectInput } from '../../../shared/CategorySelectInput/CategorySelectInput.esm.js';
|
|
15
|
+
import { TagsSelectInput } from '../../../shared/TagsSelectInput/TagsSelectInput.esm.js';
|
|
16
|
+
import { CreateCategoryDialog } from '../../categories/CreateCategoryDialog.esm.js';
|
|
17
|
+
import { CreateTagDialog } from '../../tags/CreateTagDialog.esm.js';
|
|
18
|
+
import OnBehalfTeamDropdown from './OnBehalfTeamDropdown.esm.js';
|
|
19
|
+
import MuiTextField from '@mui/material/TextField';
|
|
20
|
+
|
|
21
|
+
const AnnouncementForm = ({
|
|
22
|
+
initialData,
|
|
23
|
+
onSubmit
|
|
24
|
+
}) => {
|
|
25
|
+
const identityApi = useApi(identityApiRef);
|
|
26
|
+
const announcementsApi = useApi(announcementsApiRef);
|
|
27
|
+
const alertApi = useApi(alertApiRef);
|
|
28
|
+
const { t } = useAnnouncementsTranslation();
|
|
29
|
+
const {
|
|
30
|
+
categories,
|
|
31
|
+
loading: categoriesLoading,
|
|
32
|
+
retry: refreshCategories
|
|
33
|
+
} = useCategories();
|
|
34
|
+
const { tags, loading: tagsLoading, retry: refreshTags } = useTags();
|
|
35
|
+
const formattedStartAt = initialData.start_at ? DateTime.fromISO(initialData.start_at).toISODate() : DateTime.now().toISODate();
|
|
36
|
+
const formattedUntilDate = initialData.until_date ? DateTime.fromISO(initialData.until_date).toISODate() : DateTime.now().endOf("day").plus({ days: 7 }).toISODate();
|
|
37
|
+
const [form, setForm] = useState({
|
|
38
|
+
...initialData,
|
|
39
|
+
active: initialData.active ?? true,
|
|
40
|
+
category: initialData.category ?? null,
|
|
41
|
+
start_at: formattedStartAt || "",
|
|
42
|
+
until_date: formattedUntilDate || "",
|
|
43
|
+
tags: initialData.tags ?? null,
|
|
44
|
+
sendNotification: initialData.sendNotification ?? false
|
|
45
|
+
});
|
|
46
|
+
const [loading, setLoading] = useState(false);
|
|
47
|
+
const [onBehalfOfSelectedTeam, setOnBehalfOfSelectedTeam] = useState(
|
|
48
|
+
initialData.on_behalf_of || ""
|
|
49
|
+
);
|
|
50
|
+
const [showCreateCategoryDialog, setShowCreateCategoryDialog] = useState(false);
|
|
51
|
+
const [showCreateTagDialog, setShowCreateTagDialog] = useState(false);
|
|
52
|
+
const handleCreateCategory = async (request) => {
|
|
53
|
+
const slugifiedTitle = slugify(request.title.trim(), { lower: true });
|
|
54
|
+
const existingCategory = categories.find(
|
|
55
|
+
(cat) => cat.slug === slugifiedTitle
|
|
56
|
+
);
|
|
57
|
+
if (existingCategory) {
|
|
58
|
+
alertApi.post({
|
|
59
|
+
message: t("categoriesForm.errors.alreadyExists"),
|
|
60
|
+
severity: "warning"
|
|
61
|
+
});
|
|
62
|
+
setForm((prevForm) => ({
|
|
63
|
+
...prevForm,
|
|
64
|
+
category: existingCategory
|
|
65
|
+
}));
|
|
66
|
+
setShowCreateCategoryDialog(false);
|
|
67
|
+
} else {
|
|
68
|
+
try {
|
|
69
|
+
await announcementsApi.createCategory(request);
|
|
70
|
+
alertApi.post({
|
|
71
|
+
message: t("newCategoryDialog.createdMessage"),
|
|
72
|
+
severity: "success"
|
|
73
|
+
});
|
|
74
|
+
setShowCreateCategoryDialog(false);
|
|
75
|
+
refreshCategories();
|
|
76
|
+
setForm((prevForm) => ({
|
|
77
|
+
...prevForm,
|
|
78
|
+
category: {
|
|
79
|
+
title: request.title,
|
|
80
|
+
slug: slugifiedTitle
|
|
81
|
+
}
|
|
82
|
+
}));
|
|
83
|
+
} catch (err) {
|
|
84
|
+
alertApi.post({ message: err.message, severity: "error" });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const handleCreateTag = async (request) => {
|
|
89
|
+
const slugifiedTitle = slugify(request.title.trim(), { lower: true });
|
|
90
|
+
const existingTag = tags?.find((tag) => tag.slug === slugifiedTitle);
|
|
91
|
+
if (existingTag) {
|
|
92
|
+
alertApi.post({
|
|
93
|
+
message: t("tagsForm.errors.alreadyExists"),
|
|
94
|
+
severity: "warning"
|
|
95
|
+
});
|
|
96
|
+
setForm((prevForm) => ({
|
|
97
|
+
...prevForm,
|
|
98
|
+
tags: [...prevForm.tags ?? [], existingTag]
|
|
99
|
+
}));
|
|
100
|
+
setShowCreateTagDialog(false);
|
|
101
|
+
} else {
|
|
102
|
+
try {
|
|
103
|
+
await announcementsApi.createTag(request);
|
|
104
|
+
alertApi.post({
|
|
105
|
+
message: t("newTagDialog.createdMessage"),
|
|
106
|
+
severity: "success"
|
|
107
|
+
});
|
|
108
|
+
setShowCreateTagDialog(false);
|
|
109
|
+
refreshTags();
|
|
110
|
+
const newTag = { title: request.title, slug: slugifiedTitle };
|
|
111
|
+
setForm((prevForm) => ({
|
|
112
|
+
...prevForm,
|
|
113
|
+
tags: [...prevForm.tags ?? [], newTag]
|
|
114
|
+
}));
|
|
115
|
+
} catch (err) {
|
|
116
|
+
alertApi.post({ message: err.message, severity: "error" });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
const handleSubmit = async (event) => {
|
|
121
|
+
setLoading(true);
|
|
122
|
+
event.preventDefault();
|
|
123
|
+
const userIdentity = await identityApi.getBackstageIdentity();
|
|
124
|
+
const {
|
|
125
|
+
id,
|
|
126
|
+
created_at,
|
|
127
|
+
category,
|
|
128
|
+
tags: formTags,
|
|
129
|
+
...announcementData
|
|
130
|
+
} = form;
|
|
131
|
+
const createRequest = {
|
|
132
|
+
...announcementData,
|
|
133
|
+
category: category?.slug,
|
|
134
|
+
tags: formTags?.map((tag) => tag.slug),
|
|
135
|
+
publisher: userIdentity.userEntityRef,
|
|
136
|
+
on_behalf_of: onBehalfOfSelectedTeam
|
|
137
|
+
};
|
|
138
|
+
try {
|
|
139
|
+
await onSubmit(createRequest);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
throw error;
|
|
142
|
+
} finally {
|
|
143
|
+
setLoading(false);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
147
|
+
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(Text, { variant: "title-small", children: initialData.title ? t("announcementForm.editAnnouncement") : t("announcementForm.newAnnouncement") }) }),
|
|
148
|
+
/* @__PURE__ */ jsx(CardBody, { children: /* @__PURE__ */ jsx(Box, { p: "3", children: /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs(Grid.Root, { columns: "12", children: [
|
|
149
|
+
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "12", children: /* @__PURE__ */ jsx(
|
|
150
|
+
TextField,
|
|
151
|
+
{
|
|
152
|
+
label: t("announcementForm.title"),
|
|
153
|
+
value: form.title,
|
|
154
|
+
onChange: (title) => setForm({ ...form, title }),
|
|
155
|
+
isRequired: true
|
|
156
|
+
}
|
|
157
|
+
) }),
|
|
158
|
+
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "12", children: /* @__PURE__ */ jsx(
|
|
159
|
+
TextField,
|
|
160
|
+
{
|
|
161
|
+
label: t("announcementForm.excerpt"),
|
|
162
|
+
value: form.excerpt,
|
|
163
|
+
onChange: (excerpt) => setForm({ ...form, excerpt }),
|
|
164
|
+
isRequired: true
|
|
165
|
+
}
|
|
166
|
+
) }),
|
|
167
|
+
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "12", children: /* @__PURE__ */ jsx(
|
|
168
|
+
MDEditor,
|
|
169
|
+
{
|
|
170
|
+
value: form.body,
|
|
171
|
+
style: { minHeight: "30rem" },
|
|
172
|
+
onChange: (value) => setForm({ ...form, ...{ body: value || "" } })
|
|
173
|
+
}
|
|
174
|
+
) }),
|
|
175
|
+
/* @__PURE__ */ jsx(Grid.Item, { colSpan: { xs: "12", md: "4" }, children: /* @__PURE__ */ jsxs(Flex, { gap: "2", align: "end", children: [
|
|
176
|
+
/* @__PURE__ */ jsx(Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(
|
|
177
|
+
CategorySelectInput,
|
|
178
|
+
{
|
|
179
|
+
initialCategory: form.category ?? void 0,
|
|
180
|
+
categories,
|
|
181
|
+
isLoading: categoriesLoading,
|
|
182
|
+
setCategory: (category) => setForm((prev) => ({ ...prev, category }))
|
|
183
|
+
}
|
|
184
|
+
) }),
|
|
185
|
+
/* @__PURE__ */ jsx(
|
|
186
|
+
Button,
|
|
187
|
+
{
|
|
188
|
+
"data-testid": "create-category-icon-button",
|
|
189
|
+
variant: "secondary",
|
|
190
|
+
size: "small",
|
|
191
|
+
iconStart: /* @__PURE__ */ jsx(RiAddLine, {}),
|
|
192
|
+
onClick: () => setShowCreateCategoryDialog(true),
|
|
193
|
+
"aria-label": t("admin.categoriesContent.createButton")
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
] }) }),
|
|
197
|
+
/* @__PURE__ */ jsx(Grid.Item, { colSpan: { xs: "12", md: "4" }, children: /* @__PURE__ */ jsx(
|
|
198
|
+
OnBehalfTeamDropdown,
|
|
199
|
+
{
|
|
200
|
+
selectedTeam: onBehalfOfSelectedTeam,
|
|
201
|
+
onChange: setOnBehalfOfSelectedTeam
|
|
202
|
+
}
|
|
203
|
+
) }),
|
|
204
|
+
/* @__PURE__ */ jsx(Grid.Item, { colSpan: { xs: "12", md: "4" }, children: /* @__PURE__ */ jsxs(Flex, { gap: "2", align: "end", children: [
|
|
205
|
+
/* @__PURE__ */ jsx(Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(
|
|
206
|
+
TagsSelectInput,
|
|
207
|
+
{
|
|
208
|
+
initialTags: form.tags ?? void 0,
|
|
209
|
+
tags,
|
|
210
|
+
isLoading: tagsLoading,
|
|
211
|
+
setTags: (selectedTags) => setForm((prev) => ({ ...prev, tags: selectedTags }))
|
|
212
|
+
}
|
|
213
|
+
) }),
|
|
214
|
+
/* @__PURE__ */ jsx(
|
|
215
|
+
Button,
|
|
216
|
+
{
|
|
217
|
+
"data-testid": "create-tag-icon-button",
|
|
218
|
+
variant: "secondary",
|
|
219
|
+
size: "small",
|
|
220
|
+
iconStart: /* @__PURE__ */ jsx(RiAddLine, {}),
|
|
221
|
+
onClick: () => setShowCreateTagDialog(true),
|
|
222
|
+
"aria-label": t("admin.tagsContent.createButton")
|
|
223
|
+
}
|
|
224
|
+
)
|
|
225
|
+
] }) }),
|
|
226
|
+
/* @__PURE__ */ jsx(Grid.Item, { colSpan: { xs: "12", md: "4" }, children: /* @__PURE__ */ jsx(
|
|
227
|
+
MuiTextField,
|
|
228
|
+
{
|
|
229
|
+
variant: "outlined",
|
|
230
|
+
label: t("announcementForm.startAt"),
|
|
231
|
+
id: "start-at-date",
|
|
232
|
+
type: "date",
|
|
233
|
+
value: form.start_at,
|
|
234
|
+
InputLabelProps: { shrink: true },
|
|
235
|
+
required: true,
|
|
236
|
+
fullWidth: true,
|
|
237
|
+
onChange: (e) => setForm({
|
|
238
|
+
...form,
|
|
239
|
+
start_at: e.target.value
|
|
240
|
+
})
|
|
241
|
+
}
|
|
242
|
+
) }),
|
|
243
|
+
/* @__PURE__ */ jsx(Grid.Item, { colSpan: { xs: "12", md: "4" }, children: /* @__PURE__ */ jsx(
|
|
244
|
+
MuiTextField,
|
|
245
|
+
{
|
|
246
|
+
variant: "outlined",
|
|
247
|
+
label: t("announcementForm.untilDate"),
|
|
248
|
+
id: "until-date",
|
|
249
|
+
type: "date",
|
|
250
|
+
value: form.until_date,
|
|
251
|
+
InputLabelProps: { shrink: true },
|
|
252
|
+
fullWidth: true,
|
|
253
|
+
onChange: (e) => setForm({
|
|
254
|
+
...form,
|
|
255
|
+
until_date: e.target.value
|
|
256
|
+
}),
|
|
257
|
+
inputProps: {
|
|
258
|
+
min: DateTime.fromISO(form.start_at).endOf("day").plus({ days: 1 }).toISODate()
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
) }),
|
|
262
|
+
/* @__PURE__ */ jsx(Grid.Item, { colSpan: "12", children: /* @__PURE__ */ jsxs(Flex, { justify: "end", children: [
|
|
263
|
+
/* @__PURE__ */ jsx(
|
|
264
|
+
Switch,
|
|
265
|
+
{
|
|
266
|
+
name: "active",
|
|
267
|
+
label: t("announcementForm.active"),
|
|
268
|
+
isSelected: form.active,
|
|
269
|
+
onChange: (isSelected) => setForm({ ...form, active: isSelected })
|
|
270
|
+
}
|
|
271
|
+
),
|
|
272
|
+
/* @__PURE__ */ jsx(
|
|
273
|
+
Switch,
|
|
274
|
+
{
|
|
275
|
+
name: "sendNotification",
|
|
276
|
+
label: t("announcementForm.sendNotification"),
|
|
277
|
+
isSelected: form.sendNotification,
|
|
278
|
+
onChange: (isSelected) => setForm({ ...form, sendNotification: isSelected })
|
|
279
|
+
}
|
|
280
|
+
),
|
|
281
|
+
/* @__PURE__ */ jsx(
|
|
282
|
+
Button,
|
|
283
|
+
{
|
|
284
|
+
type: "submit",
|
|
285
|
+
isDisabled: loading || !form.body,
|
|
286
|
+
iconStart: /* @__PURE__ */ jsx(RiSave2Line, {}),
|
|
287
|
+
children: t("announcementForm.submit")
|
|
288
|
+
}
|
|
289
|
+
)
|
|
290
|
+
] }) })
|
|
291
|
+
] }) }) }) }),
|
|
292
|
+
/* @__PURE__ */ jsx(
|
|
293
|
+
CreateCategoryDialog,
|
|
294
|
+
{
|
|
295
|
+
open: showCreateCategoryDialog,
|
|
296
|
+
onConfirm: handleCreateCategory,
|
|
297
|
+
onCancel: () => setShowCreateCategoryDialog(false)
|
|
298
|
+
}
|
|
299
|
+
),
|
|
300
|
+
/* @__PURE__ */ jsx(
|
|
301
|
+
CreateTagDialog,
|
|
302
|
+
{
|
|
303
|
+
open: showCreateTagDialog,
|
|
304
|
+
onConfirm: handleCreateTag,
|
|
305
|
+
onCancel: () => setShowCreateTagDialog(false)
|
|
306
|
+
}
|
|
307
|
+
)
|
|
308
|
+
] });
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
export { AnnouncementForm };
|
|
312
|
+
//# sourceMappingURL=AnnouncementForm.esm.js.map
|
package/dist/alpha/components/admin/announcements/AnnouncementForm/AnnouncementForm.esm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnnouncementForm.esm.js","sources":["../../../../../../src/alpha/components/admin/announcements/AnnouncementForm/AnnouncementForm.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 { useState, type FormEvent } from 'react';\nimport MDEditor from '@uiw/react-md-editor';\nimport { DateTime } from 'luxon';\nimport slugify from 'slugify';\nimport {\n identityApiRef,\n useApi,\n alertApiRef,\n} from '@backstage/core-plugin-api';\nimport {\n Box,\n Button,\n Card,\n CardBody,\n CardHeader,\n Flex,\n Grid,\n Text,\n TextField,\n Switch,\n} from '@backstage/ui';\nimport { RiSave2Line, RiAddLine } from '@remixicon/react';\nimport {\n CreateAnnouncementRequest,\n CreateCategoryRequest,\n CreateTagRequest,\n useAnnouncementsTranslation,\n announcementsApiRef,\n useCategories,\n useTags,\n} from '@backstage-community/plugin-announcements-react';\nimport {\n Announcement,\n Category,\n Tag,\n} from '@backstage-community/plugin-announcements-common';\n\nimport { CategorySelectInput, TagsSelectInput } from '../../../shared';\nimport { CreateCategoryDialog } from '../../categories';\nimport { CreateTagDialog } from '../../tags';\nimport OnBehalfTeamDropdown from './OnBehalfTeamDropdown';\n\nimport MuiTextField from '@mui/material/TextField';\n\ntype AnnouncementFormProps = {\n initialData: Announcement;\n onSubmit: (data: CreateAnnouncementRequest) => Promise<void>;\n};\n\nexport const AnnouncementForm = ({\n initialData,\n onSubmit,\n}: AnnouncementFormProps) => {\n const identityApi = useApi(identityApiRef);\n const announcementsApi = useApi(announcementsApiRef);\n const alertApi = useApi(alertApiRef);\n const { t } = useAnnouncementsTranslation();\n const {\n categories,\n loading: categoriesLoading,\n retry: refreshCategories,\n } = useCategories();\n const { tags, loading: tagsLoading, retry: refreshTags } = useTags();\n\n const formattedStartAt = initialData.start_at\n ? DateTime.fromISO(initialData.start_at).toISODate()\n : DateTime.now().toISODate();\n\n const formattedUntilDate = initialData.until_date\n ? DateTime.fromISO(initialData.until_date).toISODate()\n : DateTime.now().endOf('day').plus({ days: 7 }).toISODate();\n\n const [form, setForm] = useState({\n ...initialData,\n active: initialData.active ?? true,\n category: initialData.category ?? null,\n start_at: formattedStartAt || '',\n until_date: formattedUntilDate || '',\n tags: initialData.tags ?? null,\n sendNotification: initialData.sendNotification ?? false,\n });\n const [loading, setLoading] = useState(false);\n const [onBehalfOfSelectedTeam, setOnBehalfOfSelectedTeam] = useState(\n initialData.on_behalf_of || '',\n );\n const [showCreateCategoryDialog, setShowCreateCategoryDialog] =\n useState(false);\n const [showCreateTagDialog, setShowCreateTagDialog] = useState(false);\n\n const handleCreateCategory = async (request: CreateCategoryRequest) => {\n const slugifiedTitle = slugify(request.title.trim(), { lower: true });\n const existingCategory = categories.find(\n cat => cat.slug === slugifiedTitle,\n );\n\n if (existingCategory) {\n alertApi.post({\n message: t('categoriesForm.errors.alreadyExists'),\n severity: 'warning',\n });\n\n // Select the existing category in the form\n setForm(prevForm => ({\n ...prevForm,\n category: existingCategory,\n }));\n\n setShowCreateCategoryDialog(false);\n } else {\n try {\n await announcementsApi.createCategory(request);\n\n alertApi.post({\n message: t('newCategoryDialog.createdMessage'),\n severity: 'success',\n });\n\n setShowCreateCategoryDialog(false);\n refreshCategories();\n\n // Select the new category in the form\n setForm(prevForm => ({\n ...prevForm,\n category: {\n title: request.title,\n slug: slugifiedTitle,\n },\n }));\n } catch (err) {\n alertApi.post({ message: (err as Error).message, severity: 'error' });\n }\n }\n };\n\n const handleCreateTag = async (request: CreateTagRequest) => {\n const slugifiedTitle = slugify(request.title.trim(), { lower: true });\n const existingTag = tags?.find(tag => tag.slug === slugifiedTitle);\n\n if (existingTag) {\n alertApi.post({\n message: t('tagsForm.errors.alreadyExists'),\n severity: 'warning',\n });\n\n setForm(prevForm => ({\n ...prevForm,\n tags: [...(prevForm.tags ?? []), existingTag],\n }));\n\n setShowCreateTagDialog(false);\n } else {\n try {\n await announcementsApi.createTag(request);\n\n alertApi.post({\n message: t('newTagDialog.createdMessage'),\n severity: 'success',\n });\n\n setShowCreateTagDialog(false);\n refreshTags();\n\n const newTag = { title: request.title, slug: slugifiedTitle };\n\n setForm(prevForm => ({\n ...prevForm,\n tags: [...(prevForm.tags ?? []), newTag],\n }));\n } catch (err) {\n alertApi.post({ message: (err as Error).message, severity: 'error' });\n }\n }\n };\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n setLoading(true);\n event.preventDefault();\n\n const userIdentity = await identityApi.getBackstageIdentity();\n\n const {\n id,\n created_at,\n category,\n tags: formTags,\n ...announcementData\n } = form;\n\n const createRequest: CreateAnnouncementRequest = {\n ...announcementData,\n category: category?.slug,\n tags: formTags?.map(tag => tag.slug),\n publisher: userIdentity.userEntityRef,\n on_behalf_of: onBehalfOfSelectedTeam,\n };\n\n try {\n await onSubmit(createRequest);\n } catch (error) {\n throw error;\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <Card>\n <CardHeader>\n <Text variant=\"title-small\">\n {initialData.title\n ? t('announcementForm.editAnnouncement')\n : t('announcementForm.newAnnouncement')}\n </Text>\n </CardHeader>\n\n <CardBody>\n <Box p=\"3\">\n <form onSubmit={handleSubmit}>\n <Grid.Root columns=\"12\">\n <Grid.Item colSpan=\"12\">\n <TextField\n label={t('announcementForm.title')}\n value={form.title}\n onChange={title => setForm({ ...form, title })}\n isRequired\n />\n </Grid.Item>\n\n <Grid.Item colSpan=\"12\">\n <TextField\n label={t('announcementForm.excerpt')}\n value={form.excerpt}\n onChange={excerpt => setForm({ ...form, excerpt })}\n isRequired\n />\n </Grid.Item>\n\n <Grid.Item colSpan=\"12\">\n <MDEditor\n value={form.body}\n style={{ minHeight: '30rem' }}\n onChange={value =>\n setForm({ ...form, ...{ body: value || '' } })\n }\n />\n </Grid.Item>\n\n <Grid.Item colSpan={{ xs: '12', md: '4' }}>\n <Flex gap=\"2\" align=\"end\">\n <Box style={{ flex: 1 }}>\n <CategorySelectInput\n initialCategory={form.category ?? undefined}\n categories={categories}\n isLoading={categoriesLoading}\n setCategory={(category: Category | null) =>\n setForm(prev => ({ ...prev, category }))\n }\n />\n </Box>\n\n <Button\n data-testid=\"create-category-icon-button\"\n variant=\"secondary\"\n size=\"small\"\n iconStart={<RiAddLine />}\n onClick={() => setShowCreateCategoryDialog(true)}\n aria-label={t('admin.categoriesContent.createButton')}\n />\n </Flex>\n </Grid.Item>\n\n <Grid.Item colSpan={{ xs: '12', md: '4' }}>\n <OnBehalfTeamDropdown\n selectedTeam={onBehalfOfSelectedTeam}\n onChange={setOnBehalfOfSelectedTeam}\n />\n </Grid.Item>\n\n <Grid.Item colSpan={{ xs: '12', md: '4' }}>\n <Flex gap=\"2\" align=\"end\">\n <Box style={{ flex: 1 }}>\n <TagsSelectInput\n initialTags={form.tags ?? undefined}\n tags={tags}\n isLoading={tagsLoading}\n setTags={(selectedTags: Tag[] | null) =>\n setForm(prev => ({ ...prev, tags: selectedTags }))\n }\n />\n </Box>\n\n <Button\n data-testid=\"create-tag-icon-button\"\n variant=\"secondary\"\n size=\"small\"\n iconStart={<RiAddLine />}\n onClick={() => setShowCreateTagDialog(true)}\n aria-label={t('admin.tagsContent.createButton')}\n />\n </Flex>\n </Grid.Item>\n\n <Grid.Item colSpan={{ xs: '12', md: '4' }}>\n <MuiTextField\n variant=\"outlined\"\n label={t('announcementForm.startAt')}\n id=\"start-at-date\"\n type=\"date\"\n value={form.start_at}\n InputLabelProps={{ shrink: true }}\n required\n fullWidth\n onChange={e =>\n setForm({\n ...form,\n start_at: e.target.value,\n })\n }\n />\n </Grid.Item>\n\n <Grid.Item colSpan={{ xs: '12', md: '4' }}>\n <MuiTextField\n variant=\"outlined\"\n label={t('announcementForm.untilDate')}\n id=\"until-date\"\n type=\"date\"\n value={form.until_date}\n InputLabelProps={{ shrink: true }}\n fullWidth\n onChange={e =>\n setForm({\n ...form,\n until_date: e.target.value,\n })\n }\n inputProps={{\n min: DateTime.fromISO(form.start_at)\n .endOf('day')\n .plus({ days: 1 })\n .toISODate(),\n }}\n />\n </Grid.Item>\n\n <Grid.Item colSpan=\"12\">\n <Flex justify=\"end\">\n <Switch\n name=\"active\"\n label={t('announcementForm.active')}\n isSelected={form.active}\n onChange={isSelected =>\n setForm({ ...form, active: isSelected })\n }\n />\n <Switch\n name=\"sendNotification\"\n label={t('announcementForm.sendNotification')}\n isSelected={form.sendNotification}\n onChange={isSelected =>\n setForm({ ...form, sendNotification: isSelected })\n }\n />\n <Button\n type=\"submit\"\n isDisabled={loading || !form.body}\n iconStart={<RiSave2Line />}\n >\n {t('announcementForm.submit')}\n </Button>\n </Flex>\n </Grid.Item>\n </Grid.Root>\n </form>\n </Box>\n </CardBody>\n\n <CreateCategoryDialog\n open={showCreateCategoryDialog}\n onConfirm={handleCreateCategory}\n onCancel={() => setShowCreateCategoryDialog(false)}\n />\n\n <CreateTagDialog\n open={showCreateTagDialog}\n onConfirm={handleCreateTag}\n onCancel={() => setShowCreateTagDialog(false)}\n />\n </Card>\n );\n};\n"],"names":[],"mappings":"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"}
|
package/dist/alpha/components/admin/announcements/AnnouncementForm/OnBehalfTeamDropdown.esm.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { Select } from '@backstage/ui';
|
|
4
|
+
import { useApi, identityApiRef } from '@backstage/core-plugin-api';
|
|
5
|
+
import { useAnnouncementsTranslation, useCatalogEntities } from '@backstage-community/plugin-announcements-react';
|
|
6
|
+
import useAsync from 'react-use/esm/useAsync';
|
|
7
|
+
import { stringifyEntityRef } from '@backstage/catalog-model';
|
|
8
|
+
|
|
9
|
+
function getTeamDisplayName(team) {
|
|
10
|
+
if (team.kind && team.kind.toLowerCase() === "group") {
|
|
11
|
+
return team.spec?.profile?.displayName ?? "";
|
|
12
|
+
}
|
|
13
|
+
return "";
|
|
14
|
+
}
|
|
15
|
+
function OnBehalfTeamDropdown({
|
|
16
|
+
selectedTeam,
|
|
17
|
+
onChange
|
|
18
|
+
}) {
|
|
19
|
+
const { t } = useAnnouncementsTranslation();
|
|
20
|
+
const identityApi = useApi(identityApiRef);
|
|
21
|
+
const { value: userOwns } = useAsync(async () => {
|
|
22
|
+
const identity = await identityApi.getBackstageIdentity();
|
|
23
|
+
return [identity.userEntityRef, ...identity.ownershipEntityRefs];
|
|
24
|
+
}, [identityApi]);
|
|
25
|
+
const { entities: teams, loading: teamsLoading } = useCatalogEntities(
|
|
26
|
+
userOwns,
|
|
27
|
+
// refs
|
|
28
|
+
"",
|
|
29
|
+
// searchTerm
|
|
30
|
+
"Group"
|
|
31
|
+
// kind
|
|
32
|
+
);
|
|
33
|
+
const selectOptions = useMemo(() => {
|
|
34
|
+
return teams.map((team) => {
|
|
35
|
+
const entityRef = stringifyEntityRef(team);
|
|
36
|
+
return {
|
|
37
|
+
value: entityRef,
|
|
38
|
+
label: getTeamDisplayName(team) ?? entityRef
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
}, [teams]);
|
|
42
|
+
const handleChange = (value) => {
|
|
43
|
+
if (!value) {
|
|
44
|
+
onChange("");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
let stringValue = null;
|
|
48
|
+
if (Array.isArray(value)) {
|
|
49
|
+
stringValue = String(value[0] ?? "");
|
|
50
|
+
} else {
|
|
51
|
+
stringValue = String(value);
|
|
52
|
+
}
|
|
53
|
+
onChange(stringValue || "");
|
|
54
|
+
};
|
|
55
|
+
return /* @__PURE__ */ jsx(
|
|
56
|
+
Select,
|
|
57
|
+
{
|
|
58
|
+
name: "team",
|
|
59
|
+
label: t("announcementForm.onBehalfOf"),
|
|
60
|
+
searchable: true,
|
|
61
|
+
placeholder: t("announcementForm.onBehalfOf"),
|
|
62
|
+
value: selectedTeam || null,
|
|
63
|
+
onChange: handleChange,
|
|
64
|
+
options: selectOptions,
|
|
65
|
+
isDisabled: teamsLoading || selectOptions.length === 0
|
|
66
|
+
},
|
|
67
|
+
selectedTeam || "none"
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { OnBehalfTeamDropdown as default };
|
|
72
|
+
//# sourceMappingURL=OnBehalfTeamDropdown.esm.js.map
|
package/dist/alpha/components/admin/announcements/AnnouncementForm/OnBehalfTeamDropdown.esm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OnBehalfTeamDropdown.esm.js","sources":["../../../../../../src/alpha/components/admin/announcements/AnnouncementForm/OnBehalfTeamDropdown.tsx"],"sourcesContent":["/*\n * Copyright 2025 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 { Key, useMemo } from 'react';\nimport { Select } from '@backstage/ui';\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\nimport {\n useAnnouncementsTranslation,\n useCatalogEntities,\n} from '@backstage-community/plugin-announcements-react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\n\ntype OnBehalfTeamDropdownProps = {\n selectedTeam: string;\n onChange: (team: string) => void;\n};\n\nfunction getTeamDisplayName(team: any): string {\n if (team.kind && team.kind.toLowerCase() === 'group') {\n return team.spec?.profile?.displayName ?? '';\n }\n return '';\n}\n\nexport default function OnBehalfTeamDropdown({\n selectedTeam,\n onChange,\n}: OnBehalfTeamDropdownProps) {\n const { t } = useAnnouncementsTranslation();\n const identityApi = useApi(identityApiRef);\n\n const { value: userOwns } = useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n return [identity.userEntityRef, ...identity.ownershipEntityRefs];\n }, [identityApi]);\n\n const { entities: teams, loading: teamsLoading } = useCatalogEntities(\n userOwns, // refs\n '', // searchTerm\n 'Group', // kind\n );\n\n const selectOptions = useMemo(() => {\n return teams.map(team => {\n const entityRef = stringifyEntityRef(team);\n return {\n value: entityRef,\n label: getTeamDisplayName(team) ?? entityRef,\n };\n });\n }, [teams]);\n\n const handleChange = (value: Key[] | Key | null) => {\n if (!value) {\n onChange('');\n return;\n }\n\n let stringValue: string | null = null;\n\n if (Array.isArray(value)) {\n stringValue = String(value[0] ?? '');\n } else {\n stringValue = String(value);\n }\n\n onChange(stringValue || '');\n };\n\n return (\n <Select\n key={selectedTeam || 'none'}\n name=\"team\"\n label={t('announcementForm.onBehalfOf')}\n searchable\n placeholder={t('announcementForm.onBehalfOf')}\n value={selectedTeam || null}\n onChange={handleChange}\n options={selectOptions}\n isDisabled={teamsLoading || selectOptions.length === 0}\n />\n );\n}\n"],"names":[],"mappings":";;;;;;;;AA8BA,SAAS,mBAAmB,IAAmB,EAAA;AAC7C,EAAA,IAAI,KAAK,IAAQ,IAAA,IAAA,CAAK,IAAK,CAAA,WAAA,OAAkB,OAAS,EAAA;AACpD,IAAO,OAAA,IAAA,CAAK,IAAM,EAAA,OAAA,EAAS,WAAe,IAAA,EAAA;AAAA;AAE5C,EAAO,OAAA,EAAA;AACT;AAEA,SAAwB,oBAAqB,CAAA;AAAA,EAC3C,YAAA;AAAA,EACA;AACF,CAA8B,EAAA;AAC5B,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,2BAA4B,EAAA;AAC1C,EAAM,MAAA,WAAA,GAAc,OAAO,cAAc,CAAA;AAEzC,EAAA,MAAM,EAAE,KAAA,EAAO,QAAS,EAAA,GAAI,SAAS,YAAY;AAC/C,IAAM,MAAA,QAAA,GAAW,MAAM,WAAA,CAAY,oBAAqB,EAAA;AACxD,IAAA,OAAO,CAAC,QAAA,CAAS,aAAe,EAAA,GAAG,SAAS,mBAAmB,CAAA;AAAA,GACjE,EAAG,CAAC,WAAW,CAAC,CAAA;AAEhB,EAAA,MAAM,EAAE,QAAA,EAAU,KAAO,EAAA,OAAA,EAAS,cAAiB,GAAA,kBAAA;AAAA,IACjD,QAAA;AAAA;AAAA,IACA,EAAA;AAAA;AAAA,IACA;AAAA;AAAA,GACF;AAEA,EAAM,MAAA,aAAA,GAAgB,QAAQ,MAAM;AAClC,IAAO,OAAA,KAAA,CAAM,IAAI,CAAQ,IAAA,KAAA;AACvB,MAAM,MAAA,SAAA,GAAY,mBAAmB,IAAI,CAAA;AACzC,MAAO,OAAA;AAAA,QACL,KAAO,EAAA,SAAA;AAAA,QACP,KAAA,EAAO,kBAAmB,CAAA,IAAI,CAAK,IAAA;AAAA,OACrC;AAAA,KACD,CAAA;AAAA,GACH,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAM,MAAA,YAAA,GAAe,CAAC,KAA8B,KAAA;AAClD,IAAA,IAAI,CAAC,KAAO,EAAA;AACV,MAAA,QAAA,CAAS,EAAE,CAAA;AACX,MAAA;AAAA;AAGF,IAAA,IAAI,WAA6B,GAAA,IAAA;AAEjC,IAAI,IAAA,KAAA,CAAM,OAAQ,CAAA,KAAK,CAAG,EAAA;AACxB,MAAA,WAAA,GAAc,MAAO,CAAA,KAAA,CAAM,CAAC,CAAA,IAAK,EAAE,CAAA;AAAA,KAC9B,MAAA;AACL,MAAA,WAAA,GAAc,OAAO,KAAK,CAAA;AAAA;AAG5B,IAAA,QAAA,CAAS,eAAe,EAAE,CAAA;AAAA,GAC5B;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MAEC,IAAK,EAAA,MAAA;AAAA,MACL,KAAA,EAAO,EAAE,6BAA6B,CAAA;AAAA,MACtC,UAAU,EAAA,IAAA;AAAA,MACV,WAAA,EAAa,EAAE,6BAA6B,CAAA;AAAA,MAC5C,OAAO,YAAgB,IAAA,IAAA;AAAA,MACvB,QAAU,EAAA,YAAA;AAAA,MACV,OAAS,EAAA,aAAA;AAAA,MACT,UAAA,EAAY,YAAgB,IAAA,aAAA,CAAc,MAAW,KAAA;AAAA,KAAA;AAAA,IARhD,YAAgB,IAAA;AAAA,GASvB;AAEJ;;;;"}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { useState, useMemo } from 'react';
|
|
3
3
|
import { useApi, alertApiRef } from '@backstage/core-plugin-api';
|
|
4
|
-
import { announcementsApiRef, useAnnouncementsTranslation, useAnnouncementsPermissions,
|
|
4
|
+
import { announcementsApiRef, useAnnouncementsTranslation, useAnnouncementsPermissions, useAnnouncements } from '@backstage-community/plugin-announcements-react';
|
|
5
5
|
import { announcementCreatePermission } from '@backstage-community/plugin-announcements-common';
|
|
6
6
|
import { useRouteRef } from '@backstage/frontend-plugin-api';
|
|
7
7
|
import { useNavigate } from 'react-router-dom';
|
|
8
8
|
import { RequirePermission } from '@backstage/plugin-permission-react';
|
|
9
9
|
import { Grid, Box, Flex, Button } from '@backstage/ui';
|
|
10
|
-
import slugify from 'slugify';
|
|
11
10
|
import { useDeleteConfirmationDialogState } from '../shared/DeleteConfirmationDialog/useDeleteConfirmationDialogState.esm.js';
|
|
12
11
|
import { DeleteConfirmationDialog } from '../shared/DeleteConfirmationDialog/DeleteConfirmationDialog.esm.js';
|
|
13
|
-
import { AnnouncementForm } from '
|
|
12
|
+
import { AnnouncementForm } from './AnnouncementForm/AnnouncementForm.esm.js';
|
|
14
13
|
import { AnnouncementsTableCard } from './AnnouncementsTableCard.esm.js';
|
|
15
14
|
import { announcementViewRouteRef } from '../../../../routes.esm.js';
|
|
16
15
|
|
|
@@ -18,7 +17,7 @@ const AnnouncementFormContent = (props) => {
|
|
|
18
17
|
const { t } = useAnnouncementsTranslation();
|
|
19
18
|
const { onCancel, onSubmit, initialData } = props;
|
|
20
19
|
return /* @__PURE__ */ jsxs(Box, { mb: "2", children: [
|
|
21
|
-
/* @__PURE__ */ jsx(Flex, { justify: "end", align: "center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onCancel, children: t("admin.announcementsContent.cancelButton") }) }),
|
|
20
|
+
/* @__PURE__ */ jsx(Flex, { justify: "end", align: "center", pb: "3", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onCancel, children: t("admin.announcementsContent.cancelButton") }) }),
|
|
22
21
|
/* @__PURE__ */ jsx(AnnouncementForm, { initialData, onSubmit })
|
|
23
22
|
] });
|
|
24
23
|
};
|
|
@@ -29,7 +28,6 @@ const AnnouncementsContent = ({
|
|
|
29
28
|
const alertApi = useApi(alertApiRef);
|
|
30
29
|
const { t } = useAnnouncementsTranslation();
|
|
31
30
|
const permissions = useAnnouncementsPermissions();
|
|
32
|
-
const { categories } = useCategories();
|
|
33
31
|
const [showCreateAnnouncementForm, setShowCreateAnnouncementForm] = useState(false);
|
|
34
32
|
const [editingAnnouncementId, setEditingAnnouncementId] = useState(null);
|
|
35
33
|
const { announcements, retry: refresh } = useAnnouncements({});
|
|
@@ -53,29 +51,12 @@ const AnnouncementsContent = ({
|
|
|
53
51
|
setShowCreateAnnouncementForm(false);
|
|
54
52
|
};
|
|
55
53
|
const onSubmit = async (request) => {
|
|
56
|
-
const { category } = request;
|
|
57
|
-
const slugs = categories.map((c) => c.slug);
|
|
58
|
-
let alertMsg = t("admin.announcementsContent.alertMessage");
|
|
59
54
|
try {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (slugs.indexOf(categorySlug) === -1) {
|
|
65
|
-
alertMsg = alertMsg.replace(".", "");
|
|
66
|
-
alertMsg = `${alertMsg} ${t(
|
|
67
|
-
"admin.announcementsContent.alertMessageWithNewCategory"
|
|
68
|
-
)} ${category}.`;
|
|
69
|
-
await announcementsApi.createCategory({
|
|
70
|
-
title: category
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
await announcementsApi.createAnnouncement({
|
|
75
|
-
...request,
|
|
76
|
-
category: request.category?.toLocaleLowerCase("en-US")
|
|
55
|
+
await announcementsApi.createAnnouncement(request);
|
|
56
|
+
alertApi.post({
|
|
57
|
+
message: t("admin.announcementsContent.alertMessage"),
|
|
58
|
+
severity: "success"
|
|
77
59
|
});
|
|
78
|
-
alertApi.post({ message: alertMsg, severity: "success" });
|
|
79
60
|
setShowCreateAnnouncementForm(false);
|
|
80
61
|
refresh();
|
|
81
62
|
} catch (err) {
|
|
@@ -86,26 +67,12 @@ const AnnouncementsContent = ({
|
|
|
86
67
|
if (!editingAnnouncementId) {
|
|
87
68
|
return;
|
|
88
69
|
}
|
|
89
|
-
const { category } = request;
|
|
90
|
-
const slugs = categories.map((c) => c.slug);
|
|
91
|
-
let updateMsg = t("editAnnouncementPage.updatedMessage");
|
|
92
70
|
try {
|
|
93
|
-
if (category) {
|
|
94
|
-
const categorySlug = slugify(category, {
|
|
95
|
-
lower: true
|
|
96
|
-
});
|
|
97
|
-
if (slugs.indexOf(categorySlug) === -1) {
|
|
98
|
-
updateMsg = updateMsg.replace(".", "");
|
|
99
|
-
updateMsg = `${updateMsg} ${t(
|
|
100
|
-
"editAnnouncementPage.updatedMessageWithNewCategory"
|
|
101
|
-
)} ${category}.`;
|
|
102
|
-
await announcementsApi.createCategory({
|
|
103
|
-
title: category
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
71
|
await announcementsApi.updateAnnouncement(editingAnnouncementId, request);
|
|
108
|
-
alertApi.post({
|
|
72
|
+
alertApi.post({
|
|
73
|
+
message: t("editAnnouncementPage.updatedMessage"),
|
|
74
|
+
severity: "success"
|
|
75
|
+
});
|
|
109
76
|
setEditingAnnouncementId(null);
|
|
110
77
|
refresh();
|
|
111
78
|
} catch (err) {
|