fix: sort RBAC dashboard diagram columns consistently
This commit is contained in:
@@ -1,38 +1,72 @@
|
||||
import { useRbacStats, useGroups, useRoles } from '../../../api/queries/admin/rbac';
|
||||
import type { GroupDetail, RoleDetail } from '../../../api/queries/admin/rbac';
|
||||
import { useMemo } from 'react';
|
||||
import { useRbacStats, useGroups } from '../../../api/queries/admin/rbac';
|
||||
import type { GroupDetail } from '../../../api/queries/admin/rbac';
|
||||
import styles from './RbacPage.module.css';
|
||||
|
||||
export function DashboardTab() {
|
||||
const stats = useRbacStats();
|
||||
const groups = useGroups();
|
||||
const roles = useRoles();
|
||||
|
||||
const groupList: GroupDetail[] = groups.data ?? [];
|
||||
|
||||
// Build inheritance diagram data: top-level groups sorted alphabetically,
|
||||
// children sorted alphabetically and indented below their parent.
|
||||
const { topLevelGroups, childMap } = useMemo(() => {
|
||||
const sorted = [...groupList].sort((a, b) => a.name.localeCompare(b.name));
|
||||
const top = sorted.filter((g) => !g.parentGroupId);
|
||||
const cMap = new Map<string, GroupDetail[]>();
|
||||
for (const g of sorted) {
|
||||
if (g.parentGroupId) {
|
||||
const children = cMap.get(g.parentGroupId) ?? [];
|
||||
children.push(g);
|
||||
cMap.set(g.parentGroupId, children);
|
||||
}
|
||||
}
|
||||
return { topLevelGroups: top, childMap: cMap };
|
||||
}, [groupList]);
|
||||
|
||||
// Derive roles from groups in tree order (top-level then children), collecting
|
||||
// each group's directRoles, deduplicating by id and preserving first-seen order.
|
||||
const roleList = useMemo(() => {
|
||||
const seen = new Set<string>();
|
||||
const result: { id: string; name: string }[] = [];
|
||||
for (const g of topLevelGroups) {
|
||||
for (const r of g.directRoles) {
|
||||
if (!seen.has(r.id)) {
|
||||
seen.add(r.id);
|
||||
result.push(r);
|
||||
}
|
||||
}
|
||||
for (const child of childMap.get(g.id) ?? []) {
|
||||
for (const r of child.directRoles) {
|
||||
if (!seen.has(r.id)) {
|
||||
seen.add(r.id);
|
||||
result.push(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}, [topLevelGroups, childMap]);
|
||||
|
||||
// Collect unique users from all groups, sorted alphabetically by displayName.
|
||||
const allUsers = useMemo(() => {
|
||||
const userMap = new Map<string, string>();
|
||||
for (const g of groupList) {
|
||||
for (const m of g.members) {
|
||||
userMap.set(m.userId, m.displayName);
|
||||
}
|
||||
}
|
||||
return new Map(
|
||||
[...userMap.entries()].sort((a, b) => a[1].localeCompare(b[1]))
|
||||
);
|
||||
}, [groupList]);
|
||||
|
||||
if (stats.isLoading) {
|
||||
return <div className={styles.loading}>Loading...</div>;
|
||||
}
|
||||
|
||||
const s = stats.data;
|
||||
const groupList: GroupDetail[] = groups.data ?? [];
|
||||
const roleList: RoleDetail[] = roles.data ?? [];
|
||||
|
||||
// Build inheritance diagram data
|
||||
const topLevelGroups = groupList.filter((g) => !g.parentGroupId);
|
||||
const childMap = new Map<string, GroupDetail[]>();
|
||||
for (const g of groupList) {
|
||||
if (g.parentGroupId) {
|
||||
const children = childMap.get(g.parentGroupId) ?? [];
|
||||
children.push(g);
|
||||
childMap.set(g.parentGroupId, children);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect unique users from all groups
|
||||
const allUsers = new Map<string, string>();
|
||||
for (const g of groupList) {
|
||||
for (const m of g.members) {
|
||||
allUsers.set(m.userId, m.displayName);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user