@backstage-community/plugin-announcements 2.0.0 → 2.2.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.
Files changed (28) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/Router.esm.js +3 -0
  3. package/dist/Router.esm.js.map +1 -1
  4. package/dist/alpha/components/admin/announcements/AnnouncementForm/AnnouncementForm.esm.js +194 -126
  5. package/dist/alpha/components/admin/announcements/AnnouncementForm/AnnouncementForm.esm.js.map +1 -1
  6. package/dist/alpha/components/admin/announcements/AnnouncementForm/OnBehalfTeamDropdown.esm.js +35 -44
  7. package/dist/alpha/components/admin/announcements/AnnouncementForm/OnBehalfTeamDropdown.esm.js.map +1 -1
  8. package/dist/alpha/components/admin/announcements/AnnouncementsContent.esm.js +10 -43
  9. package/dist/alpha/components/admin/announcements/AnnouncementsContent.esm.js.map +1 -1
  10. package/dist/alpha/components/admin/announcements/AnnouncementsTable.esm.js +15 -1
  11. package/dist/alpha/components/admin/announcements/AnnouncementsTable.esm.js.map +1 -1
  12. package/dist/alpha/components/admin/categories/CategoriesContent.esm.js +2 -2
  13. package/dist/alpha/components/admin/categories/CategoriesContent.esm.js.map +1 -1
  14. package/dist/alpha/components/admin/categories/{CreateCatagoryDialog.esm.js → CreateCategoryDialog.esm.js} +3 -3
  15. package/dist/alpha/components/admin/categories/{CreateCatagoryDialog.esm.js.map → CreateCategoryDialog.esm.js.map} +1 -1
  16. package/dist/alpha/components/announcements/AnnouncementsFilterBar.esm.js +6 -2
  17. package/dist/alpha/components/announcements/AnnouncementsFilterBar.esm.js.map +1 -1
  18. package/dist/alpha/components/announcements/AnnouncementsGrid.esm.js +9 -12
  19. package/dist/alpha/components/announcements/AnnouncementsGrid.esm.js.map +1 -1
  20. package/dist/alpha/components/shared/CategorySelectInput/CategorySelectInput.esm.js +4 -3
  21. package/dist/alpha/components/shared/CategorySelectInput/CategorySelectInput.esm.js.map +1 -1
  22. package/dist/alpha/components/shared/TagsSelectInput/TagsSelectInput.esm.js +4 -3
  23. package/dist/alpha/components/shared/TagsSelectInput/TagsSelectInput.esm.js.map +1 -1
  24. package/package.json +12 -12
  25. package/dist/alpha/components/admin/announcements/AnnouncementForm/CategoryInput.esm.js +0 -82
  26. package/dist/alpha/components/admin/announcements/AnnouncementForm/CategoryInput.esm.js.map +0 -1
  27. package/dist/alpha/components/admin/announcements/AnnouncementForm/TagsInput.esm.js +0 -100
  28. package/dist/alpha/components/admin/announcements/AnnouncementForm/TagsInput.esm.js.map +0 -1
@@ -1,15 +1,16 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { useMemo } from 'react';
3
3
  import { Select } from '@backstage/ui';
