The Usage tab shows a bar for each configured limit. It turns amber at
80% and red at 100%. The tab also shows rejected requests per day, a
projected month-end cost with budget headroom, and CSV export for users
and groups. Names link to Charts with the matching scope.
The Charts tab ranks models over the full 24h, 30d or 12mo window. A
provider filter is applied on the server, and the ranking can be
exported as CSV. A new Events tab lists recent failures, filtered by
kind and user. The selected tab, filters and scope live in the URL
hash. Polling stops while the page is hidden. Views show which replica
answered, and a banner lists configuration warnings.
CSV cells that start with a formula character are neutralised. Links
sit outside the accordion buttons, so both controls keep their
accessible names. admin_assets_gen.go is regenerated.
Claude-Session: https://claude.ai/code/session_01V5jYJNxpDFdJkyyExpADrv
Component-first admin-panel rework (operator directive), replacing
hand-rolled patterns with the actual shadcn-vue library components
rather than working around them.
- Providers (OverviewView) and Groups (UsageView) now render as a real
shadcn-vue Accordion: trigger is the summary line, content holds the
detail (base URL, last refresh/error, model chips for providers;
full stat grid + member users for groups) — the earlier hand-rolled
second-<TableRow> toggle is retired. lib/provider-expand.ts's tested
two-set expand-state module is unchanged; only the template now
adapts it to Accordion's type="multiple" v-model via a writable
computed instead of driving a plain v-if.
- Usage view: expanding a group shows its member users' own usage rows
— a client-side join on AdminUsageEntryView.groupName, which admin.go
already sets per user (verified via admin_test.go's existing
TestAdminUsage_MathAgainstSeededCounters; no backend change needed).
- New DataTable.vue: the shadcn-vue DataTable pattern
(@tanstack/vue-table, pinned to ^8.21.3 — the version whose API
matches the documented pattern; npm's default "latest" resolves to
v9, a breaking rewrite with a different API) factored into one
reusable, generic component so every real table (users usage,
aliases, a group's nested member list) gets clickable sortable
headers with asc/desc indicators for free. usage-columns.ts holds
the shared ColumnDef set; UsageTable.vue now delegates to DataTable.
Groups themselves cannot be a literal <table> (Accordion wraps
content in a <div>, illegal inside <tbody>), so their own
sortability is driven by the same columns headlessly, surfaced as a
small header-button toolbar above the Accordion.
- Aliases table: alias id gets the ModelChip copy treatment (the alias
name is the routable string); target stays plain text.
- App.vue: dropped the max-w-6xl container — the panel now uses the
full viewport width with responsive gutters (px-4 sm:px-6 lg:px-8).
Table.vue already wraps every table in its own overflow-x-auto
container, so a wide table still scrolls itself, never the page.
shadcn-vue add accordion re-added @lucide/vue and required swapping
its Chevron icons for FontAwesome (webui/README.md's own documented
trap); components.json's iconLibrary/font keys stayed absent
(verified main.css byte-identical after the add).
Browser-verified against the real integration stack (real /admin over
the Yaegi plugin, strict CSP incl. style-src 'self'): provider/group
accordion expand, search auto-expand through the new Accordion
adapter, sort toggles on aliases/users/groups-toolbar/nested-member
tables, alias copy-to-clipboard, full-width at 1920px. Zero console
errors (one unrelated MetaMask extension log).