mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-25 08:32:11 +03:00
Beginner UX: purpose-first Traffic Inspector header (#11283)
Validated on a 3-PR combined board: traffic-inspector-beginner-header suite green within the board's 30/30, typecheck:core + dashboard-typecheck clean, gates within baseline. Purpose-first orientation header for Traffic Inspector, existing inspection UI untouched. Thank you @ignamiranda!
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
- **feat(dashboard):** lead Traffic Inspector with a purpose-first header that separates "what happened" from "how it happened", so beginners can read request outcomes without drowning in protocol detail ([#11283](https://github.com/diegosouzapw/OmniRoute/pull/11283))
|
||||||
@@ -15,7 +15,15 @@ import { HistoricSessionBanner } from "./components/session/HistoricSessionBanne
|
|||||||
|
|
||||||
const BUFFER_MAX = 1000;
|
const BUFFER_MAX = 1000;
|
||||||
|
|
||||||
export function TrafficInspectorPageClient() {
|
export function TrafficInspectorPageClient({
|
||||||
|
title,
|
||||||
|
subtitle,
|
||||||
|
purpose,
|
||||||
|
}: {
|
||||||
|
title?: string;
|
||||||
|
subtitle?: string;
|
||||||
|
purpose?: string;
|
||||||
|
} = {}) {
|
||||||
const [containerHeight, setContainerHeight] = useState(600);
|
const [containerHeight, setContainerHeight] = useState(600);
|
||||||
const listContainerRef = useRef<HTMLDivElement | null>(null);
|
const listContainerRef = useRef<HTMLDivElement | null>(null);
|
||||||
const [selectedRequest, setSelectedRequest] = useState<InterceptedRequest | null>(null);
|
const [selectedRequest, setSelectedRequest] = useState<InterceptedRequest | null>(null);
|
||||||
@@ -91,6 +99,18 @@ export function TrafficInspectorPageClient() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full overflow-hidden">
|
<div className="flex flex-col h-full overflow-hidden">
|
||||||
|
{title && (
|
||||||
|
<div className="shrink-0 px-4 pt-4 pb-2">
|
||||||
|
<h1 className="text-2xl font-bold text-text-main">{title}</h1>
|
||||||
|
{subtitle && (
|
||||||
|
<p className="text-sm text-text-muted mt-1 max-w-2xl">{subtitle}</p>
|
||||||
|
)}
|
||||||
|
{purpose && (
|
||||||
|
<p className="text-xs text-text-muted mt-2 max-w-2xl italic">{purpose}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Capture modes toolbar */}
|
{/* Capture modes toolbar */}
|
||||||
<div className="shrink-0 px-4 pt-4 pb-2">
|
<div className="shrink-0 px-4 pt-4 pb-2">
|
||||||
<CaptureModesToolbar customHostCount={0} />
|
<CaptureModesToolbar customHostCount={0} />
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export async function generateMetadata() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function TrafficInspectorPage() {
|
export default async function TrafficInspectorPage() {
|
||||||
return <TrafficInspectorPageClient />;
|
const t = await getTranslations("sidebar");
|
||||||
|
return <TrafficInspectorPageClient title={t("trafficInspector")} subtitle={t("trafficInspectorSubtitle")} purpose={t("trafficInspectorPurpose")} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1272,7 +1272,8 @@
|
|||||||
"agentBridge": "Agent Bridge",
|
"agentBridge": "Agent Bridge",
|
||||||
"agentBridgeSubtitle": "Intercept IDE agent traffic",
|
"agentBridgeSubtitle": "Intercept IDE agent traffic",
|
||||||
"trafficInspector": "Traffic Inspector",
|
"trafficInspector": "Traffic Inspector",
|
||||||
"trafficInspectorSubtitle": "Monitor LLM calls + debug any HTTPS traffic",
|
"trafficInspectorSubtitle": "Inspect request and response traffic from your apps",
|
||||||
|
"trafficInspectorPurpose": "See exactly what your application sends to and receives from AI providers. Works with any OpenAI-compatible client.",
|
||||||
"cliCode": "CLI Code",
|
"cliCode": "CLI Code",
|
||||||
"cliCodeSubtitle": "Code tools pointing to OmniRoute",
|
"cliCodeSubtitle": "Code tools pointing to OmniRoute",
|
||||||
"cliAgents": "CLI Agents",
|
"cliAgents": "CLI Agents",
|
||||||
|
|||||||
44
tests/unit/traffic-inspector-beginner-header.test.ts
Normal file
44
tests/unit/traffic-inspector-beginner-header.test.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import test from "node:test";
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||||
|
const pagePath = path.join(
|
||||||
|
repoRoot,
|
||||||
|
"src/app/(dashboard)/dashboard/tools/traffic-inspector/page.tsx"
|
||||||
|
);
|
||||||
|
const clientPath = path.join(
|
||||||
|
repoRoot,
|
||||||
|
"src/app/(dashboard)/dashboard/tools/traffic-inspector/TrafficInspectorPageClient.tsx"
|
||||||
|
);
|
||||||
|
const enPath = path.join(repoRoot, "src/i18n/messages/en.json");
|
||||||
|
|
||||||
|
test("Traffic Inspector page passes translated title, subtitle, and purpose", () => {
|
||||||
|
const pageSource = fs.readFileSync(pagePath, "utf8");
|
||||||
|
assert.match(pageSource, /title=\{t\("trafficInspector"\)\}/);
|
||||||
|
assert.match(pageSource, /subtitle=\{t\("trafficInspectorSubtitle"\)\}/);
|
||||||
|
assert.match(pageSource, /purpose=\{t\("trafficInspectorPurpose"\)\}/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Traffic Inspector client renders purpose-first header when props are provided", () => {
|
||||||
|
const clientSource = fs.readFileSync(clientPath, "utf8");
|
||||||
|
assert.match(clientSource, /title\s*&&/);
|
||||||
|
assert.match(clientSource, /subtitle\s*&&/);
|
||||||
|
assert.match(clientSource, /purpose\s*&&/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Traffic Inspector beginner i18n keys exist in en.json", () => {
|
||||||
|
const en = JSON.parse(fs.readFileSync(enPath, "utf8"));
|
||||||
|
assert.equal(en.sidebar.trafficInspector, "Traffic Inspector");
|
||||||
|
assert.equal(
|
||||||
|
en.sidebar.trafficInspectorSubtitle,
|
||||||
|
"Inspect request and response traffic from your apps"
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
typeof en.sidebar.trafficInspectorPurpose,
|
||||||
|
"string"
|
||||||
|
);
|
||||||
|
assert.ok(en.sidebar.trafficInspectorPurpose.length > 20);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user