feat(web,coder): add analytics + results pages for token usage and run history
New /analytics route: token usage dashboard with aggregate summary, per-session breakdown, context window stats, and per-category token distribution. Data served from existing agent_sessions + tool_cost_stats. New /results route: browsable archive of orchestrator flow runs and arena battles. Two-tab layout (Analysis Runs / Arena Battles) using existing API endpoints (no new backend). Sidebar gains Results (ScrollText icon) and Token Analytics (BarChart3 icon) nav buttons above Settings.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { NavLink, useLocation, useNavigate } from 'react-router-dom';
|
||||
import { ChevronRight, ExternalLink, Folder, MessageSquare, Plus, Settings as SettingsIcon, X, Code } from 'lucide-react';
|
||||
import { BarChart3, ChevronRight, ExternalLink, Folder, MessageSquare, Plus, ScrollText, Settings as SettingsIcon, X, Code } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import mascot from '@/assets/brand/banner-mascot.png';
|
||||
@@ -519,11 +519,40 @@ export function ProjectSidebar() {
|
||||
})}
|
||||
</nav>
|
||||
|
||||
{/* v1.9: bottom-pinned Settings button. In a session, opens/focuses the
|
||||
workspace settings pane via the sessionEvents bus (Session.tsx owns
|
||||
the panesHook). Outside a session there's no workspace to mount the
|
||||
pane in, so we navigate to /settings (themes page) instead. */}
|
||||
<div className="border-t shrink-0 p-2">
|
||||
{/* bottom-pinned nav buttons. Results → Analytics → Settings. */}
|
||||
<div className="border-t shrink-0 p-2 space-y-0.5">
|
||||
<NavLink
|
||||
to="/results"
|
||||
onClick={() => { if (isMobile) setDrawerOpen(false); }}
|
||||
className={({ isActive }) =>
|
||||
`w-full flex items-center gap-2 px-2 py-1.5 rounded-md text-sm hover:bg-sidebar-accent/60 text-sidebar-foreground ${
|
||||
isActive ? 'bg-sidebar-accent text-sidebar-accent-foreground' : ''
|
||||
}`
|
||||
}
|
||||
aria-label="Results"
|
||||
>
|
||||
<ScrollText className="size-3.5 shrink-0 opacity-70" />
|
||||
<span className="flex-1 text-left">Results</span>
|
||||
</NavLink>
|
||||
|
||||
<NavLink
|
||||
to="/analytics"
|
||||
onClick={() => { if (isMobile) setDrawerOpen(false); }}
|
||||
className={({ isActive }) =>
|
||||
`w-full flex items-center gap-2 px-2 py-1.5 rounded-md text-sm hover:bg-sidebar-accent/60 text-sidebar-foreground ${
|
||||
isActive ? 'bg-sidebar-accent text-sidebar-accent-foreground' : ''
|
||||
}`
|
||||
}
|
||||
aria-label="Token Analytics"
|
||||
>
|
||||
<BarChart3 className="size-3.5 shrink-0 opacity-70" />
|
||||
<span className="flex-1 text-left">Token Analytics</span>
|
||||
</NavLink>
|
||||
|
||||
{/* v1.9: bottom-pinned Settings button. In a session, opens/focuses the
|
||||
workspace settings pane via the sessionEvents bus (Session.tsx owns
|
||||
the panesHook). Outside a session there's no workspace to mount the
|
||||
pane in, so we navigate to /settings (themes page) instead. */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
|
||||
Reference in New Issue
Block a user