fix: wave 1 quick wins — agent names, scroll bounce-back, chart empty states, model-pin preservation, UUID spawn normalization (#546)

* fix(panel): notifications show agent names, metrics charts get empty states

* fix(panel): stop expand/collapse scroll bounce-back; add floating scroll-jump buttons

* fix(llm): provider mode switches preserve per-agent model pins

* fix(api): normalize agent UUID to slug at the orchestrator route boundary

* fix(panel,docs): align routing-card copy and map docs with preserved-pin mode switches

* fix(panel): drop dead unfiltered scroll hook, re-observe on Suspense swap, name system sender

* docs(map): reflect preserved-pin mode switches, UUID-slug normalization, panel wave-1 deltas

---------

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
Renzo F
2026-07-18 00:42:13 +02:00
committed by GitHub
co-authored by Renn F
parent 4c8a9fc008
commit 9b4ce6b9c8
24 changed files with 415 additions and 160 deletions
@@ -0,0 +1,24 @@
import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import { UsageTimeSeriesChart } from "../usage-time-series-chart";
describe("UsageTimeSeriesChart", () => {
it("renders the card title", () => {
render(<UsageTimeSeriesChart data={undefined} isLoading={false} />);
expect(screen.getByText("Token Usage Over Time")).toBeInTheDocument();
});
it("shows an empty state when there is no data", () => {
render(<UsageTimeSeriesChart data={[]} isLoading={false} />);
expect(
screen.getByText("No usage recorded in this window yet."),
).toBeInTheDocument();
});
it("does not show the empty state while loading", () => {
render(<UsageTimeSeriesChart data={[]} isLoading />);
expect(
screen.queryByText("No usage recorded in this window yet."),
).not.toBeInTheDocument();
});
});
@@ -64,6 +64,10 @@ export function AgentUsageChart({ data, isLoading }: AgentUsageChartProps) {
<CardContent>
{isLoading ? (
<Skeleton className="h-52 w-full" />
) : tableRows.length === 0 ? (
<p className="text-sm text-muted-foreground py-16 text-center">
No usage recorded in this window yet.
</p>
) : view === "table" ? (
<div className="max-h-52 overflow-y-auto">
<table className="w-full text-sm">
@@ -47,6 +47,10 @@ export function ModelUsageDonut({ data, isLoading }: ModelUsageDonutProps) {
<CardContent>
{isLoading ? (
<Skeleton className="h-52 w-full" />
) : chartData.length === 0 ? (
<p className="text-sm text-muted-foreground py-16 text-center">
No usage recorded in this window yet.
</p>
) : (
<ResponsiveContainer width="100%" height={208}>
<PieChart>
@@ -61,6 +61,10 @@ export function TeamUsageChart({ data, isLoading }: TeamUsageChartProps) {
<CardContent>
{isLoading ? (
<Skeleton className="h-52 w-full" />
) : tableRows.length === 0 ? (
<p className="text-sm text-muted-foreground py-16 text-center">
No usage recorded in this window yet.
</p>
) : view === "table" ? (
<div className="max-h-52 overflow-y-auto">
<table className="w-full text-sm">
@@ -59,6 +59,10 @@ export function UsageTimeSeriesChart({
<CardContent>
{isLoading ? (
<Skeleton className="h-52 w-full" />
) : chartData.length === 0 ? (
<p className="text-sm text-muted-foreground py-16 text-center">
No usage recorded in this window yet.
</p>
) : (
<ResponsiveContainer width="100%" height={208}>
<AreaChart