feat: build admin search data for cmd-k on admin pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,8 @@ import { Box, Settings, FileText, ChevronRight, Square, Pause, Star, X } from 'l
|
||||
import { useRouteCatalog } from '../api/queries/catalog';
|
||||
import { useAgents } from '../api/queries/agents';
|
||||
import { useSearchExecutions, useAttributeKeys } from '../api/queries/executions';
|
||||
import { useUsers, useGroups, useRoles } from '../api/queries/admin/rbac';
|
||||
import type { UserDetail, GroupDetail, RoleDetail } from '../api/queries/admin/rbac';
|
||||
import { useAuthStore } from '../auth/auth-store';
|
||||
import { useState, useMemo, useCallback, useEffect, useRef, createElement } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
@@ -95,6 +97,52 @@ function buildSearchData(
|
||||
return results;
|
||||
}
|
||||
|
||||
function buildAdminSearchData(
|
||||
users: UserDetail[] | undefined,
|
||||
groups: GroupDetail[] | undefined,
|
||||
roles: RoleDetail[] | undefined,
|
||||
): SearchResult[] {
|
||||
const results: SearchResult[] = [];
|
||||
|
||||
if (users) {
|
||||
for (const u of users) {
|
||||
results.push({
|
||||
id: `user:${u.userId}`,
|
||||
category: 'user',
|
||||
title: u.displayName || u.userId,
|
||||
meta: u.userId,
|
||||
path: '/admin/rbac',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (groups) {
|
||||
for (const g of groups) {
|
||||
results.push({
|
||||
id: `group:${g.id}`,
|
||||
category: 'group',
|
||||
title: g.name,
|
||||
meta: g.parentGroupId ? `parent: ${g.parentGroupId}` : 'top-level group',
|
||||
path: '/admin/rbac',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (roles) {
|
||||
for (const r of roles) {
|
||||
results.push({
|
||||
id: `role:${r.id}`,
|
||||
category: 'role',
|
||||
title: r.name,
|
||||
meta: r.scope,
|
||||
path: '/admin/rbac',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function healthToSearchColor(health: string): string {
|
||||
switch (health) {
|
||||
case 'live': return 'success';
|
||||
@@ -226,6 +274,12 @@ function LayoutContent() {
|
||||
const { data: catalog } = useRouteCatalog(timeRange.start.toISOString(), timeRange.end.toISOString());
|
||||
const { data: agents } = useAgents();
|
||||
const { data: attributeKeys } = useAttributeKeys();
|
||||
|
||||
// --- Admin search data (only fetched on admin pages) ----------------
|
||||
const { data: adminUsers } = useUsers();
|
||||
const { data: adminGroups } = useGroups();
|
||||
const { data: adminRoles } = useRoles();
|
||||
|
||||
const { username, logout } = useAuthStore();
|
||||
const { open: paletteOpen, setOpen: setPaletteOpen } = useCommandPalette();
|
||||
const { scope, setTab } = useScope();
|
||||
@@ -365,7 +419,14 @@ function LayoutContent() {
|
||||
catalogRef.current = catalogData;
|
||||
}
|
||||
|
||||
const searchData: SearchResult[] = useMemo(() => {
|
||||
const adminSearchData: SearchResult[] = useMemo(
|
||||
() => buildAdminSearchData(adminUsers, adminGroups, adminRoles),
|
||||
[adminUsers, adminGroups, adminRoles],
|
||||
);
|
||||
|
||||
const operationalSearchData: SearchResult[] = useMemo(() => {
|
||||
if (isAdminPage) return [];
|
||||
|
||||
const exchangeItems: SearchResult[] = (exchangeResults?.data || []).map((e: any) => ({
|
||||
id: e.executionId,
|
||||
category: 'exchange' as const,
|
||||
@@ -399,7 +460,9 @@ function LayoutContent() {
|
||||
}
|
||||
|
||||
return [...catalogRef.current, ...exchangeItems, ...attributeItems];
|
||||
}, [catalogRef.current, exchangeResults, debouncedQuery]);
|
||||
}, [isAdminPage, catalogRef.current, exchangeResults, debouncedQuery]);
|
||||
|
||||
const searchData = isAdminPage ? adminSearchData : operationalSearchData;
|
||||
|
||||
// --- Breadcrumb ---------------------------------------------------
|
||||
const breadcrumb = useMemo(() => {
|
||||
|
||||
Reference in New Issue
Block a user