4
- import { useAnnouncementsTranslation, useCategories } from '@backstage-community/plugin-announcements-react';
4
+ import { useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';
5
5
 
6
6
  const CategorySelectInput = ({
7
7
  setCategory,
8
8
  initialCategory,
9
+ categories,
10
+ isLoading = false,
9
11
  hideLabel = false
10
12
  }) => {
11
13
  const { t } = useAnnouncementsTranslation();
12
- const { categories, loading: categoriesLoading } = useCategories();
13
14
  const selectOptions = useMemo(() => {
14
15
  if (!categories) return [];
15
16
  return categories.map((category) => ({
@@ -57,7 +58,7 @@ const CategorySelectInput = ({
57
58
  value: selectedCategory?.slug ?? null,
58
59
  onChange: handleChange,
59
60
  options: selectOptions,
60
- isDisabled: categoriesLoading || selectOptions.length === 0
61
+ isDisabled: isLoading || selectOptions.length === 0
61
62
  },
62
63
  selectedCategory?.slug ?? "none"
63
64
  );
@@ -1 +1 @@
1
- {"version":3,"file":"CategorySelectInput.esm.js","sources":["../../../../../src/alpha/components/shared/CategorySelectInput/CategorySelectInput.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 { Key, useMemo } from 'react';\nimport { Select } from '@backstage/ui';\nimport {\n useAnnouncementsTranslation,\n useCategories,\n} from '@backstage-community/plugin-announcements-react';\nimport { Category } from '@backstage-community/plugin-announcements-common';\n\ntype CategorySelectInputProps = {\n initialCategory?: Category;\n setCategory: (category: Category | null) => void;\n hideLabel?: boolean;\n};\n\nexport const CategorySelectInput = ({\n setCategory,\n initialCategory,\n hideLabel = false,\n}: CategorySelectInputProps) => {\n const { t } = useAnnouncementsTranslation();\n\n const { categories, loading: categoriesLoading } = useCategories();\n\n const selectOptions = useMemo(() => {\n if (!categories) return [];\n return categories.map(category => ({\n value: category.slug,\n label: category.title,\n }));\n }, [categories]);\n\n const selectedCategory = useMemo(() => {\n if (!initialCategory) return undefined;\n\n const category = categories?.find(cat => cat.slug === initialCategory.slug);\n\n return category ?? initialCategory;\n }, [initialCategory, categories]);\n\n const handleChange = (value: Key[] | Key | null) => {\n if (!value) {\n setCategory(null);\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 if (!stringValue) {\n setCategory(null);\n return;\n }\n\n const category = categories?.find(cat => cat.slug === stringValue);\n\n if (!category) {\n setCategory(null);\n return;\n }\n\n setCategory(category);\n };\n\n return (\n <Select\n key={selectedCategory?.slug ?? 'none'}\n name=\"category\"\n label={hideLabel ? null : t('announcementsPage.filter.category')}\n searchable\n placeholder={t('announcementsPage.filter.categoryPlaceholder')}\n searchPlaceholder={t(\n 'announcementsPage.filter.categorySearchPlaceholder',\n )}\n value={selectedCategory?.slug ?? null}\n onChange={handleChange}\n options={selectOptions}\n isDisabled={categoriesLoading || selectOptions.length === 0}\n />\n );\n};\n"],"names":[],"mappings":";;;;;AA6BO,MAAM,sBAAsB,CAAC;AAAA,EAClC,WAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAY,GAAA;AACd,CAAgC,KAAA;AAC9B,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,2BAA4B,EAAA;AAE1C,EAAA,MAAM,EAAE,UAAA,EAAY,OAAS,EAAA,iBAAA,KAAsB,aAAc,EAAA;AAEjE,EAAM,MAAA,aAAA,GAAgB,QAAQ,MAAM;AAClC,IAAI,IAAA,CAAC,UAAY,EAAA,OAAO,EAAC;AACzB,IAAO,OAAA,UAAA,CAAW,IAAI,CAAa,QAAA,MAAA;AAAA,MACjC,OAAO,QAAS,CAAA,IAAA;AAAA,MAChB,OAAO,QAAS,CAAA;AAAA,KAChB,CAAA,CAAA;AAAA,GACJ,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAM,MAAA,gBAAA,GAAmB,QAAQ,MAAM;AACrC,IAAI,IAAA,CAAC,iBAAwB,OAAA,KAAA,CAAA;AAE7B,IAAA,MAAM,WAAW,UAAY,EAAA,IAAA,CAAK,SAAO,GAAI,CAAA,IAAA,KAAS,gBAAgB,IAAI,CAAA;AAE1E,IAAA,OAAO,QAAY,IAAA,eAAA;AAAA,GAClB,EAAA,CAAC,eAAiB,EAAA,UAAU,CAAC,CAAA;AAEhC,EAAM,MAAA,YAAA,GAAe,CAAC,KAA8B,KAAA;AAClD,IAAA,IAAI,CAAC,KAAO,EAAA;AACV,MAAA,WAAA,CAAY,IAAI,CAAA;AAChB,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,IAAI,CAAC,WAAa,EAAA;AAChB,MAAA,WAAA,CAAY,IAAI,CAAA;AAChB,MAAA;AAAA;AAGF,IAAA,MAAM,WAAW,UAAY,EAAA,IAAA,CAAK,CAAO,GAAA,KAAA,GAAA,CAAI,SAAS,WAAW,CAAA;AAEjE,IAAA,IAAI,CAAC,QAAU,EAAA;AACb,MAAA,WAAA,CAAY,IAAI,CAAA;AAChB,MAAA;AAAA;AAGF,IAAA,WAAA,CAAY,QAAQ,CAAA;AAAA,GACtB;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MAEC,IAAK,EAAA,UAAA;AAAA,MACL,KAAO,EAAA,SAAA,GAAY,IAAO,GAAA,CAAA,CAAE,mCAAmC,CAAA;AAAA,MAC/D,UAAU,EAAA,IAAA;AAAA,MACV,WAAA,EAAa,EAAE,8CAA8C,CAAA;AAAA,MAC7D,iBAAmB,EAAA,CAAA;AAAA,QACjB;AAAA,OACF;AAAA,MACA,KAAA,EAAO,kBAAkB,IAAQ,IAAA,IAAA;AAAA,MACjC,QAAU,EAAA,YAAA;AAAA,MACV,OAAS,EAAA,aAAA;AAAA,MACT,UAAA,EAAY,iBAAqB,IAAA,aAAA,CAAc,MAAW,KAAA;AAAA,KAAA;AAAA,IAXrD,kBAAkB,IAAQ,IAAA;AAAA,GAYjC;AAEJ;;;;"}
1
+ {"version":3,"file":"CategorySelectInput.esm.js","sources":["../../../../../src/alpha/components/shared/CategorySelectInput/CategorySelectInput.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 { Key, useMemo } from 'react';\nimport { Select } from '@backstage/ui';\nimport { useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';\nimport { Category } from '@backstage-community/plugin-announcements-common';\n\ntype CategorySelectInputProps = {\n initialCategory?: Category;\n setCategory: (category: Category | null) => void;\n categories: Category[];\n isLoading?: boolean;\n hideLabel?: boolean;\n};\n\nexport const CategorySelectInput = ({\n setCategory,\n initialCategory,\n categories,\n isLoading = false,\n hideLabel = false,\n}: CategorySelectInputProps) => {\n const { t } = useAnnouncementsTranslation();\n\n const selectOptions = useMemo(() => {\n if (!categories) return [];\n return categories.map(category => ({\n value: category.slug,\n label: category.title,\n }));\n }, [categories]);\n\n const selectedCategory = useMemo(() => {\n if (!initialCategory) return undefined;\n\n const category = categories?.find(cat => cat.slug === initialCategory.slug);\n\n return category ?? initialCategory;\n }, [initialCategory, categories]);\n\n const handleChange = (value: Key[] | Key | null) => {\n if (!value) {\n setCategory(null);\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 if (!stringValue) {\n setCategory(null);\n return;\n }\n\n const category = categories?.find(cat => cat.slug === stringValue);\n\n if (!category) {\n setCategory(null);\n return;\n }\n\n setCategory(category);\n };\n\n return (\n <Select\n key={selectedCategory?.slug ?? 'none'}\n name=\"category\"\n label={hideLabel ? null : t('announcementsPage.filter.category')}\n searchable\n placeholder={t('announcementsPage.filter.categoryPlaceholder')}\n searchPlaceholder={t(\n 'announcementsPage.filter.categorySearchPlaceholder',\n )}\n value={selectedCategory?.slug ?? null}\n onChange={handleChange}\n options={selectOptions}\n isDisabled={isLoading || selectOptions.length === 0}\n />\n );\n};\n"],"names":[],"mappings":";;;;;AA4BO,MAAM,sBAAsB,CAAC;AAAA,EAClC,WAAA;AAAA,EACA,eAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAY,GAAA,KAAA;AAAA,EACZ,SAAY,GAAA;AACd,CAAgC,KAAA;AAC9B,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,2BAA4B,EAAA;AAE1C,EAAM,MAAA,aAAA,GAAgB,QAAQ,MAAM;AAClC,IAAI,IAAA,CAAC,UAAY,EAAA,OAAO,EAAC;AACzB,IAAO,OAAA,UAAA,CAAW,IAAI,CAAa,QAAA,MAAA;AAAA,MACjC,OAAO,QAAS,CAAA,IAAA;AAAA,MAChB,OAAO,QAAS,CAAA;AAAA,KAChB,CAAA,CAAA;AAAA,GACJ,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAM,MAAA,gBAAA,GAAmB,QAAQ,MAAM;AACrC,IAAI,IAAA,CAAC,iBAAwB,OAAA,KAAA,CAAA;AAE7B,IAAA,MAAM,WAAW,UAAY,EAAA,IAAA,CAAK,SAAO,GAAI,CAAA,IAAA,KAAS,gBAAgB,IAAI,CAAA;AAE1E,IAAA,OAAO,QAAY,IAAA,eAAA;AAAA,GAClB,EAAA,CAAC,eAAiB,EAAA,UAAU,CAAC,CAAA;AAEhC,EAAM,MAAA,YAAA,GAAe,CAAC,KAA8B,KAAA;AAClD,IAAA,IAAI,CAAC,KAAO,EAAA;AACV,MAAA,WAAA,CAAY,IAAI,CAAA;AAChB,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,IAAI,CAAC,WAAa,EAAA;AAChB,MAAA,WAAA,CAAY,IAAI,CAAA;AAChB,MAAA;AAAA;AAGF,IAAA,MAAM,WAAW,UAAY,EAAA,IAAA,CAAK,CAAO,GAAA,KAAA,GAAA,CAAI,SAAS,WAAW,CAAA;AAEjE,IAAA,IAAI,CAAC,QAAU,EAAA;AACb,MAAA,WAAA,CAAY,IAAI,CAAA;AAChB,MAAA;AAAA;AAGF,IAAA,WAAA,CAAY,QAAQ,CAAA;AAAA,GACtB;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MAEC,IAAK,EAAA,UAAA;AAAA,MACL,KAAO,EAAA,SAAA,GAAY,IAAO,GAAA,CAAA,CAAE,mCAAmC,CAAA;AAAA,MAC/D,UAAU,EAAA,IAAA;AAAA,MACV,WAAA,EAAa,EAAE,8CAA8C,CAAA;AAAA,MAC7D,iBAAmB,EAAA,CAAA;AAAA,QACjB;AAAA,OACF;AAAA,MACA,KAAA,EAAO,kBAAkB,IAAQ,IAAA,IAAA;AAAA,MACjC,QAAU,EAAA,YAAA;AAAA,MACV,OAAS,EAAA,aAAA;AAAA,MACT,UAAA,EAAY,SAAa,IAAA,aAAA,CAAc,MAAW,KAAA;AAAA,KAAA;AAAA,IAX7C,kBAAkB,IAAQ,IAAA;AAAA,GAYjC;AAEJ;;;;"}
@@ -1,15 +1,16 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { useMemo } from 'react';
3
3
  import { Select } from '@backstage/ui';
4
- import { useAnnouncementsTranslation, useTags } from '@backstage-community/plugin-announcements-react';
4
+ import { useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';
5
5
 
6
6
  const TagsSelectInput = ({
7
7
  setTags,
8
8
  initialTags,
9
+ tags,
10
+ isLoading = false,
9
11
  hideLabel = false
10
12
  }) => {
11
13
  const { t } = useAnnouncementsTranslation();
12
- const { tags, loading: tagsLoading } = useTags();
13
14
  const selectOptions = useMemo(() => {
14
15
  if (!tags) return [];
15
16
  return tags.map((tag) => ({
@@ -57,7 +58,7 @@ const TagsSelectInput = ({
57
58
  value: selectedTagSlugs,
58
59
  onChange: handleChange,
59
60
  options: selectOptions,
60
- isDisabled: tagsLoading || selectOptions.length === 0
61
+ isDisabled: isLoading || selectOptions.length === 0
61
62
  },
62
63
  selectedTagSlugs.join(",") || "none"
63
64
  );
@@ -1 +1 @@
1
- {"version":3,"file":"TagsSelectInput.esm.js","sources":["../../../../../src/alpha/components/shared/TagsSelectInput/TagsSelectInput.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 { Key, useMemo } from 'react';\nimport { Select } from '@backstage/ui';\nimport {\n useAnnouncementsTranslation,\n useTags,\n} from '@backstage-community/plugin-announcements-react';\nimport { Tag } from '@backstage-community/plugin-announcements-common';\n\ntype TagsSelectInputProps = {\n initialTags?: Tag[];\n setTags: (tags: Tag[] | null) => void;\n hideLabel?: boolean;\n};\n\nexport const TagsSelectInput = ({\n setTags,\n initialTags,\n hideLabel = false,\n}: TagsSelectInputProps) => {\n const { t } = useAnnouncementsTranslation();\n\n const { tags, loading: tagsLoading } = useTags();\n\n const selectOptions = useMemo(() => {\n if (!tags) return [];\n return tags.map(tag => ({\n value: tag.slug,\n label: tag.title,\n }));\n }, [tags]);\n\n const selectedTags = useMemo(() => {\n if (!initialTags || initialTags.length === 0) return [];\n\n return initialTags.map(initialTag => {\n const tag = tags?.find(tagItem => tagItem.slug === initialTag.slug);\n return tag ?? initialTag;\n });\n }, [initialTags, tags]);\n\n const selectedTagSlugs = useMemo(() => {\n return selectedTags.map(tag => tag.slug);\n }, [selectedTags]);\n\n const handleChange = (value: Key[] | Key | null) => {\n if (!value) {\n setTags(null);\n return;\n }\n\n let stringValues: string[] = [];\n\n if (Array.isArray(value)) {\n stringValues = value.map(v => String(v));\n } else {\n stringValues = [String(value)];\n }\n\n if (stringValues.length === 0) {\n setTags(null);\n return;\n }\n\n const selectedTagsList = stringValues\n .map(slug => tags?.find(tag => tag.slug === slug))\n .filter((tag): tag is Tag => tag !== undefined);\n\n setTags(selectedTagsList.length > 0 ? selectedTagsList : null);\n };\n\n return (\n <Select\n key={selectedTagSlugs.join(',') || 'none'}\n name=\"tags\"\n label={hideLabel ? null : t('announcementsPage.filter.tags')}\n placeholder={t('announcementsPage.filter.tagsPlaceholder')}\n searchPlaceholder={t('announcementsPage.filter.tagsSearchPlaceholder')}\n searchable\n selectionMode=\"multiple\"\n value={selectedTagSlugs}\n onChange={handleChange}\n options={selectOptions}\n isDisabled={tagsLoading || selectOptions.length === 0}\n />\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TagsSelectInput.esm.js","sources":["../../../../../src/alpha/components/shared/TagsSelectInput/TagsSelectInput.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 { Key, useMemo } from 'react';\nimport { Select } from '@backstage/ui';\nimport { useAnnouncementsTranslation } from '@backstage-community/plugin-announcements-react';\nimport { Tag } from '@backstage-community/plugin-announcements-common';\n\ntype TagsSelectInputProps = {\n initialTags?: Tag[];\n setTags: (tags: Tag[] | null) => void;\n tags: Tag[];\n isLoading?: boolean;\n hideLabel?: boolean;\n};\n\nexport const TagsSelectInput = ({\n setTags,\n initialTags,\n tags,\n isLoading = false,\n hideLabel = false,\n}: TagsSelectInputProps) => {\n const { t } = useAnnouncementsTranslation();\n\n const selectOptions = useMemo(() => {\n if (!tags) return [];\n return tags.map(tag => ({\n value: tag.slug,\n label: tag.title,\n }));\n }, [tags]);\n\n const selectedTags = useMemo(() => {\n if (!initialTags || initialTags.length === 0) return [];\n\n return initialTags.map(initialTag => {\n const tag = tags?.find(tagItem => tagItem.slug === initialTag.slug);\n return tag ?? initialTag;\n });\n }, [initialTags, tags]);\n\n const selectedTagSlugs = useMemo(() => {\n return selectedTags.map(tag => tag.slug);\n }, [selectedTags]);\n\n const handleChange = (value: Key[] | Key | null) => {\n if (!value) {\n setTags(null);\n return;\n }\n\n let stringValues: string[] = [];\n\n if (Array.isArray(value)) {\n stringValues = value.map(v => String(v));\n } else {\n stringValues = [String(value)];\n }\n\n if (stringValues.length === 0) {\n setTags(null);\n return;\n }\n\n const selectedTagsList = stringValues\n .map(slug => tags?.find(tag => tag.slug === slug))\n .filter((tag): tag is Tag => tag !== undefined);\n\n setTags(selectedTagsList.length > 0 ? selectedTagsList : null);\n };\n\n return (\n <Select\n key={selectedTagSlugs.join(',') || 'none'}\n name=\"tags\"\n label={hideLabel ? null : t('announcementsPage.filter.tags')}\n placeholder={t('announcementsPage.filter.tagsPlaceholder')}\n searchPlaceholder={t('announcementsPage.filter.tagsSearchPlaceholder')}\n searchable\n selectionMode=\"multiple\"\n value={selectedTagSlugs}\n onChange={handleChange}\n options={selectOptions}\n isDisabled={isLoading || selectOptions.length === 0}\n />\n );\n};\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage-community/plugin-announcements",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "main": "./dist/index.esm.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -61,22 +61,22 @@
61
61
  "postpack": "backstage-cli package postpack"
62
62
  },
63
63
  "dependencies": {
64
- "@backstage-community/plugin-announcements-common": "^0.16.0",
65
- "@backstage-community/plugin-announcements-react": "^0.19.0",
64
+ "@backstage-community/plugin-announcements-common": "^0.17.0",
65
+ "@backstage-community/plugin-announcements-react": "^0.21.0",
66
66
  "@backstage/catalog-model": "^1.7.6",
67
- "@backstage/core-app-api": "^1.19.3",
68
- "@backstage/core-compat-api": "^0.5.6",
69
- "@backstage/core-components": "^0.18.5",
70
- "@backstage/core-plugin-api": "^1.12.1",
67
+ "@backstage/core-app-api": "^1.19.4",
68
+ "@backstage/core-compat-api": "^0.5.7",
69
+ "@backstage/core-components": "^0.18.6",
70
+ "@backstage/core-plugin-api": "^1.12.2",
71
71
  "@backstage/errors": "^1.2.7",
72
- "@backstage/frontend-plugin-api": "^0.13.3",
73
- "@backstage/plugin-catalog-react": "^1.21.5",
72
+ "@backstage/frontend-plugin-api": "^0.13.4",
73
+ "@backstage/plugin-catalog-react": "^1.21.6",
74
74
  "@backstage/plugin-permission-react": "^0.4.39",
75
75
  "@backstage/plugin-search-common": "^1.2.21",
76
76
  "@backstage/plugin-search-react": "^1.10.2",
77
77
  "@backstage/plugin-signals-react": "^0.0.18",
78
78
  "@backstage/theme": "^0.7.1",
79
- "@backstage/ui": "^0.11.1",
79
+ "@backstage/ui": "^0.11.2",
80
80
  "@material-ui/core": "^4.12.2",
81
81
  "@material-ui/icons": "^4.11.3",
82
82
  "@material-ui/lab": "4.0.0-alpha.61",
@@ -95,9 +95,9 @@
95
95
  "react-router-dom": "^6.3.0"
96
96
  },
97
97
  "devDependencies": {
98
- "@backstage/cli": "^0.35.2",
98
+ "@backstage/cli": "^0.35.3",
99
99
  "@backstage/dev-utils": "^1.1.19",
100
- "@backstage/frontend-test-utils": "^0.4.4",
100
+ "@backstage/frontend-test-utils": "^0.4.5",
101
101
  "@backstage/plugin-signals": "^0.0.27",
102
102
  "@backstage/test-utils": "^1.7.14",
103
103
  "@testing-library/jest-dom": "^6.3.0",
@@ -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
@@ -1 +0,0 @@
1
- {"version":3,"file":"CategoryInput.esm.js","sources":["../../../../../../src/alpha/components/admin/announcements/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":"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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/alpha/components/admin/announcements/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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"}