diff --git a/.changeset/cuddly-cooks-fry.md b/.changeset/cuddly-cooks-fry.md
new file mode 100644
index 0000000000..028b0291bd
--- /dev/null
+++ b/.changeset/cuddly-cooks-fry.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-catalog-react': patch
+---
+
+Added a `useEntityKinds` hook to load a unique list of entity kinds from the catalog.
+Fixed a bug in `EntityTypePicker` where the component did not hide when no types were available in returned entities.
diff --git a/.changeset/nasty-ads-nail.md b/.changeset/nasty-ads-nail.md
new file mode 100644
index 0000000000..0518b1e569
--- /dev/null
+++ b/.changeset/nasty-ads-nail.md
@@ -0,0 +1,10 @@
+---
+'@backstage/core-components': minor
+---
+
+Changed the `titleComponent` prop on `ContentHeader` to accept `ReactNode` instead of a React `ComponentType`. Usages of this prop should be converted from passing a component to passing in the rendered element:
+
+```diff
+-
++}>
+```
diff --git a/.changeset/short-years-smile.md b/.changeset/short-years-smile.md
new file mode 100644
index 0000000000..6e7b882c1e
--- /dev/null
+++ b/.changeset/short-years-smile.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog': patch
+---
+
+Added the ability to switch entity kind on the catalog index page. This is a non-breaking change, but if you created a custom `CatalogPage` and wish to use this feature, make the modifications shown on [#6895](https://github.com/backstage/backstage/pull/6895).
diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md
index 07258a55cb..8f855776a0 100644
--- a/docs/features/software-catalog/catalog-customization.md
+++ b/docs/features/software-catalog/catalog-customization.md
@@ -34,15 +34,14 @@ export const CustomCatalogPage = ({
}: CatalogPageProps) => {
return (
-
-
-
- All your software catalog entities
-
-
+
+
+ }>
+
+ All your software catalog entities
+
-
@@ -51,8 +50,8 @@ export const CustomCatalogPage = ({
-
-
+
+
);
};
diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md
index b4402f67ac..f73eee1f13 100644
--- a/packages/core-components/api-report.md
+++ b/packages/core-components/api-report.md
@@ -15,7 +15,6 @@ import { Column } from '@material-table/core';
import { CommonProps } from '@material-ui/core/OverridableComponent';
import { ComponentClass } from 'react';
import { ComponentProps } from 'react';
-import { ComponentType } from 'react';
import { Context } from 'react';
import { default as CSS_2 } from 'csstype';
import { CSSProperties } from 'react';
diff --git a/packages/core-components/src/layout/ContentHeader/ContentHeader.test.tsx b/packages/core-components/src/layout/ContentHeader/ContentHeader.test.tsx
index 498b859db1..37059766a8 100644
--- a/packages/core-components/src/layout/ContentHeader/ContentHeader.test.tsx
+++ b/packages/core-components/src/layout/ContentHeader/ContentHeader.test.tsx
@@ -32,7 +32,7 @@ describe('', () => {
it('should render with titleComponent', async () => {
const title = 'Custom title';
- const titleComponent = () =>
{title}
;
+ const titleComponent =
{title}
;
const rendered = await renderInTestApp(
,
);
diff --git a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx
index 4bda2d76af..2259731148 100644
--- a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx
+++ b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx
@@ -18,7 +18,7 @@
* TODO favoriteable capability
*/
-import React, { ComponentType, PropsWithChildren } from 'react';
+import React, { PropsWithChildren, ReactNode } from 'react';
import { Typography, makeStyles } from '@material-ui/core';
import { Helmet } from 'react-helmet';
@@ -77,7 +77,7 @@ const ContentHeaderTitle = ({
type ContentHeaderProps = {
title?: ContentHeaderTitleProps['title'];
- titleComponent?: ComponentType;
+ titleComponent?: ReactNode;
description?: string;
textAlign?: 'left' | 'right' | 'center';
};
@@ -92,7 +92,7 @@ export const ContentHeader = ({
const classes = useStyles({ textAlign })();
const renderedTitle = TitleComponent ? (
-
+ TitleComponent
) : (
);
diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md
index c5f3226874..5f65426ed3 100644
--- a/plugins/catalog-react/api-report.md
+++ b/plugins/catalog-react/api-report.md
@@ -693,7 +693,7 @@ export const MockEntityListContextProvider: ({
children,
value,
}: React_2.PropsWithChildren<{
- value: Partial;
+ value?: Partial> | undefined;
}>) => JSX.Element;
// Warning: (ae-missing-release-tag) "reduceCatalogFilters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -750,6 +750,15 @@ export const useEntityCompoundName: () => {
// @public (undocumented)
export const useEntityFromUrl: () => EntityLoadingStatus;
+// Warning: (ae-missing-release-tag) "useEntityKinds" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export function useEntityKinds(): {
+ error: Error | undefined;
+ loading: boolean;
+ kinds: string[] | undefined;
+};
+
// Warning: (ae-missing-release-tag) "useEntityListProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
diff --git a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx
index 903a7ba4eb..9912f3d371 100644
--- a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx
+++ b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx
@@ -15,7 +15,7 @@
*/
import React from 'react';
-import { fireEvent, render, waitFor } from '@testing-library/react';
+import { fireEvent, waitFor } from '@testing-library/react';
import { capitalize } from 'lodash';
import { CatalogApi } from '@backstage/catalog-client';
import { Entity } from '@backstage/catalog-model';
@@ -26,6 +26,7 @@ import { EntityKindFilter, EntityTypeFilter } from '../../filters';
import { AlertApi, alertApiRef } from '@backstage/core-plugin-api';
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
+import { renderWithEffects } from '@backstage/test-utils';
const entities: Entity[] = [
{
@@ -60,26 +61,15 @@ const entities: Entity[] = [
},
];
-const apis = ApiRegistry.from([
- [
- catalogApiRef,
- {
- getEntities: jest
- .fn()
- .mockImplementation(() => Promise.resolve({ items: entities })),
- } as unknown as CatalogApi,
- ],
- [
- alertApiRef,
- {
- post: jest.fn(),
- } as unknown as AlertApi,
- ],
-]);
+const apis = ApiRegistry.with(catalogApiRef, {
+ getEntities: jest.fn().mockResolvedValue({ items: entities }),
+} as unknown as CatalogApi).with(alertApiRef, {
+ post: jest.fn(),
+} as unknown as AlertApi);
describe('', () => {
it('renders available entity types', async () => {
- const rendered = render(
+ const rendered = await renderWithEffects(
', () => {
it('sets the selected type filter', async () => {
const updateFilters = jest.fn();
- const rendered = render(
+ const rendered = await renderWithEffects(
{
}
}, [error, alertApi]);
- if (!availableTypes || error) return null;
+ if (availableTypes.length === 0 || error) return null;
const items = [
{ value: 'all', label: 'All' },
diff --git a/plugins/catalog-react/src/hooks/index.ts b/plugins/catalog-react/src/hooks/index.ts
index 868e50c852..2f3ce8411d 100644
--- a/plugins/catalog-react/src/hooks/index.ts
+++ b/plugins/catalog-react/src/hooks/index.ts
@@ -22,6 +22,7 @@ export {
} from './useEntityListProvider';
export type { DefaultEntityFilters } from './useEntityListProvider';
export { useEntityTypeFilter } from './useEntityTypeFilter';
+export { useEntityKinds } from './useEntityKinds';
export { useOwnUser } from './useOwnUser';
export { useRelatedEntities } from './useRelatedEntities';
export { useStarredEntities } from './useStarredEntities';
diff --git a/plugins/catalog-react/src/hooks/useEntityKinds.test.tsx b/plugins/catalog-react/src/hooks/useEntityKinds.test.tsx
new file mode 100644
index 0000000000..d801e508a6
--- /dev/null
+++ b/plugins/catalog-react/src/hooks/useEntityKinds.test.tsx
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { PropsWithChildren } from 'react';
+import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
+import { CatalogApi } from '@backstage/catalog-client';
+import { Entity } from '@backstage/catalog-model';
+import { catalogApiRef } from '../api';
+import { renderHook } from '@testing-library/react-hooks';
+import { useEntityKinds } from './useEntityKinds';
+
+const entities: Entity[] = [
+ {
+ apiVersion: '1',
+ kind: 'Component',
+ metadata: {
+ name: 'component-1',
+ },
+ },
+ {
+ apiVersion: '1',
+ kind: 'Component',
+ metadata: {
+ name: 'component-2',
+ },
+ },
+ {
+ apiVersion: '1',
+ kind: 'Template',
+ metadata: {
+ name: 'template',
+ },
+ },
+ {
+ apiVersion: '1',
+ kind: 'System',
+ metadata: {
+ name: 'system',
+ },
+ },
+];
+
+const mockCatalogApi: Partial = {
+ getEntities: jest.fn().mockResolvedValue({ items: entities }),
+};
+
+const wrapper = ({ children }: PropsWithChildren<{}>) => {
+ return (
+
+ {children}
+
+ );
+};
+
+describe('useEntityKinds', () => {
+ it('does not return duplicate kinds', async () => {
+ const { result, waitForValueToChange } = renderHook(
+ () => useEntityKinds(),
+ {
+ wrapper,
+ },
+ );
+ await waitForValueToChange(() => result.current);
+ expect(result.current.kinds).toBeDefined();
+ expect(result.current.kinds!.length).toBe(3);
+ });
+
+ it('sorts entity kinds', async () => {
+ const { result, waitForValueToChange } = renderHook(
+ () => useEntityKinds(),
+ {
+ wrapper,
+ },
+ );
+ await waitForValueToChange(() => result.current);
+ expect(result.current.kinds).toEqual(['Component', 'System', 'Template']);
+ });
+});
diff --git a/plugins/catalog-react/src/hooks/useEntityKinds.ts b/plugins/catalog-react/src/hooks/useEntityKinds.ts
new file mode 100644
index 0000000000..082e4a207d
--- /dev/null
+++ b/plugins/catalog-react/src/hooks/useEntityKinds.ts
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useAsync } from 'react-use';
+import { useApi } from '@backstage/core-plugin-api';
+import { catalogApiRef } from '../api';
+
+// Retrieve a list of unique entity kinds present in the catalog
+export function useEntityKinds() {
+ const catalogApi = useApi(catalogApiRef);
+
+ const {
+ error,
+ loading,
+ value: kinds,
+ } = useAsync(async () => {
+ const entities = await catalogApi
+ .getEntities({ fields: ['kind'] })
+ .then(response => response.items);
+
+ return [...new Set(entities.map(e => e.kind))].sort();
+ });
+ return { error, loading, kinds };
+}
diff --git a/plugins/catalog-react/src/testUtils/providers.tsx b/plugins/catalog-react/src/testUtils/providers.tsx
index 1f9e4f40d6..2172f6c5a9 100644
--- a/plugins/catalog-react/src/testUtils/providers.tsx
+++ b/plugins/catalog-react/src/testUtils/providers.tsx
@@ -25,12 +25,12 @@ export const MockEntityListContextProvider = ({
children,
value,
}: PropsWithChildren<{
- value: Partial;
+ value?: Partial;
}>) => {
// Provides a default implementation that stores filter state, for testing components that
// reflect filter state.
const [filters, setFilters] = useState(
- value.filters ?? {},
+ value?.filters ?? {},
);
const updateFilters = useCallback(
(
@@ -60,7 +60,7 @@ export const MockEntityListContextProvider = ({
// Extract value.filters to avoid overwriting it; some tests exercise filter updates. The value
// provided is used as the initial seed in useState above.
- const { filters: _, ...otherContextFields } = value;
+ const { filters: _, ...otherContextFields } = value ?? {};
return (
JSX.Element;
+// Warning: (ae-forgotten-export) The symbol "CatalogKindHeaderProps" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "CatalogKindHeader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export const CatalogKindHeader: ({
+ initialFilter,
+}: CatalogKindHeaderProps) => JSX.Element;
+
// Warning: (ae-missing-release-tag) "catalogPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
diff --git a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx
new file mode 100644
index 0000000000..2730665fb6
--- /dev/null
+++ b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import { fireEvent } from '@testing-library/react';
+import { Entity } from '@backstage/catalog-model';
+import {
+ CatalogApi,
+ catalogApiRef,
+ EntityKindFilter,
+ MockEntityListContextProvider,
+} from '@backstage/plugin-catalog-react';
+import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
+import { renderWithEffects } from '@backstage/test-utils';
+import { CatalogKindHeader } from './CatalogKindHeader';
+
+const entities: Entity[] = [
+ {
+ apiVersion: '1',
+ kind: 'Component',
+ metadata: {
+ name: 'component-1',
+ },
+ },
+ {
+ apiVersion: '1',
+ kind: 'Component',
+ metadata: {
+ name: 'component-2',
+ },
+ },
+ {
+ apiVersion: '1',
+ kind: 'Template',
+ metadata: {
+ name: 'template',
+ },
+ },
+ {
+ apiVersion: '1',
+ kind: 'System',
+ metadata: {
+ name: 'system',
+ },
+ },
+];
+
+const apis = ApiRegistry.with(catalogApiRef, {
+ getEntities: jest.fn().mockResolvedValue({ items: entities }),
+} as Partial);
+
+describe('', () => {
+ it('renders available kinds', async () => {
+ const rendered = await renderWithEffects(
+
+
+
+
+ ,
+ );
+
+ const input = rendered.getByText('Components');
+ fireEvent.mouseDown(input);
+
+ entities.map(entity => {
+ expect(
+ rendered.getByRole('option', { name: `${entity.kind}s` }),
+ ).toBeInTheDocument();
+ });
+ });
+
+ it('renders unknown kinds provided in query parameters', async () => {
+ const rendered = await renderWithEffects(
+
+
+
+
+ ,
+ );
+
+ expect(rendered.getByText('Frobs')).toBeInTheDocument();
+ });
+
+ it('updates the kind filter', async () => {
+ const updateFilters = jest.fn();
+ const rendered = await renderWithEffects(
+
+
+
+
+ ,
+ );
+
+ const input = rendered.getByText('Components');
+ fireEvent.mouseDown(input);
+
+ const option = rendered.getByRole('option', { name: 'Templates' });
+ fireEvent.click(option);
+
+ expect(updateFilters).toHaveBeenCalledWith({
+ kind: new EntityKindFilter('template'),
+ });
+ });
+});
diff --git a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx
new file mode 100644
index 0000000000..41c5888d79
--- /dev/null
+++ b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useEffect, useState } from 'react';
+import {
+ capitalize,
+ createStyles,
+ InputBase,
+ makeStyles,
+ MenuItem,
+ Select,
+ Theme,
+} from '@material-ui/core';
+import {
+ EntityKindFilter,
+ useEntityKinds,
+ useEntityListProvider,
+} from '@backstage/plugin-catalog-react';
+
+const useStyles = makeStyles((theme: Theme) =>
+ createStyles({
+ root: {
+ ...theme.typography.h4,
+ },
+ }),
+);
+
+type CatalogKindHeaderProps = {
+ initialFilter?: string;
+};
+
+export const CatalogKindHeader = ({
+ initialFilter = 'component',
+}: CatalogKindHeaderProps) => {
+ const classes = useStyles();
+ const { kinds: allKinds = [] } = useEntityKinds();
+ const { updateFilters, queryParameters } = useEntityListProvider();
+
+ const [selectedKind, setSelectedKind] = useState(
+ ([queryParameters.kind].flat()[0] ?? initialFilter).toLocaleLowerCase(
+ 'en-US',
+ ),
+ );
+
+ useEffect(() => {
+ updateFilters({
+ kind: selectedKind ? new EntityKindFilter(selectedKind) : undefined,
+ });
+ }, [selectedKind, updateFilters]);
+
+ // Before allKinds is loaded, or when a kind is entered manually in the URL, selectedKind may not
+ // be present in allKinds. It should still be shown in the dropdown, but may not have the nice
+ // 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);
+
+ return (
+ }
+ value={selectedKind}
+ onChange={e => setSelectedKind(e.target.value as string)}
+ classes={classes}
+ >
+ {Object.keys(options).map(kind => (
+
+ ))}
+
+ );
+};
diff --git a/plugins/catalog/src/components/CatalogKindHeader/index.ts b/plugins/catalog/src/components/CatalogKindHeader/index.ts
new file mode 100644
index 0000000000..0078207d58
--- /dev/null
+++ b/plugins/catalog/src/components/CatalogKindHeader/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export { CatalogKindHeader } from './CatalogKindHeader';
diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx
index a4f6c01bc8..ec29d3839b 100644
--- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx
+++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx
@@ -25,7 +25,6 @@ import {
} from '@backstage/core-components';
import { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';
import {
- EntityKindPicker,
EntityLifecyclePicker,
EntityListProvider,
EntityOwnerPicker,
@@ -43,6 +42,7 @@ import {
EntityListContainer,
FilterContainer,
} from '../FilteredEntityLayout';
+import { CatalogKindHeader } from '../CatalogKindHeader';
export type CatalogPageProps = {
initiallySelectedFilter?: UserListFilterKind;
@@ -61,18 +61,17 @@ export const CatalogPage = ({
return (
-
-
-
- All your software catalog entities
-
-
+
+
+ }>
+
+ All your software catalog entities
+
-
@@ -83,8 +82,8 @@ export const CatalogPage = ({
-
-
+
+
);
};
diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx
index 84c2afa0f6..c85a60c7c1 100644
--- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx
+++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx
@@ -27,7 +27,7 @@ import {
import Edit from '@material-ui/icons/Edit';
import OpenInNew from '@material-ui/icons/OpenInNew';
import { capitalize } from 'lodash';
-import React from 'react';
+import React, { useMemo } from 'react';
import * as columnFactories from './columns';
import { EntityRow } from './types';
import {
@@ -38,16 +38,6 @@ import {
WarningPanel,
} from '@backstage/core-components';
-const defaultColumns: TableColumn[] = [
- columnFactories.createNameColumn(),
- columnFactories.createSystemColumn(),
- columnFactories.createOwnerColumn(),
- columnFactories.createSpecTypeColumn(),
- columnFactories.createSpecLifecycleColumn(),
- columnFactories.createMetadataDescriptionColumn(),
- columnFactories.createTagsColumn(),
-];
-
type CatalogTableProps = {
columns?: TableColumn[];
actions?: TableProps['actions'];
@@ -57,6 +47,19 @@ export const CatalogTable = ({ columns, actions }: CatalogTableProps) => {
const { isStarredEntity, toggleStarredEntity } = useStarredEntities();
const { loading, error, entities, filters } = useEntityListProvider();
+ const defaultColumns: TableColumn[] = useMemo(
+ () => [
+ columnFactories.createNameColumn({ defaultKind: filters.kind?.value }),
+ columnFactories.createSystemColumn(),
+ columnFactories.createOwnerColumn(),
+ columnFactories.createSpecTypeColumn(),
+ columnFactories.createSpecLifecycleColumn(),
+ columnFactories.createMetadataDescriptionColumn(),
+ columnFactories.createTagsColumn(),
+ ],
+ [filters.kind?.value],
+ );
+
const showTypeColumn = filters.type === undefined;
// TODO(timbonicus): remove the title from the CatalogTable once using EntitySearchBar
const titlePreamble = capitalize(filters.user?.value ?? 'all');
diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts
index c5cc69f609..31184204a9 100644
--- a/plugins/catalog/src/index.ts
+++ b/plugins/catalog/src/index.ts
@@ -16,6 +16,7 @@
export { CatalogClientWrapper } from './CatalogClientWrapper';
export * from './components/AboutCard';
+export * from './components/CatalogKindHeader';
export * from './components/CatalogResultListItem';
export { CatalogTable } from './components/CatalogTable';
export type { EntityRow as CatalogTableRow } from './components/CatalogTable';