Skip to content

Commit

Permalink
frontend: RoleList: Make multi cluster aware
Browse files Browse the repository at this point in the history
In single cluster mode the RoleList is the same.

The ColumnType is exported needed here to keep the typechecker happy.

Signed-off-by: René Dudfield <[email protected]>
  • Loading branch information
illume committed Oct 16, 2024
1 parent 4752b32 commit 2018ed1
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 42 deletions.
2 changes: 1 addition & 1 deletion frontend/src/components/common/Resource/ResourceTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export type ResourceTableColumn<RowItem> = {
}
);

type ColumnType = 'age' | 'name' | 'namespace' | 'type' | 'kind' | 'cluster';
export type ColumnType = 'age' | 'name' | 'namespace' | 'type' | 'kind' | 'cluster';

export interface ResourceTableProps<RowItem> {
/** The columns to be rendered, like used in Table, or by name. */
Expand Down
59 changes: 18 additions & 41 deletions frontend/src/components/role/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,40 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import ClusterRole from '../../lib/k8s/clusterRole';
import Role from '../../lib/k8s/role';
import { useErrorState } from '../../lib/util';
import { combineClusterListErrors, flattenClusterListItems, getClusterGroup } from '../../lib/util';
import Link from '../common/Link';
import ResourceListView from '../common/Resource/ResourceListView';

interface RolesDict {
[kind: string]: Role[] | null;
}
import { ColumnType } from '../common/Resource/ResourceTable';

export default function RoleList() {
const [roles, setRoles] = React.useState<RolesDict | null>(null);
const [roleError, setRolesError] = useErrorState(setupRoles);
const [clusterRoleError, setClusterRolesError] = useErrorState(setupClusterRoles);
const { t } = useTranslation('glossary');
const [roles, rolesErrors] = Role.useListPerCluster();
const [clusterRoles, clusterRolesErrors] = ClusterRole.useListPerCluster();

function setupRolesWithKind(newRoles: Role[] | null, kind: string) {
setRoles(oldRoles => ({ ...(oldRoles || {}), [kind]: newRoles }));
}
const clusters = getClusterGroup();
const isMultiCluster = clusters.length > 1;

function setupRoles(roles: Role[] | null) {
setupRolesWithKind(roles, 'Role');
}
const allRoles = React.useMemo(() => {
return flattenClusterListItems(roles, clusterRoles);
}, [roles, clusterRoles]);

function setupClusterRoles(roles: ClusterRole[] | null) {
setupRolesWithKind(roles, 'ClusterRole');
}

function getJointItems() {
if (roles === null) {
return null;
}

let joint: Role[] = [];
let hasItems = false;

for (const items of Object.values(roles)) {
if (items !== null) {
joint = joint.concat(items);
hasItems = true;
}
}

return hasItems ? joint : null;
}
const allErrors = React.useMemo(() => {
return combineClusterListErrors(rolesErrors, clusterRolesErrors);
}, [rolesErrors, clusterRolesErrors]);

function getErrorMessage() {
if (getJointItems() === null) {
return Role.getErrorMessage(roleError || clusterRoleError);
if (Object.values(allErrors || {}).length === clusters.length && clusters.length > 1) {
return Role.getErrorMessage(Object.values(allErrors!)[0]);
}

return null;
}

Role.useApiList(setupRoles, setRolesError);
ClusterRole.useApiList(setupClusterRoles, setClusterRolesError);

return (
<ResourceListView
title={t('Roles')}
errorMessage={getErrorMessage()}
// clusterErrors={isMultiCluster ? allErrors : null}
columns={[
'type',
{
Expand All @@ -72,16 +47,18 @@ export default function RoleList() {
params={{
namespace: item.metadata.namespace || '',
name: item.metadata.name,
cluster: item.cluster,
}}
>
{item.metadata.name}
</Link>
),
},
'namespace',
...(isMultiCluster ? (['cluster'] as ColumnType[]) : ([] as ColumnType[])),
'age',
]}
data={getJointItems()}
data={allRoles}
id="headlamp-roles"
/>
);
Expand Down

0 comments on commit 2018ed1

Please sign in to comment.