diff --git a/frontend/src/components/common/Resource/ResourceTable.tsx b/frontend/src/components/common/Resource/ResourceTable.tsx index 7ca7792a82..28b96112f8 100644 --- a/frontend/src/components/common/Resource/ResourceTable.tsx +++ b/frontend/src/components/common/Resource/ResourceTable.tsx @@ -42,6 +42,8 @@ export type ResourceTableColumn = { * "min-content" */ gridTemplate?: string | number; + /** Options for the select filter */ + filterSelectOptions?: TableColumn['filterSelectOptions']; } & ( | { /** To render a simple value provide property name of the item */ @@ -266,6 +268,7 @@ function ResourceTableContent(props: ResourceTableProps) { sx: { ...(column.cellProps?.sx ?? {}), width: 'unset', minWidth: 'unset' }, }, gridTemplate: column.gridTemplate ?? 1, + filterSelectOptions: column.filterSelectOptions, }; if ('getValue' in column) { diff --git a/frontend/src/components/crd/Details.tsx b/frontend/src/components/crd/Details.tsx index 58c8121242..061e940b4d 100644 --- a/frontend/src/components/crd/Details.tsx +++ b/frontend/src/components/crd/Details.tsx @@ -58,6 +58,11 @@ export default function CustomResourceDefinitionDetails() { ), }, + { + name: t('translation|Categories'), + value: item.getCategories().join(', '), + hide: item.getCategories().length === 0, + }, ] } /> diff --git a/frontend/src/components/crd/List.tsx b/frontend/src/components/crd/List.tsx index f7c183f3f6..b47fdf35e4 100644 --- a/frontend/src/components/crd/List.tsx +++ b/frontend/src/components/crd/List.tsx @@ -1,22 +1,40 @@ +import React from 'react'; import { useTranslation } from 'react-i18next'; import CRD from '../../lib/k8s/crd'; -import { Link } from '../common'; +import { Link, useThrottle } from '../common'; import ResourceListView from '../common/Resource/ResourceListView'; export default function CustomResourceDefinitionList() { const { t } = useTranslation(['glossary', 'frequent']); + const [items, error] = CRD.useList(); + const throttledItems = useThrottle(items, 1000); + + const categories = React.useMemo(() => { + if (!items || items?.length === 0) { + return []; + } + + const categories = new Set(); + items.forEach((crd: CRD) => { + const crdCategories = crd.getCategories() || []; + crdCategories.forEach(category => categories.add(category)); + }); + + return Array.from(categories).sort(); + }, [items]); return ( crd.spec.names.kind, + getValue: (crd: CRD) => crd.spec.names.kind, render: crd => ( crd.spec.scope, }, + { + label: t('translation|Categories'), + getValue: crd => crd.getCategories()?.join(', '), + filterVariant: 'multi-select', + filterSelectOptions: categories, + }, 'age', ]} /> diff --git a/frontend/src/components/crd/__snapshots__/CustomResourceDefinition.stories.storyshot b/frontend/src/components/crd/__snapshots__/CustomResourceDefinition.stories.storyshot index 687a2e92cc..23d0cc20e8 100644 --- a/frontend/src/components/crd/__snapshots__/CustomResourceDefinition.stories.storyshot +++ b/frontend/src/components/crd/__snapshots__/CustomResourceDefinition.stories.storyshot @@ -1383,6 +1383,83 @@ exports[`Storyshots crd/CustomResourceDefinition List 1`] = ` /> +
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+
+
+ +
+
+ +
+ +
+
+
+ +

('crd') { @@ -48,6 +65,10 @@ class CustomResourceDefinition extends makeKubeObject('crd') { return this.jsonData!.spec; } + get status(): KubeCRD['status'] { + return this.jsonData!.status; + } + get plural(): string { return this.spec.names.plural; } @@ -88,6 +109,10 @@ class CustomResourceDefinition extends makeKubeObject('crd') { pluralName: this.spec.names.plural, }); } + + getCategories() { + return this.status?.acceptedNames?.categories ?? []; + } } export interface CRClassArgs {