diff --git a/.changeset/gorgeous-trains-clap.md b/.changeset/gorgeous-trains-clap.md
new file mode 100644
index 0000000000..d0abf6148a
--- /dev/null
+++ b/.changeset/gorgeous-trains-clap.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog': patch
+---
+
+Added an `allowedKinds` option to `CatalogKindHeader` to limit entity kinds available in the dropdown.
diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md
index 3223d6aa59..43cde23c57 100644
--- a/plugins/catalog/api-report.md
+++ b/plugins/catalog/api-report.md
@@ -74,7 +74,7 @@ export function CatalogKindHeader(props: CatalogKindHeaderProps): JSX.Element;
// @public
export interface CatalogKindHeaderProps {
- // (undocumented)
+ allowedKinds?: string[];
initialFilter?: string;
}
diff --git a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx
index a7dc18eae2..15d41f3ab3 100644
--- a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx
+++ b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx
@@ -169,4 +169,47 @@ describe('', () => {
kind: new EntityKindFilter('template'),
});
});
+
+ it('limits kinds when allowedKinds is set', async () => {
+ const rendered = await renderWithEffects(
+
+
+
+
+ ,
+ );
+
+ const input = rendered.getByText('Components');
+ fireEvent.mouseDown(input);
+
+ expect(
+ rendered.getByRole('option', { name: 'Components' }),
+ ).toBeInTheDocument();
+ expect(
+ rendered.getByRole('option', { name: 'Systems' }),
+ ).toBeInTheDocument();
+ expect(
+ rendered.queryByRole('option', { name: 'Templates' }),
+ ).not.toBeInTheDocument();
+ });
+
+ it('renders kind from the query parameter even when not in allowedKinds', async () => {
+ const rendered = await renderWithEffects(
+
+
+
+
+ ,
+ );
+
+ expect(rendered.getByText('Frobs')).toBeInTheDocument();
+ const input = rendered.getByText('Frobs');
+ fireEvent.mouseDown(input);
+
+ expect(
+ rendered.getByRole('option', { name: 'Systems' }),
+ ).toBeInTheDocument();
+ });
});
diff --git a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx
index 27184bafef..67eedb9acc 100644
--- a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx
+++ b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx
@@ -46,12 +46,21 @@ const useStyles = makeStyles((theme: Theme) =>
* @public
*/
export interface CatalogKindHeaderProps {
+ /**
+ * Entity kinds to show in the dropdown; by default all kinds are fetched from the catalog and
+ * displayed.
+ */
+ allowedKinds?: string[];
+ /**
+ * The initial kind to select; defaults to 'component'. A kind filter entered directly in the
+ * query parameter will override this value.
+ */
initialFilter?: string;
}
/** @public */
export function CatalogKindHeader(props: CatalogKindHeaderProps) {
- const { initialFilter = 'component' } = props;
+ const { initialFilter = 'component', allowedKinds } = props;
const classes = useStyles();
const catalogApi = useApi(catalogApiRef);
const { value: allKinds } = useAsync(async () => {
@@ -65,7 +74,7 @@ export function CatalogKindHeader(props: CatalogKindHeaderProps) {
} = useEntityList();
const queryParamKind = useMemo(
- () => [kindParameter].flat()[0],
+ () => [kindParameter].flat()[0]?.toLocaleLowerCase('en-US'),
[kindParameter],
);
const [selectedKind, setSelectedKind] = useState(
@@ -91,13 +100,19 @@ export function CatalogKindHeader(props: CatalogKindHeaderProps) {
// enforced casing from the catalog-backend. This makes a key/value record for the Select options,
// including selectedKind if it's unknown - but allows the selectedKind to get clobbered by the
// more proper catalog kind if it exists.
- const options = [capitalize(selectedKind)]
- .concat(allKinds ?? [])
- .sort()
- .reduce((acc, kind) => {
- acc[kind.toLocaleLowerCase('en-US')] = kind;
- return acc;
- }, {} as Record);
+ const availableKinds = [capitalize(selectedKind)].concat(
+ allKinds?.filter(k =>
+ allowedKinds
+ ? allowedKinds.some(
+ a => a.toLocaleLowerCase('en-US') === k.toLocaleLowerCase('en-US'),
+ )
+ : true,
+ ) ?? [],
+ );
+ const options = availableKinds.sort().reduce((acc, kind) => {
+ acc[kind.toLocaleLowerCase('en-US')] = kind;
+ return acc;
+ }, {} as Record);
return (