feat: fetch server capabilities and hide infra tabs when disabled
Adds a useServerCapabilities hook that fetches /api/v1/health once per session (staleTime: Infinity) and extracts the infrastructureEndpoints flag. buildAdminTreeNodes now accepts an opts parameter so ClickHouse and Database tabs are hidden when the server reports infra endpoints as disabled. LayoutShell wires the hook result into the admin tree memo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
29
ui/src/api/queries/capabilities.ts
Normal file
29
ui/src/api/queries/capabilities.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { config } from '../../config';
|
||||
|
||||
interface HealthResponse {
|
||||
status: string;
|
||||
components?: {
|
||||
serverCapabilities?: {
|
||||
details?: {
|
||||
infrastructureEndpoints?: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function useServerCapabilities() {
|
||||
return useQuery<{ infrastructureEndpoints: boolean }>({
|
||||
queryKey: ['server-capabilities'],
|
||||
queryFn: async () => {
|
||||
const res = await fetch(config.apiBaseUrl + '/health');
|
||||
if (!res.ok) return { infrastructureEndpoints: true };
|
||||
const data: HealthResponse = await res.json();
|
||||
return {
|
||||
infrastructureEndpoints:
|
||||
data.components?.serverCapabilities?.details?.infrastructureEndpoints ?? true,
|
||||
};
|
||||
},
|
||||
staleTime: Infinity,
|
||||
});
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import {
|
||||
readCollapsed,
|
||||
writeCollapsed,
|
||||
} from './sidebar-utils';
|
||||
import { useServerCapabilities } from '../api/queries/capabilities';
|
||||
import type { SidebarApp } from './sidebar-utils';
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -290,6 +291,9 @@ function LayoutContent() {
|
||||
const globalFilters = useGlobalFilters();
|
||||
const { timeRange, autoRefresh, refreshTimeRange } = globalFilters;
|
||||
|
||||
// --- Server capabilities ------------------------------------------
|
||||
const { data: capabilities } = useServerCapabilities();
|
||||
|
||||
// --- Role checks ----------------------------------------------------
|
||||
const isAdmin = useIsAdmin();
|
||||
|
||||
@@ -432,8 +436,8 @@ function LayoutContent() {
|
||||
);
|
||||
|
||||
const adminTreeNodes: SidebarTreeNode[] = useMemo(
|
||||
() => buildAdminTreeNodes(),
|
||||
[],
|
||||
() => buildAdminTreeNodes({ infrastructureEndpoints: capabilities?.infrastructureEndpoints }),
|
||||
[capabilities?.infrastructureEndpoints],
|
||||
);
|
||||
|
||||
// --- Starred items ------------------------------------------------
|
||||
|
||||
@@ -99,13 +99,15 @@ export function buildAppTreeNodes(
|
||||
/**
|
||||
* Admin tree — static nodes, alphabetically sorted.
|
||||
*/
|
||||
export function buildAdminTreeNodes(): SidebarTreeNode[] {
|
||||
return [
|
||||
export function buildAdminTreeNodes(opts?: { infrastructureEndpoints?: boolean }): SidebarTreeNode[] {
|
||||
const showInfra = opts?.infrastructureEndpoints !== false;
|
||||
const nodes: SidebarTreeNode[] = [
|
||||
{ id: 'admin:audit', label: 'Audit Log', path: '/admin/audit' },
|
||||
{ id: 'admin:clickhouse', label: 'ClickHouse', path: '/admin/clickhouse' },
|
||||
{ id: 'admin:database', label: 'Database', path: '/admin/database' },
|
||||
...(showInfra ? [{ id: 'admin:clickhouse', label: 'ClickHouse', path: '/admin/clickhouse' }] : []),
|
||||
...(showInfra ? [{ id: 'admin:database', label: 'Database', path: '/admin/database' }] : []),
|
||||
{ id: 'admin:environments', label: 'Environments', path: '/admin/environments' },
|
||||
{ id: 'admin:oidc', label: 'OIDC', path: '/admin/oidc' },
|
||||
{ id: 'admin:rbac', label: 'Users & Roles', path: '/admin/rbac' },
|
||||
];
|
||||
return nodes;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user