Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display categories for CRDs #1991

Merged
merged 4 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions frontend/src/components/common/Resource/ResourceTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export type ResourceTableColumn<RowItem> = {
* "min-content"
*/
gridTemplate?: string | number;
/** Options for the select filter */
filterSelectOptions?: TableColumn<any>['filterSelectOptions'];
} & (
| {
/** To render a simple value provide property name of the item */
Expand Down Expand Up @@ -266,6 +268,7 @@ function ResourceTableContent<RowItem>(props: ResourceTableProps<RowItem>) {
sx: { ...(column.cellProps?.sx ?? {}), width: 'unset', minWidth: 'unset' },
},
gridTemplate: column.gridTemplate ?? 1,
filterSelectOptions: column.filterSelectOptions,
};

if ('getValue' in column) {
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/components/crd/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ export default function CustomResourceDefinitionDetails() {
</Link>
),
},
{
name: t('translation|Categories'),
value: item.getCategories().join(', '),
hide: item.getCategories().length === 0,
},
]
}
/>
Expand Down
32 changes: 28 additions & 4 deletions frontend/src/components/crd/List.tsx
Original file line number Diff line number Diff line change
@@ -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<string>();
items.forEach((crd: CRD) => {
const crdCategories = crd.getCategories() || [];
crdCategories.forEach(category => categories.add(category));
});

return Array.from(categories).sort();
}, [items]);

