import { Link, useLocation } from "react-router"; import { ArrowLeft } from "lucide-react"; import type { ReactNode } from "react"; import { SideNavItem, SideNavSection } from "@/components/SideNav"; import { SiloBrand } from "@/components/SiloBrand"; import { ADMIN_NAV_SECTIONS, buildAdminPluginNavItems, type AdminNavGroup, type AdminNavItem, } from "@/lib/adminNavigation"; import { navigateToPluginRoute } from "@/lib/buildPluginHref"; import { useAdminPluginInstallations } from "@/hooks/queries/admin/plugins"; import { useAdminSessions } from "@/hooks/queries/admin/stats"; import { useBuildInfo } from "@/hooks/queries/admin/system"; interface SidebarItem extends AdminNavItem { badge?: ReactNode; } interface SidebarSection extends Omit { label: string; items: SidebarItem[]; } interface AdminSidebarProps { onNavigate?: () => void; } function useSessionCount() { const { data: sessions = [] } = useAdminSessions(); return sessions.length; } export default function AdminSidebar({ onNavigate }: AdminSidebarProps) { const location = useLocation(); const sessionCount = useSessionCount(); const buildInfo = useBuildInfo(); // Falls back to "dev build" when the binary carries no VCS/ldflags revision // (e.g. `go run` or an image built without BUILD_REVISION) rather than a stark // "unavailable". let buildDisplay = "dev build"; if (buildInfo.isPending && !buildInfo.data) { buildDisplay = "loading..."; } else if (buildInfo.isError) { buildDisplay = "load failed"; } else if (buildInfo.data?.available) { buildDisplay = buildInfo.data.display; } const activityBadge = sessionCount > 0 ? {sessionCount} live : undefined; const sections: SidebarSection[] = ADMIN_NAV_SECTIONS.map((section) => ({ ...section, items: section.items.map((item) => item.href === "/admin/activity" ? { ...item, badge: activityBadge } : item, ), })); // Use the admin installations endpoint, not /settings/plugins — the user // settings endpoint filters to plugins that expose user settings / a user- // navigable route, which excludes admin-only plugins like arrproxy and // arrouter. The admin sidebar needs the full installation list to render // its "Plugin Apps" group. const { data: adminInstallations } = useAdminPluginInstallations(); const adminPluginItems = buildAdminPluginNavItems(adminInstallations); if (adminPluginItems.length > 0) { sections.push({ label: "Plugin Apps", items: adminPluginItems }); } function isActive(item: SidebarItem) { if (item.exact) return location.pathname === item.href; return location.pathname === item.href || location.pathname.startsWith(`${item.href}/`); } return ( ); }