@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
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import TextField from '@mui/material/TextField';
|
|
3
|
-
import Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete';
|
|
4
|
-
import { useCategories, useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';
|
|
5
|
-
import CircularProgress from '@mui/material/CircularProgress';
|
|
6
|
-
|
|
7
|
-
const filter = createFilterOptions();
|
|
8
|
-
function prepareCategoryFromInput(inputCategory, localizedCreate) {
|
|
9
|
-
return (typeof inputCategory === "string" ? inputCategory : inputCategory.title).replace(localizedCreate ? `${localizedCreate} ` : "Create ", "").replaceAll('"', "");
|
|
10
|
-
}
|
|
11
|
-
function CategoryInput({
|
|
12
|
-
setForm,
|
|
13
|
-
form,
|
|
14
|
-
initialValue
|
|
15
|
-
}) {
|
|
16
|
-
const { categories, loading: categoriesLoading } = useCategories();
|
|
17
|
-
const { t } = useAnnouncementsTranslation();
|
|
18
|
-
return /* @__PURE__ */ jsx(
|
|
19
|
-
Autocomplete,
|
|
20
|
-
{
|
|
21
|
-
fullWidth: true,
|
|
22
|
-
value: initialValue ?? "",
|
|
23
|
-
onChange: async (_, newValue) => {
|
|
24
|
-
if (!newValue) {
|
|
25
|
-
setForm({ ...form, category: void 0 });
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
const newCategory = prepareCategoryFromInput(
|
|
29
|
-
newValue,
|
|
30
|
-
t("announcementForm.categoryInput.create")
|
|
31
|
-
);
|
|
32
|
-
setForm({ ...form, category: newCategory });
|
|
33
|
-
},
|
|
34
|
-
filterOptions: (options, params) => {
|
|
35
|
-
const filtered = filter(options, params);
|
|
36
|
-
const { inputValue } = params;
|
|
37
|
-
const isExisting = options.some(
|
|
38
|
-
(option) => inputValue.toLocaleLowerCase("en-US") === option.title.toLocaleLowerCase("en-US")
|
|
39
|
-
);
|
|
40
|
-
if (inputValue !== "" && !isExisting) {
|
|
41
|
-
filtered.push({
|
|
42
|
-
title: `${t(
|
|
43
|
-
"announcementForm.categoryInput.create"
|
|
44
|
-
)} "${inputValue}"`,
|
|
45
|
-
slug: inputValue.toLocaleLowerCase("en-US")
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
return filtered;
|
|
49
|
-
},
|
|
50
|
-
selectOnFocus: true,
|
|
51
|
-
handleHomeEndKeys: true,
|
|
52
|
-
loading: categoriesLoading,
|
|
53
|
-
id: "category-input-field",
|
|
54
|
-
options: categories || [],
|
|
55
|
-
getOptionLabel: (option) => {
|
|
56
|
-
return prepareCategoryFromInput(option);
|
|
57
|
-
},
|
|
58
|
-
renderOption: (props, option) => /* @__PURE__ */ jsx("li", { ...props, children: option.title }),
|
|
59
|
-
freeSolo: true,
|
|
60
|
-
renderInput: (params) => /* @__PURE__ */ jsx(
|
|
61
|
-
TextField,
|
|
62
|
-
{
|
|
63
|
-
...params,
|
|
64
|
-
id: "category",
|
|
65
|
-
label: t("announcementForm.categoryInput.label"),
|
|
66
|
-
variant: "outlined",
|
|
67
|
-
fullWidth: true,
|
|
68
|
-
InputProps: {
|
|
69
|
-
...params.InputProps,
|
|
70
|
-
endAdornment: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
71
|
-
categoriesLoading ? /* @__PURE__ */ jsx(CircularProgress, { color: "inherit", size: 20 }) : null,
|
|
72
|
-
params.InputProps.endAdornment
|
|
73
|
-
] })
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
)
|
|
77
|
-
}
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export { CategoryInput as default };
|
|
82
|
-
//# sourceMappingURL=CategoryInput.esm.js.map
|
package/dist/components/Admin/AnnouncementsContent/AnnouncementForm/CategoryInput.esm.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CategoryInput.esm.js","sources":["../../../../../src/components/Admin/AnnouncementsContent/AnnouncementForm/CategoryInput.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 { SetStateAction } from 'react';\nimport TextField from '@mui/material/TextField';\nimport Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete';\nimport { Category } from '@backstage-community/plugin-announcements-common';\nimport {\n useAnnouncementsTranslation,\n useCategories,\n} from '@backstage-community/plugin-announcements-react';\nimport CircularProgress from '@mui/material/CircularProgress';\n\ntype CategoryInputProps = {\n setForm: (\n value: SetStateAction<{\n category: string | undefined;\n tags: string[] | undefined;\n id: string;\n publisher: string;\n title: string;\n excerpt: string;\n body: string;\n created_at: string;\n active: boolean;\n start_at: string;\n until_date: string;\n sendNotification: boolean;\n updated_at: string;\n }>,\n ) => void;\n form: {\n category: string | undefined;\n tags: string[] | undefined;\n id: string;\n publisher: string;\n title: string;\n excerpt: string;\n body: string;\n created_at: string;\n active: boolean;\n start_at: string;\n until_date: string;\n sendNotification: boolean;\n updated_at: string;\n };\n initialValue: string;\n};\n\nconst filter = createFilterOptions<Category>();\n\nfunction prepareCategoryFromInput(\n inputCategory: Category | string,\n localizedCreate?: string,\n): string {\n return (\n typeof inputCategory === 'string' ? inputCategory : inputCategory.title\n )\n .replace(localizedCreate ? `${localizedCreate} ` : 'Create ', '')\n .replaceAll('\"', '');\n}\n\nexport default function CategoryInput({\n setForm,\n form,\n initialValue,\n}: CategoryInputProps) {\n const { categories, loading: categoriesLoading } = useCategories();\n const { t } = useAnnouncementsTranslation();\n\n return (\n <Autocomplete\n fullWidth\n value={initialValue ?? ''}\n onChange={async (_, newValue) => {\n if (!newValue) {\n setForm({ ...form, category: undefined });\n return;\n }\n\n const newCategory = prepareCategoryFromInput(\n newValue,\n t('announcementForm.categoryInput.create'),\n );\n setForm({ ...form, category: newCategory });\n }}\n filterOptions={(options, params) => {\n const filtered = filter(options, params);\n const { inputValue } = params;\n\n /*\n Suggest the creation of a new category. This adds the new value to the list of options\n and creates the new category when the form is submitted.\n */\n const isExisting = options.some(\n option =>\n inputValue.toLocaleLowerCase('en-US') ===\n option.title.toLocaleLowerCase('en-US'),\n );\n if (inputValue !== '' && !isExisting) {\n filtered.push({\n title: `${t(\n 'announcementForm.categoryInput.create',\n )} \"${inputValue}\"`,\n slug: inputValue.toLocaleLowerCase('en-US'),\n });\n }\n\n return filtered;\n }}\n selectOnFocus\n handleHomeEndKeys\n loading={categoriesLoading}\n id=\"category-input-field\"\n options={categories || []}\n getOptionLabel={option => {\n // Value selected with enter, right from the input\n return prepareCategoryFromInput(option);\n }}\n renderOption={(props, option) => <li {...props}>{option.title}</li>}\n freeSolo\n renderInput={params => (\n <TextField\n {...params}\n id=\"category\"\n label={t('announcementForm.categoryInput.label')}\n variant=\"outlined\"\n fullWidth\n InputProps={{\n ...params.InputProps,\n endAdornment: (\n <>\n {categoriesLoading ? (\n <CircularProgress color=\"inherit\" size={20} />\n ) : null}\n {params.InputProps.endAdornment}\n </>\n ),\n }}\n />\n )}\n />\n );\n}\n"],"names":[],"mappings":";;;;;;AA6DA,MAAM,SAAS,mBAA8B,EAAA;AAE7C,SAAS,wBAAA,CACP,eACA,eACQ,EAAA;AACR,EAAA,OAAA,CACE,OAAO,aAAkB,KAAA,QAAA,GAAW,aAAgB,GAAA,aAAA,CAAc,OAEjE,OAAQ,CAAA,eAAA,GAAkB,CAAG,EAAA,eAAe,MAAM,SAAW,EAAA,EAAE,CAC/D,CAAA,UAAA,CAAW,KAAK,EAAE,CAAA;AACvB;AAEA,SAAwB,aAAc,CAAA;AAAA,EACpC,OAAA;AAAA,EACA,IAAA;AAAA,EACA;AACF,CAAuB,EAAA;AACrB,EAAA,MAAM,EAAE,UAAA,EAAY,OAAS,EAAA,iBAAA,KAAsB,aAAc,EAAA;AACjE,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,2BAA4B,EAAA;AAE1C,EACE,uBAAA,GAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,SAAS,EAAA,IAAA;AAAA,MACT,OAAO,YAAgB,IAAA,EAAA;AAAA,MACvB,QAAA,EAAU,OAAO,CAAA,EAAG,QAAa,KAAA;AAC/B,QAAA,IAAI,CAAC,QAAU,EAAA;AACb,UAAA,OAAA,CAAQ,EAAE,GAAG,IAAM,EAAA,QAAA,EAAU,QAAW,CAAA;AACxC,UAAA;AAAA;AAGF,QAAA,MAAM,WAAc,GAAA,wBAAA;AAAA,UAClB,QAAA;AAAA,UACA,EAAE,uCAAuC;AAAA,SAC3C;AACA,QAAA,OAAA,CAAQ,EAAE,GAAG,IAAM,EAAA,QAAA,EAAU,aAAa,CAAA;AAAA,OAC5C;AAAA,MACA,aAAA,EAAe,CAAC,OAAA,EAAS,MAAW,KAAA;AAClC,QAAM,MAAA,QAAA,GAAW,MAAO,CAAA,OAAA,EAAS,MAAM,CAAA;AACvC,QAAM,MAAA,EAAE,YAAe,GAAA,MAAA;AAMvB,QAAA,MAAM,aAAa,OAAQ,CAAA,IAAA;AAAA,UACzB,CAAA,MAAA,KACE,WAAW,iBAAkB,CAAA,OAAO,MACpC,MAAO,CAAA,KAAA,CAAM,kBAAkB,OAAO;AAAA,SAC1C;AACA,QAAI,IAAA,UAAA,KAAe,EAAM,IAAA,CAAC,UAAY,EAAA;AACpC,UAAA,QAAA,CAAS,IAAK,CAAA;AAAA,YACZ,OAAO,CAAG,EAAA,CAAA;AAAA,cACR;AAAA,aACD,KAAK,UAAU,CAAA,CAAA,CAAA;AAAA,YAChB,IAAA,EAAM,UAAW,CAAA,iBAAA,CAAkB,OAAO;AAAA,WAC3C,CAAA;AAAA;AAGH,QAAO,OAAA,QAAA;AAAA,OACT;AAAA,MACA,aAAa,EAAA,IAAA;AAAA,MACb,iBAAiB,EAAA,IAAA;AAAA,MACjB,OAAS,EAAA,iBAAA;AAAA,MACT,EAAG,EAAA,sBAAA;AAAA,MACH,OAAA,EAAS,cAAc,EAAC;AAAA,MACxB,gBAAgB,CAAU,MAAA,KAAA;AAExB,QAAA,OAAO,yBAAyB,MAAM,CAAA;AAAA,OACxC;AAAA,MACA,YAAA,EAAc,CAAC,KAAO,EAAA,MAAA,yBAAY,IAAI,EAAA,EAAA,GAAG,KAAQ,EAAA,QAAA,EAAA,MAAA,CAAO,KAAM,EAAA,CAAA;AAAA,MAC9D,QAAQ,EAAA,IAAA;AAAA,MACR,aAAa,CACX,MAAA,qBAAA,GAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACE,GAAG,MAAA;AAAA,UACJ,EAAG,EAAA,UAAA;AAAA,UACH,KAAA,EAAO,EAAE,sCAAsC,CAAA;AAAA,UAC/C,OAAQ,EAAA,UAAA;AAAA,UACR,SAAS,EAAA,IAAA;AAAA,UACT,UAAY,EAAA;AAAA,YACV,GAAG,MAAO,CAAA,UAAA;AAAA,YACV,8BAEK,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,cAAA,iBAAA,uBACE,gBAAiB,EAAA,EAAA,KAAA,EAAM,SAAU,EAAA,IAAA,EAAM,IAAI,CAC1C,GAAA,IAAA;AAAA,cACH,OAAO,UAAW,CAAA;AAAA,aACrB,EAAA;AAAA;AAEJ;AAAA;AACF;AAAA,GAEJ;AAEJ;;;;"}
|
package/dist/components/Admin/AnnouncementsContent/AnnouncementForm/OnBehalfTeamDropdown.esm.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import TextField from '@mui/material/TextField';
|
|
3
|
-
import Autocomplete from '@mui/material/Autocomplete';
|
|
4
|
-
import CircularProgress from '@mui/material/CircularProgress';
|
|
5
|
-
import { useApi, identityApiRef } from '@backstage/core-plugin-api';
|
|
6
|
-
import { useAnnouncementsTranslation, useCatalogEntities } from '@backstage-community/plugin-announcements-react';
|
|
7
|
-
import useAsync from 'react-use/esm/useAsync';
|
|
8
|
-
import { useMemo } from 'react';
|
|
9
|
-
import { stringifyEntityRef } from '@backstage/catalog-model';
|
|
10
|
-
import Box from '@mui/material/Box';
|
|
11
|
-
import Typography from '@mui/material/Typography';
|
|
12
|
-
|
|
13
|
-
function getTeamDisplayName(team) {
|
|
14
|
-
if (team.kind && team.kind.toLowerCase() === "group") {
|
|
15
|
-
return team.spec?.profile?.displayName ?? "";
|
|
16
|
-
}
|
|
17
|
-
return "";
|
|
18
|
-
}
|
|
19
|
-
function OnBehalfTeamDropdown({
|
|
20
|
-
selectedTeam,
|
|
21
|
-
onChange
|
|
22
|
-
}) {
|
|
23
|
-
const { t } = useAnnouncementsTranslation();
|
|
24
|
-
const identityApi = useApi(identityApiRef);
|
|
25
|
-
const { value: userOwns } = useAsync(async () => {
|
|
26
|
-
const identity = await identityApi.getBackstageIdentity();
|
|
27
|
-
return [identity.userEntityRef, ...identity.ownershipEntityRefs];
|
|
28
|
-
}, [identityApi]);
|
|
29
|
-
const { entities: teams, loading: teamsLoading } = useCatalogEntities(
|
|
30
|
-
userOwns,
|
|
31
|
-
// refs
|
|
32
|
-
"",
|
|
33
|
-
// searchTerm
|
|
34
|
-
"Group"
|
|
35
|
-
// kind
|
|
36
|
-
);
|
|
37
|
-
const teamOptions = useMemo(() => {
|
|
38
|
-
return teams.map((team) => ({
|
|
39
|
-
entityRef: stringifyEntityRef(team),
|
|
40
|
-
displayName: getTeamDisplayName(team)
|
|
41
|
-
}));
|
|
42
|
-
}, [teams]);
|
|
43
|
-
const selectedTeamOption = useMemo(() => {
|
|
44
|
-
return teamOptions.find((team) => team.entityRef === selectedTeam) || null;
|
|
45
|
-
}, [teamOptions, selectedTeam]);
|
|
46
|
-
return /* @__PURE__ */ jsx(
|
|
47
|
-
Autocomplete,
|
|
48
|
-
{
|
|
49
|
-
value: selectedTeamOption,
|
|
50
|
-
onChange: (_, newValue) => {
|
|
51
|
-
onChange(newValue?.entityRef || "");
|
|
52
|
-
},
|
|
53
|
-
options: teamOptions,
|
|
54
|
-
getOptionLabel: (team) => team.entityRef,
|
|
55
|
-
loading: teamsLoading,
|
|
56
|
-
id: "team-dropdown-field",
|
|
57
|
-
renderOption: (props, team) => /* @__PURE__ */ jsx(Box, { component: "li", ...props, children: /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: "column" }, children: [
|
|
58
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body1", children: team.entityRef }),
|
|
59
|
-
team.displayName && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: team.displayName })
|
|
60
|
-
] }) }),
|
|
61
|
-
renderInput: (params) => /* @__PURE__ */ jsx(
|
|
62
|
-
TextField,
|
|
63
|
-
{
|
|
64
|
-
...params,
|
|
65
|
-
id: "team",
|
|
66
|
-
label: t("announcementForm.onBehalfOf"),
|
|
67
|
-
InputProps: {
|
|
68
|
-
...params.InputProps,
|
|
69
|
-
endAdornment: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
70
|
-
teamsLoading ? /* @__PURE__ */ jsx(CircularProgress, { color: "inherit", size: 20 }) : null,
|
|
71
|
-
params.InputProps.endAdornment
|
|
72
|
-
] })
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
)
|
|
76
|
-
}
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export { OnBehalfTeamDropdown as default };
|
|
81
|
-
//# sourceMappingURL=OnBehalfTeamDropdown.esm.js.map
|
package/dist/components/Admin/AnnouncementsContent/AnnouncementForm/OnBehalfTeamDropdown.esm.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OnBehalfTeamDropdown.esm.js","sources":["../../../../../src/components/Admin/AnnouncementsContent/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 TextField from '@mui/material/TextField';\nimport Autocomplete from '@mui/material/Autocomplete';\nimport CircularProgress from '@mui/material/CircularProgress';\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 { useMemo } from 'react';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\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 teamOptions = useMemo(() => {\n return teams.map(team => ({\n entityRef: stringifyEntityRef(team),\n displayName: getTeamDisplayName(team),\n }));\n }, [teams]);\n\n const selectedTeamOption = useMemo(() => {\n return teamOptions.find(team => team.entityRef === selectedTeam) || null;\n }, [teamOptions, selectedTeam]);\n\n return (\n <Autocomplete\n value={selectedTeamOption}\n onChange={(_, newValue) => {\n onChange(newValue?.entityRef || '');\n }}\n options={teamOptions}\n getOptionLabel={team => team.entityRef}\n loading={teamsLoading}\n id=\"team-dropdown-field\"\n renderOption={(props, team) => (\n <Box component=\"li\" {...props}>\n <Box sx={{ display: 'flex', flexDirection: 'column' }}>\n <Typography variant=\"body1\">{team.entityRef}</Typography>\n {team.displayName && (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {team.displayName}\n </Typography>\n )}\n </Box>\n </Box>\n )}\n renderInput={params => (\n <TextField\n {...params}\n id=\"team\"\n label={t('announcementForm.onBehalfOf')}\n InputProps={{\n ...params.InputProps,\n endAdornment: (\n <>\n {teamsLoading ? (\n <CircularProgress color=\"inherit\" size={20} />\n ) : null}\n {params.InputProps.endAdornment}\n </>\n ),\n }}\n />\n )}\n />\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { useMemo } from 'react';
|
|
3
|
-
import Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete';
|
|
4
|
-
import TextField from '@mui/material/TextField';
|
|
5
|
-
import Chip from '@mui/material/Chip';
|
|
6
|
-
import CircularProgress from '@mui/material/CircularProgress';
|
|
7
|
-
import { useTags, useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';
|
|
8
|
-
|
|
9
|
-
const filter = createFilterOptions();
|
|
10
|
-
function prepareTagFromInput(input) {
|
|
11
|
-
if (typeof input === "string") {
|
|
12
|
-
return input.toLocaleLowerCase("en-US");
|
|
13
|
-
}
|
|
14
|
-
if (input.inputValue) {
|
|
15
|
-
return input.inputValue.toLocaleLowerCase("en-US");
|
|
16
|
-
}
|
|
17
|
-
return input.title.toLocaleLowerCase("en-US");
|
|
18
|
-
}
|
|
19
|
-
function TagsInput({ setForm, form }) {
|
|
20
|
-
const { tags, loading } = useTags();
|
|
21
|
-
const { t } = useAnnouncementsTranslation();
|
|
22
|
-
const createLabel = t("announcementForm.tagsInput.create");
|
|
23
|
-
const existingTags = useMemo(() => {
|
|
24
|
-
if (!form.tags || form.tags.length === 0) return [];
|
|
25
|
-
return form.tags.map((tagSlug) => {
|
|
26
|
-
const foundTag = tags?.find((tag) => tag.slug === tagSlug);
|
|
27
|
-
return foundTag || { title: tagSlug, slug: tagSlug };
|
|
28
|
-
});
|
|
29
|
-
}, [form.tags, tags]);
|
|
30
|
-
const handleTagChange = (_event, newValue) => {
|
|
31
|
-
if (!newValue || newValue.length === 0) {
|
|
32
|
-
setForm({ ...form, tags: [] });
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
const processedTags = newValue.map((item) => prepareTagFromInput(item));
|
|
36
|
-
const uniqueTags = Array.from(new Set(processedTags));
|
|
37
|
-
setForm({ ...form, tags: uniqueTags });
|
|
38
|
-
};
|
|
39
|
-
return /* @__PURE__ */ jsx(
|
|
40
|
-
Autocomplete,
|
|
41
|
-
{
|
|
42
|
-
fullWidth: true,
|
|
43
|
-
multiple: true,
|
|
44
|
-
freeSolo: true,
|
|
45
|
-
clearOnBlur: true,
|
|
46
|
-
value: existingTags,
|
|
47
|
-
onChange: handleTagChange,
|
|
48
|
-
options: tags || [],
|
|
49
|
-
loading,
|
|
50
|
-
getOptionLabel: (option) => typeof option === "string" ? option : option.title,
|
|
51
|
-
filterOptions: (options, params) => {
|
|
52
|
-
const filtered = filter(options, params);
|
|
53
|
-
const { inputValue } = params;
|
|
54
|
-
if (inputValue.trim() !== "" && !options.some(
|
|
55
|
-
(option) => typeof option !== "string" && inputValue.toLocaleLowerCase("en-US") === option.title.toLocaleLowerCase("en-US")
|
|
56
|
-
)) {
|
|
57
|
-
filtered.push({
|
|
58
|
-
title: `${createLabel} "${inputValue}"`,
|
|
59
|
-
slug: inputValue.toLocaleLowerCase("en-US"),
|
|
60
|
-
inputValue,
|
|
61
|
-
isNew: true
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
return filtered;
|
|
65
|
-
},
|
|
66
|
-
renderTags: (value, getTagProps) => value.map((option, index) => {
|
|
67
|
-
const tag = typeof option === "string" ? { title: option, slug: option.toLocaleLowerCase("en-US") } : option;
|
|
68
|
-
const tagProps = getTagProps({ index });
|
|
69
|
-
const { key, ...chipProps } = tagProps;
|
|
70
|
-
return /* @__PURE__ */ jsx(
|
|
71
|
-
Chip,
|
|
72
|
-
{
|
|
73
|
-
variant: "outlined",
|
|
74
|
-
label: tag.title,
|
|
75
|
-
...chipProps
|
|
76
|
-
},
|
|
77
|
-
key
|
|
78
|
-
);
|
|
79
|
-
}),
|
|
80
|
-
renderInput: (params) => /* @__PURE__ */ jsx(
|
|
81
|
-
TextField,
|
|
82
|
-
{
|
|
83
|
-
...params,
|
|
84
|
-
label: "Tags",
|
|
85
|
-
variant: "outlined",
|
|
86
|
-
InputProps: {
|
|
87
|
-
...params.InputProps,
|
|
88
|
-
endAdornment: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
89
|
-
loading ? /* @__PURE__ */ jsx(CircularProgress, { color: "inherit", size: 20 }) : null,
|
|
90
|
-
params.InputProps.endAdornment
|
|
91
|
-
] })
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
)
|
|
95
|
-
}
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export { TagsInput as default };
|
|
100
|
-
//# sourceMappingURL=TagsInput.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TagsInput.esm.js","sources":["../../../../../src/components/Admin/AnnouncementsContent/AnnouncementForm/TagsInput.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 { useMemo } from 'react';\nimport Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete';\nimport TextField from '@mui/material/TextField';\nimport Chip from '@mui/material/Chip';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport {\n useTags,\n useAnnouncementsTranslation,\n} from '@backstage-community/plugin-announcements-react';\nimport { Tag } from '@backstage-community/plugin-announcements-common';\n\nexport interface TagOption extends Tag {\n inputValue?: string;\n isNew?: boolean;\n}\n\nconst filter = createFilterOptions<TagOption>();\n\nfunction prepareTagFromInput(input: string | TagOption): string {\n if (typeof input === 'string') {\n return input.toLocaleLowerCase('en-US');\n }\n if (input.inputValue) {\n return input.inputValue.toLocaleLowerCase('en-US');\n }\n return input.title.toLocaleLowerCase('en-US');\n}\n\ninterface TagsInputProps {\n setForm: (form: any) => void;\n form: any;\n}\n\nexport default function TagsInput({ setForm, form }: TagsInputProps) {\n const { tags, loading } = useTags();\n const { t } = useAnnouncementsTranslation();\n const createLabel = t('announcementForm.tagsInput.create');\n\n const existingTags = useMemo(() => {\n if (!form.tags || form.tags.length === 0) return [];\n return form.tags.map((tagSlug: string) => {\n const foundTag = tags?.find(tag => tag.slug === tagSlug);\n return foundTag || { title: tagSlug, slug: tagSlug };\n });\n }, [form.tags, tags]);\n\n const handleTagChange = (_event: any, newValue: (string | TagOption)[]) => {\n if (!newValue || newValue.length === 0) {\n setForm({ ...form, tags: [] });\n return;\n }\n\n const processedTags = newValue.map(item => prepareTagFromInput(item));\n const uniqueTags = Array.from(new Set(processedTags));\n\n setForm({ ...form, tags: uniqueTags });\n };\n\n return (\n <Autocomplete\n fullWidth\n multiple\n freeSolo\n clearOnBlur\n value={existingTags}\n onChange={handleTagChange}\n options={tags || []}\n loading={loading}\n getOptionLabel={(option: string | TagOption) =>\n typeof option === 'string' ? option : option.title\n }\n filterOptions={(options, params) => {\n const filtered = filter(options as TagOption[], params);\n const { inputValue } = params;\n if (\n inputValue.trim() !== '' &&\n !options.some(\n option =>\n typeof option !== 'string' &&\n inputValue.toLocaleLowerCase('en-US') ===\n option.title.toLocaleLowerCase('en-US'),\n )\n ) {\n filtered.push({\n title: `${createLabel} \"${inputValue}\"`,\n slug: inputValue.toLocaleLowerCase('en-US'),\n inputValue,\n isNew: true,\n });\n }\n return filtered;\n }}\n renderTags={(value: (string | TagOption)[], getTagProps) =>\n value.map((option, index) => {\n const tag =\n typeof option === 'string'\n ? { title: option, slug: option.toLocaleLowerCase('en-US') }\n : option;\n\n const tagProps = getTagProps({ index });\n const { key, ...chipProps } = tagProps;\n\n return (\n <Chip\n key={key}\n variant=\"outlined\"\n label={tag.title}\n {...chipProps}\n />\n );\n })\n }\n renderInput={params => (\n <TextField\n {...params}\n label=\"Tags\"\n variant=\"outlined\"\n InputProps={{\n ...params.InputProps,\n endAdornment: (\n <>\n {loading ? (\n <CircularProgress color=\"inherit\" size={20} />\n ) : null}\n {params.InputProps.endAdornment}\n </>\n ),\n }}\n />\n )}\n />\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { useState, useMemo } from 'react';
|
|
3
|
-
import { Progress, ErrorPanel, StatusOK, StatusPending, Table } from '@backstage/core-components';
|
|
4
|
-
import { useApi, alertApiRef } from '@backstage/core-plugin-api';
|
|
5
|
-
import { announcementsApiRef, useCategories, useAnnouncementsTranslation, useAnnouncementsPermissions } from '@backstage-community/plugin-announcements-react';
|
|
6
|
-
import { announcementCreatePermission } from '@backstage-community/plugin-announcements-common';
|
|
7
|
-
import useAsyncRetry from 'react-use/esm/useAsyncRetry';
|
|
8
|
-
import { useDeleteDialogState } from '../shared/DeleteDialog/useDeleteDialogState.esm.js';
|
|
9
|
-
import { DeleteDialog } from '../shared/DeleteDialog/DeleteDialog.esm.js';
|
|
10
|
-
import { Typography, Box, IconButton, Grid, Button } from '@material-ui/core';
|
|
11
|
-
import { useNavigate } from 'react-router-dom';
|
|
12
|
-
import { AnnouncementForm } from './AnnouncementForm/AnnouncementForm.esm.js';
|
|
13
|
-
import slugify from 'slugify';
|
|
14
|
-
import { RequirePermission } from '@backstage/plugin-permission-react';
|
|
15
|
-
import DeleteIcon from '@material-ui/icons/Delete';
|
|
16
|
-
import EditIcon from '@material-ui/icons/Edit';
|
|
17
|
-
import PreviewIcon from '@material-ui/icons/Visibility';
|
|
18
|
-
import { DateTime } from 'luxon';
|
|
19
|
-
|
|
20
|
-
const AnnouncementsContent = ({
|
|
21
|
-
defaultInactive
|
|
22
|
-
}) => {
|
|
23
|
-
const alertApi = useApi(alertApiRef);
|
|
24
|
-
const announcementsApi = useApi(announcementsApiRef);
|
|
25
|
-
const navigate = useNavigate();
|
|
26
|
-
const { categories } = useCategories();
|
|
27
|
-
const { t } = useAnnouncementsTranslation();
|
|
28
|
-
const permissions = useAnnouncementsPermissions();
|
|
29
|
-
const [showCreateAnnouncementForm, setShowCreateAnnouncementForm] = useState(false);
|
|
30
|
-
const [editingAnnouncementId, setEditingAnnouncementId] = useState(null);
|
|
31
|
-
const {
|
|
32
|
-
loading,
|
|
33
|
-
error,
|
|
34
|
-
value: announcements,
|
|
35
|
-
retry
|
|
36
|
-
} = useAsyncRetry(async () => await announcementsApi.announcements({}));
|
|
37
|
-
const {
|
|
38
|
-
isOpen: isDeleteDialogOpen,
|
|
39
|
-
open: openDeleteDialog,
|
|
40
|
-
close: closeDeleteDialog,
|
|
41
|
-
item: announcementToDelete
|
|
42
|
-
} = useDeleteDialogState();
|
|
43
|
-
const onCreateButtonClick = () => {
|
|
44
|
-
setShowCreateAnnouncementForm(!showCreateAnnouncementForm);
|
|
45
|
-
setEditingAnnouncementId(null);
|
|
46
|
-
};
|
|
47
|
-
const onTitleClick = (announcement) => {
|
|
48
|
-
navigate(`/announcements/view/${announcement.id}`);
|
|
49
|
-
};
|
|
50
|
-
const onEdit = (announcement) => {
|
|
51
|
-
setEditingAnnouncementId(announcement.id);
|
|
52
|
-
setShowCreateAnnouncementForm(false);
|
|
53
|
-
};
|
|
54
|
-
const onCancelEdit = () => {
|
|
55
|
-
setEditingAnnouncementId(null);
|
|
56
|
-
};
|
|
57
|
-
const onCancelDelete = () => {
|
|
58
|
-
closeDeleteDialog();
|
|
59
|
-
};
|
|
60
|
-
const onConfirmDelete = async () => {
|
|
61
|
-
closeDeleteDialog();
|
|
62
|
-
try {
|
|
63
|
-
await announcementsApi.deleteAnnouncementByID(announcementToDelete.id);
|
|
64
|
-
alertApi.post({ message: "Announcement deleted.", severity: "success" });
|
|
65
|
-
} catch (err) {
|
|
66
|
-
alertApi.post({ message: err.message, severity: "error" });
|
|
67
|
-
}
|
|
68
|
-
retry();
|
|
69
|
-
};
|
|
70
|
-
const onSubmit = async (request) => {
|
|
71
|
-
const { category } = request;
|
|
72
|
-
const slugs = categories.map((c) => c.slug);
|
|
73
|
-
let alertMsg = t("admin.announcementsContent.alertMessage");
|
|
74
|
-
try {
|
|
75
|
-
if (category) {
|
|
76
|
-
const categorySlug = slugify(category, {
|
|
77
|
-
lower: true
|
|
78
|
-
});
|
|
79
|
-
if (slugs.indexOf(categorySlug) === -1) {
|
|
80
|
-
alertMsg = alertMsg.replace(".", "");
|
|
81
|
-
alertMsg = `${alertMsg} ${t(
|
|
82
|
-
"admin.announcementsContent.alertMessageWithNewCategory"
|
|
83
|
-
)} ${category}.`;
|
|
84
|
-
await announcementsApi.createCategory({
|
|
85
|
-
title: category
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
await announcementsApi.createAnnouncement({
|
|
90
|
-
...request,
|
|
91
|
-
category: request.category?.toLocaleLowerCase("en-US")
|
|
92
|
-
});
|
|
93
|
-
alertApi.post({ message: alertMsg, severity: "success" });
|
|
94
|
-
setShowCreateAnnouncementForm(false);
|
|
95
|
-
retry();
|
|
96
|
-
} catch (err) {
|
|
97
|
-
alertApi.post({ message: err.message, severity: "error" });
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
const onUpdate = async (request) => {
|
|
101
|
-
if (!editingAnnouncementId) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const { category } = request;
|
|
105
|
-
const slugs = categories.map((c) => c.slug);
|
|
106
|
-
let updateMsg = t("editAnnouncementPage.updatedMessage");
|
|
107
|
-
try {
|
|
108
|
-
if (category) {
|
|
109
|
-
const categorySlug = slugify(category, {
|
|
110
|
-
lower: true
|
|
111
|
-
});
|
|
112
|
-
if (slugs.indexOf(categorySlug) === -1) {
|
|
113
|
-
updateMsg = updateMsg.replace(".", "");
|
|
114
|
-
updateMsg = `${updateMsg} ${t(
|
|
115
|
-
"editAnnouncementPage.updatedMessageWithNewCategory"
|
|
116
|
-
)} ${category}.`;
|
|
117
|
-
await announcementsApi.createCategory({
|
|
118
|
-
title: category
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
await announcementsApi.updateAnnouncement(editingAnnouncementId, request);
|
|
123
|
-
alertApi.post({ message: updateMsg, severity: "success" });
|
|
124
|
-
setEditingAnnouncementId(null);
|
|
125
|
-
retry();
|
|
126
|
-
} catch (err) {
|
|
127
|
-
alertApi.post({ message: err.message, severity: "error" });
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
const announcementToEdit = useMemo(() => {
|
|
131
|
-
if (!editingAnnouncementId || !announcements?.results) {
|
|
132
|
-
return null;
|
|
133
|
-
}
|
|
134
|
-
return announcements.results.find((a) => a.id === editingAnnouncementId) ?? null;
|
|
135
|
-
}, [editingAnnouncementId, announcements?.results]);
|
|
136
|
-
if (loading) {
|
|
137
|
-
return /* @__PURE__ */ jsx(Progress, {});
|
|
138
|
-
}
|
|
139
|
-
if (error) {
|
|
140
|
-
return /* @__PURE__ */ jsx(ErrorPanel, { error });
|
|
141
|
-
}
|
|
142
|
-
const columns = [
|
|
143
|
-
{
|
|
144
|
-
title: /* @__PURE__ */ jsx(Typography, { children: t("admin.announcementsContent.table.title") }),
|
|
145
|
-
sorting: true,
|
|
146
|
-
field: "title",
|
|
147
|
-
render: (rowData) => rowData.title
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
title: /* @__PURE__ */ jsx(Typography, { children: t("admin.announcementsContent.table.body") }),
|
|
151
|
-
sorting: true,
|
|
152
|
-
field: "body",
|
|
153
|
-
render: (rowData) => rowData.body
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
title: /* @__PURE__ */ jsx(Typography, { children: t("admin.announcementsContent.table.publisher") }),
|
|
157
|
-
sorting: true,
|
|
158
|
-
field: "publisher",
|
|
159
|
-
render: (rowData) => rowData.publisher
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
title: /* @__PURE__ */ jsx(Typography, { children: t("admin.announcementsContent.table.onBehalfOf") }),
|
|
163
|
-
sorting: true,
|
|
164
|
-
field: "on_behalf_of",
|
|
165
|
-
render: (rowData) => rowData.on_behalf_of
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
title: /* @__PURE__ */ jsx(Typography, { children: t("admin.announcementsContent.table.category") }),
|
|
169
|
-
sorting: true,
|
|
170
|
-
field: "category",
|
|
171
|
-
render: (rowData) => rowData.category?.title ?? ""
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
title: /* @__PURE__ */ jsx(Typography, { children: t("admin.announcementsContent.table.tags") }),
|
|
175
|
-
sorting: true,
|
|
176
|
-
field: "tags",
|
|
177
|
-
render: (rowData) => rowData.tags?.map((tag) => tag.title).join(", ") || ""
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
title: /* @__PURE__ */ jsx(Typography, { children: t("admin.announcementsContent.table.status") }),
|
|
181
|
-
sorting: true,
|
|
182
|
-
field: "active",
|
|
183
|
-
render: (rowData) => rowData.active ? /* @__PURE__ */ jsx(StatusOK, { children: t("admin.announcementsContent.table.active") }) : /* @__PURE__ */ jsx(StatusPending, { children: t("admin.announcementsContent.table.inactive") })
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
title: /* @__PURE__ */ jsx(Typography, { children: t("admin.announcementsContent.table.created_at") }),
|
|
187
|
-
sorting: true,
|
|
188
|
-
field: "created_at",
|
|
189
|
-
type: "date",
|
|
190
|
-
render: (rowData) => DateTime.fromISO(rowData.created_at).toFormat("M/d/yyyy")
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
title: /* @__PURE__ */ jsx(Typography, { children: t("admin.announcementsContent.table.start_at") }),
|
|
194
|
-
sorting: true,
|
|
195
|
-
field: "start_at",
|
|
196
|
-
type: "date",
|
|
197
|
-
render: (rowData) => DateTime.fromISO(rowData.start_at).toFormat("M/d/yyyy")
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
title: /* @__PURE__ */ jsx(Typography, { children: t("admin.announcementsContent.table.until_date") }),
|
|
201
|
-
sorting: true,
|
|
202
|
-
field: "until_date",
|
|
203
|
-
type: "date",
|
|
204
|
-
render: (rowData) => rowData?.until_date ? DateTime.fromISO(rowData.until_date).toFormat("M/d/yyyy") : "-"
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
title: /* @__PURE__ */ jsx(Typography, { children: t("admin.announcementsContent.table.actions") }),
|
|
208
|
-
render: (rowData) => {
|
|
209
|
-
return /* @__PURE__ */ jsxs(Box, { display: "flex", flexDirection: "row", children: [
|
|
210
|
-
/* @__PURE__ */ jsx(
|
|
211
|
-
IconButton,
|
|
212
|
-
{
|
|
213
|
-
"aria-label": "preview",
|
|
214
|
-
onClick: () => onTitleClick(rowData),
|
|
215
|
-
size: "small",
|
|
216
|
-
children: /* @__PURE__ */ jsx(PreviewIcon, { fontSize: "small", "data-testid": "preview" })
|
|
217
|
-
}
|
|
218
|
-
),
|
|
219
|
-
/* @__PURE__ */ jsx(
|
|
220
|
-
IconButton,
|
|
221
|
-
{
|
|
222
|
-
"aria-label": "edit",
|
|
223
|
-
disabled: permissions.update.loading || !permissions.update.allowed || editingAnnouncementId === rowData.id,
|
|
224
|
-
onClick: () => onEdit(rowData),
|
|
225
|
-
size: "small",
|
|
226
|
-
children: /* @__PURE__ */ jsx(EditIcon, { fontSize: "small", "data-testid": "edit-icon" })
|
|
227
|
-
}
|
|
228
|
-
),
|
|
229
|
-
/* @__PURE__ */ jsx(
|
|
230
|
-
IconButton,
|
|
231
|
-
{
|
|
232
|
-
"aria-label": "delete",
|
|
233
|
-
disabled: permissions.delete.loading || !permissions.delete.allowed,
|
|
234
|
-
onClick: () => openDeleteDialog(rowData),
|
|
235
|
-
size: "small",
|
|
236
|
-
children: /* @__PURE__ */ jsx(DeleteIcon, { fontSize: "small", "data-testid": "delete-icon" })
|
|
237
|
-
}
|
|
238
|
-
)
|
|
239
|
-
] });
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
];
|
|
243
|
-
return /* @__PURE__ */ jsx(RequirePermission, { permission: announcementCreatePermission, children: /* @__PURE__ */ jsxs(Grid, { container: true, children: [
|
|
244
|
-
!editingAnnouncementId && /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
|
|
245
|
-
Button,
|
|
246
|
-
{
|
|
247
|
-
disabled: permissions.create.loading || !permissions.create.allowed,
|
|
248
|
-
variant: "contained",
|
|
249
|
-
onClick: () => onCreateButtonClick(),
|
|
250
|
-
children: showCreateAnnouncementForm ? t("admin.announcementsContent.cancelButton") : t("admin.announcementsContent.createButton")
|
|
251
|
-
}
|
|
252
|
-
) }),
|
|
253
|
-
showCreateAnnouncementForm && /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
|
|
254
|
-
AnnouncementForm,
|
|
255
|
-
{
|
|
256
|
-
initialData: { active: !defaultInactive },
|
|
257
|
-
onSubmit
|
|
258
|
-
}
|
|
259
|
-
) }),
|
|
260
|
-
editingAnnouncementId && announcementToEdit && /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsxs(Box, { children: [
|
|
261
|
-
/* @__PURE__ */ jsxs(
|
|
262
|
-
Box,
|
|
263
|
-
{
|
|
264
|
-
display: "flex",
|
|
265
|
-
justifyContent: "space-between",
|
|
266
|
-
style: { marginBottom: 16 },
|
|
267
|
-
children: [
|
|
268
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h6", children: t("announcementForm.editAnnouncement") }),
|
|
269
|
-
/* @__PURE__ */ jsx(Button, { variant: "outlined", onClick: onCancelEdit, size: "small", children: t("admin.announcementsContent.cancelButton") })
|
|
270
|
-
]
|
|
271
|
-
}
|
|
272
|
-
),
|
|
273
|
-
/* @__PURE__ */ jsx(
|
|
274
|
-
AnnouncementForm,
|
|
275
|
-
{
|
|
276
|
-
initialData: announcementToEdit,
|
|
277
|
-
onSubmit: onUpdate
|
|
278
|
-
}
|
|
279
|
-
)
|
|
280
|
-
] }) }),
|
|
281
|
-
/* @__PURE__ */ jsxs(Grid, { item: true, xs: 12, children: [
|
|
282
|
-
/* @__PURE__ */ jsx(
|
|
283
|
-
Table,
|
|
284
|
-
{
|
|
285
|
-
title: t("admin.announcementsContent.announcements"),
|
|
286
|
-
options: { pageSize: 20, search: true },
|
|
287
|
-
columns,
|
|
288
|
-
data: announcements?.results ?? [],
|
|
289
|
-
emptyContent: /* @__PURE__ */ jsx(Typography, { style: { padding: 2, textAlign: "center" }, children: t("admin.announcementsContent.noAnnouncementsFound") })
|
|
290
|
-
}
|
|
291
|
-
),
|
|
292
|
-
/* @__PURE__ */ jsx(
|
|
293
|
-
DeleteDialog,
|
|
294
|
-
{
|
|
295
|
-
isOpen: isDeleteDialogOpen,
|
|
296
|
-
onCancel: onCancelDelete,
|
|
297
|
-
onConfirm: onConfirmDelete
|
|
298
|
-
}
|
|
299
|
-
)
|
|
300
|
-
] })
|
|
301
|
-
] }) });
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
export { AnnouncementsContent };
|
|
305
|
-
//# sourceMappingURL=AnnouncementsContent.esm.js.map
|