return (
<ResourceListView
title={t('glossary|Custom Resources')}
headerProps={{
noNamespaceFilter: true,
noNamespaceFilter: false,
}}
resourceClass={CRD}
data={throttledItems}
errorMessage={CRD.getErrorMessage(error)}
columns={[
{
label: t('glossary|Resource'),
getValue: crd => crd.spec.names.kind,
getValue: (crd: CRD) => crd.spec.names.kind,
render: crd => (
<Link
routeName="customresources"
Expand Down Expand Up @@ -50,6 +68,12 @@ export default function CustomResourceDefinitionList() {
label: t('Scope'),
getValue: crd => crd.spec.scope,
},
{
label: t('translation|Categories'),
getValue: crd => crd.getCategories()?.join(', '),
filterVariant: 'multi-select',
filterSelectOptions: categories,
},
'age',
]}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1383,6 +1383,83 @@ exports[`Storyshots crd/CustomResourceDefinition List 1`] = `
/>
</div>
</div>
<div
class="MuiGrid-root MuiGrid-item css-13i4rnv-MuiGrid-root"
>
<div
class="MuiGrid-root MuiGrid-container MuiGrid-item css-43x3z6-MuiGrid-root"
>
<div
class="MuiGrid-root MuiGrid-item css-13i4rnv-MuiGrid-root"
>
<div
class="MuiAutocomplete-root MuiAutocomplete-hasPopupIcon css-clttge-MuiAutocomplete-root"
>
<div
class="MuiBox-root css-1dipl1t"
>
<div
class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root css-wb57ya-MuiFormControl-root-MuiTextField-root"
style="margin-top: 0px;"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-sizeMedium MuiInputLabel-standard MuiFormLabel-colorPrimary MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-sizeMedium MuiInputLabel-standard css-1n1vwza-MuiFormLabel-root-MuiInputLabel-root"
data-shrink="true"
for="mui-test-id"
id="mui-test-id-label"
>
Namespaces
</label>
<div
class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-adornedEnd MuiAutocomplete-inputRoot css-lbi814-MuiInputBase-root-MuiInput-root"
>
<input
aria-autocomplete="both"
aria-expanded="false"
aria-invalid="false"
autocapitalize="none"
autocomplete="off"
class="MuiInputBase-input MuiInput-input MuiInputBase-inputAdornedEnd MuiAutocomplete-input MuiAutocomplete-inputFocused css-1x51dt5-MuiInputBase-input-MuiInput-input"
id="mui-test-id"
placeholder="Filter"
role="combobox"
spellcheck="false"
type="text"
value=""
/>
<div
class="MuiAutocomplete-endAdornment css-p1olib-MuiAutocomplete-endAdornment"
>
<button
aria-label="Open"
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium MuiAutocomplete-popupIndicator css-1aav1nn-MuiButtonBase-root-MuiIconButton-root-MuiAutocomplete-popupIndicator"
tabindex="-1"
title="Open"
type="button"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
data-testid="ArrowDropDownIcon"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
<span
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
/>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="MuiBox-root css-1txv3mw"
Expand Down Expand Up @@ -1518,8 +1595,8 @@ exports[`Storyshots crd/CustomResourceDefinition List 1`] = `
class="MuiTableContainer-root css-nhjqqh-MuiTableContainer-root"
>
<table
class="MuiTable-root css-1v00ztz-MuiTable-root"
style="--header-0-size: 180; --col-0-size: 180; --header-1-size: 180; --col-1-size: 180; --header-2-size: 180; --col-2-size: 180; --header-3-size: 180; --col-3-size: 180; --header-age-size: 180; --col-age-size: 180;"
class="MuiTable-root css-6s04ct-MuiTable-root"
style="--header-0-size: 180; --col-0-size: 180; --header-1-size: 180; --col-1-size: 180; --header-2-size: 180; --col-2-size: 180; --header-3-size: 180; --col-3-size: 180; --header-4-size: 180; --col-4-size: 180; --header-age-size: 180; --col-age-size: 180;"
>
<thead
class="MuiTableHead-root css-114s3s2-MuiTableHead-root"
Expand Down Expand Up @@ -1836,10 +1913,87 @@ exports[`Storyshots crd/CustomResourceDefinition List 1`] = `
</div>
</th>
<th
class="MuiTableCell-root MuiTableCell-head MuiTableCell-alignLeft MuiTableCell-sizeMedium css-148gq9i-MuiTableCell-root"
class="MuiTableCell-root MuiTableCell-head MuiTableCell-alignLeft MuiTableCell-sizeMedium css-hzrbgy-MuiTableCell-root"
colspan="1"
data-index="4"
scope="col"
>
<div
class="Mui-TableHeadCell-Content MuiBox-root css-1w86f15"
>
<div
class="Mui-TableHeadCell-Content-Labels MuiBox-root css-68rqdf"
>
<div
class="Mui-TableHeadCell-Content-Wrapper MuiBox-root css-lapokc"
>
Categories
</div>
<span
aria-label="Sort by Categories ascending"
class="MuiBadge-root css-1c32n2y-MuiBadge-root"
data-mui-internal-clone-element="true"
>
<span
aria-label="Sort by Categories ascending"
class="MuiButtonBase-root MuiTableSortLabel-root Mui-active css-118d58w-MuiButtonBase-root-MuiTableSortLabel-root"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTableSortLabel-icon MuiTableSortLabel-iconDirectionAsc css-1vweko9-MuiSvgIcon-root-MuiTableSortLabel-icon"
data-testid="SyncAltIcon"
focusable="false"
style="transform: rotate(-90deg) scaleX(0.9) translateX(-1px);"
viewBox="0 0 24 24"
>
<path
d="m18 12 4-4-4-4v3H3v2h15zM6 12l-4 4 4 4v-3h15v-2H6z"
/>
</svg>
</span>
<span
class="MuiBadge-badge MuiBadge-standard MuiBadge-invisible MuiBadge-anchorOriginTopRight MuiBadge-anchorOriginTopRightCircular MuiBadge-overlapCircular css-dniquu-MuiBadge-badge"
>
0
</span>
</span>
</div>
<div
class="Mui-TableHeadCell-Content-Actions MuiBox-root css-epvm6"
>
<button
aria-label="Column Actions"
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1a0q64w-MuiButtonBase-root-MuiIconButton-root"
data-mui-internal-clone-element="true"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
data-testid="MoreVertIcon"
focusable="false"
style="transform: scale(0.9);"
viewBox="0 0 24 24"
>
<path
d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2m0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2m0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2"
/>
</svg>
<span
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
/>
</button>
</div>
</div>
</th>
<th
class="MuiTableCell-root MuiTableCell-head MuiTableCell-alignLeft MuiTableCell-sizeMedium css-148gq9i-MuiTableCell-root"
colspan="1"
data-index="5"
scope="col"
>
<div
class="Mui-TableHeadCell-Content MuiBox-root css-1w86f15"
Expand Down Expand Up @@ -1955,9 +2109,15 @@ exports[`Storyshots crd/CustomResourceDefinition List 1`] = `
Namespaced
</td>
<td
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignRight MuiTableCell-sizeMedium css-1k7434z-MuiTableCell-root"
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignLeft MuiTableCell-sizeMedium css-11hnma5-MuiTableCell-root"
data-index="4"
>

</td>
<td
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignRight MuiTableCell-sizeMedium css-1k7434z-MuiTableCell-root"
data-index="5"
>
<p
aria-label="2021-12-15T14:57:13.000Z"
class="MuiTypography-root MuiTypography-body1 css-1d0cpfm-MuiTypography-root"
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/crd/storyHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const mockCRDMap: { [crdName: string]: KubeCRD | null } = {
singular: 'mycustomresource',
kind: 'MyCustomResource',
listKind: 'MyCustomResourceList',
categories: ['all', 'category1'],
},
versions: [
{
Expand Down
1 change: 1 addition & 0 deletions frontend/src/i18n/locales/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
"No custom resources found": "Keine benutzerdefinierten Ressourcen gefunden",
"Loading resource definition details": "Lade Details zur Ressourcendefinition",
"Group": "Gruppe",
"Categories": "",
"Accepted Names": "Akzeptierte Namen",
"Versions": "Versionen",
"Spawn Job": "Erzeuge Job",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
"No custom resources found": "No custom resources found",
"Loading resource definition details": "Loading resource definition details",
"Group": "Group",
"Categories": "Categories",
"Accepted Names": "Accepted Names",
"Versions": "Versions",
"Spawn Job": "Spawn Job",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/i18n/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
"No custom resources found": "No se encontraron custom resources",
"Loading resource definition details": "Cargando detalles de la definición del recurso",
"Group": "Grupo",
"Categories": "",
"Accepted Names": "Nombres Aceptados",
"Versions": "Versiones",
"Spawn Job": "Crear Job",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/i18n/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
"No custom resources found": "Aucune ressource personnalisée trouvée",
"Loading resource definition details": "Chargement des détails de la définition des ressources",
"Group": "Groupe",
"Categories": "",
"Accepted Names": "Noms acceptés",
"Versions": "Versions",
"Spawn Job": "Lancer un Job",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/i18n/locales/pt/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
"No custom resources found": "Não foram encontrados \"custom resources\"",
"Loading resource definition details": "A carregar os detalhes de definição do recurso",
"Group": "Grupo",
"Categories": "",
"Accepted Names": "Nomes aceites",
"Versions": "Versões",
"Spawn Job": "Criar Job",
Expand Down
25 changes: 25 additions & 0 deletions frontend/src/lib/k8s/crd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface KubeCRD extends KubeObjectInterface {
singular: string;
kind: string;
listKind: string;
categories?: string[];
};
versions: {
name: string;
Expand All @@ -28,6 +29,22 @@ export interface KubeCRD extends KubeObjectInterface {
scope: string;
[other: string]: any;
};
status?: {
acceptedNames?: {
kind: string;
plural: string;
shortNames: string[];
categories?: string[];
};
conditions?: {
type: string;
status: string;
lastTransitionTime: string;
reason: string;
message: string;
}[];
storedVersions?: string[];
};
}

class CustomResourceDefinition extends makeKubeObject<KubeCRD>('crd') {
Expand All @@ -48,6 +65,10 @@ class CustomResourceDefinition extends makeKubeObject<KubeCRD>('crd') {
return this.jsonData!.spec;
}

get status(): KubeCRD['status'] {
return this.jsonData!.status;
}

get plural(): string {
return this.spec.names.plural;
}
Expand Down Expand Up @@ -88,6 +109,10 @@ class CustomResourceDefinition extends makeKubeObject<KubeCRD>('crd') {
pluralName: this.spec.names.plural,
});
}

getCategories() {
return this.status?.acceptedNames?.categories ?? [];
}
}

export interface CRClassArgs {
Expand Down
Loading