fix: correct response field mappings and add logout button
- SearchResult uses 'data' not 'items', 'total' not 'totalCount' - ExecutionStats uses 'p99LatencyMs' not 'p99DurationMs' - TimeseriesBucket uses 'time' not 'timestamp' - Add user Dropdown with logout action to LayoutShell Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
12
ui/src/api/schema.d.ts
vendored
12
ui/src/api/schema.d.ts
vendored
@@ -151,7 +151,7 @@ export interface components {
|
|||||||
totalCount: number;
|
totalCount: number;
|
||||||
failedCount: number;
|
failedCount: number;
|
||||||
avgDurationMs: number;
|
avgDurationMs: number;
|
||||||
p99DurationMs: number;
|
p99LatencyMs: number;
|
||||||
activeCount: number;
|
activeCount: number;
|
||||||
totalToday: number;
|
totalToday: number;
|
||||||
prevTotalCount: number;
|
prevTotalCount: number;
|
||||||
@@ -163,7 +163,7 @@ export interface components {
|
|||||||
buckets: components['schemas']['TimeseriesBucket'][];
|
buckets: components['schemas']['TimeseriesBucket'][];
|
||||||
};
|
};
|
||||||
TimeseriesBucket: {
|
TimeseriesBucket: {
|
||||||
timestamp: string;
|
time: string;
|
||||||
totalCount: number;
|
totalCount: number;
|
||||||
failedCount: number;
|
failedCount: number;
|
||||||
avgDurationMs: number;
|
avgDurationMs: number;
|
||||||
@@ -171,8 +171,10 @@ export interface components {
|
|||||||
activeCount: number;
|
activeCount: number;
|
||||||
};
|
};
|
||||||
SearchResultExecutionSummary: {
|
SearchResultExecutionSummary: {
|
||||||
items: components['schemas']['ExecutionSummary'][];
|
data: components['schemas']['ExecutionSummary'][];
|
||||||
totalCount: number;
|
total: number;
|
||||||
|
offset: number;
|
||||||
|
limit: number;
|
||||||
};
|
};
|
||||||
UserInfo: {
|
UserInfo: {
|
||||||
userId: string;
|
userId: string;
|
||||||
@@ -228,7 +230,7 @@ export interface components {
|
|||||||
exchangeCount: number;
|
exchangeCount: number;
|
||||||
successRate: number;
|
successRate: number;
|
||||||
avgDurationMs: number;
|
avgDurationMs: number;
|
||||||
p99DurationMs: number;
|
p99LatencyMs: number;
|
||||||
errorRate: number;
|
errorRate: number;
|
||||||
throughputPerSec: number;
|
throughputPerSec: number;
|
||||||
sparkline: number[];
|
sparkline: number[];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Outlet, useNavigate, useLocation } from 'react-router';
|
import { Outlet, useNavigate, useLocation } from 'react-router';
|
||||||
import { AppShell, Sidebar, TopBar, CommandPalette, CommandPaletteProvider, GlobalFilterProvider, useCommandPalette } from '@cameleer/design-system';
|
import { AppShell, Sidebar, TopBar, CommandPalette, CommandPaletteProvider, GlobalFilterProvider, useCommandPalette, Dropdown, Avatar } from '@cameleer/design-system';
|
||||||
import { useRouteCatalog } from '../api/queries/catalog';
|
import { useRouteCatalog } from '../api/queries/catalog';
|
||||||
import { useAuthStore } from '../auth/auth-store';
|
import { useAuthStore } from '../auth/auth-store';
|
||||||
import { useMemo, useCallback } from 'react';
|
import { useMemo, useCallback } from 'react';
|
||||||
@@ -9,7 +9,7 @@ function LayoutContent() {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { data: catalog } = useRouteCatalog();
|
const { data: catalog } = useRouteCatalog();
|
||||||
const { username, roles } = useAuthStore();
|
const { username, roles, logout } = useAuthStore();
|
||||||
const { open: paletteOpen, setOpen: setPaletteOpen } = useCommandPalette();
|
const { open: paletteOpen, setOpen: setPaletteOpen } = useCommandPalette();
|
||||||
|
|
||||||
const sidebarApps: SidebarApp[] = useMemo(() => {
|
const sidebarApps: SidebarApp[] = useMemo(() => {
|
||||||
@@ -56,10 +56,22 @@ function LayoutContent() {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
<TopBar
|
<TopBar
|
||||||
breadcrumb={breadcrumb}
|
breadcrumb={breadcrumb}
|
||||||
user={username ? { name: username } : undefined}
|
user={username ? { name: username } : undefined}
|
||||||
/>
|
/>
|
||||||
|
{username && (
|
||||||
|
<Dropdown
|
||||||
|
trigger={<Avatar name={username} size="sm" />}
|
||||||
|
items={[
|
||||||
|
{ label: `Signed in as ${username}`, disabled: true },
|
||||||
|
{ divider: true, label: '' },
|
||||||
|
{ label: 'Logout', onClick: () => { logout(); navigate('/login'); } },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<CommandPalette
|
<CommandPalette
|
||||||
open={paletteOpen}
|
open={paletteOpen}
|
||||||
onClose={() => setPaletteOpen(false)}
|
onClose={() => setPaletteOpen(false)}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export default function Dashboard() {
|
|||||||
const { data: snapshot } = useProcessorSnapshot(selectedId, processorIdx);
|
const { data: snapshot } = useProcessorSnapshot(selectedId, processorIdx);
|
||||||
|
|
||||||
const rows: Row[] = useMemo(() =>
|
const rows: Row[] = useMemo(() =>
|
||||||
(searchResult?.items || []).map((e: ExecutionSummary) => ({ ...e, id: e.executionId })),
|
(searchResult?.data || []).map((e: ExecutionSummary) => ({ ...e, id: e.executionId })),
|
||||||
[searchResult],
|
[searchResult],
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ export default function Dashboard() {
|
|||||||
<StatCard label="Total Exchanges" value={stats?.totalCount ?? 0} sparkline={sparklineData} />
|
<StatCard label="Total Exchanges" value={stats?.totalCount ?? 0} sparkline={sparklineData} />
|
||||||
<StatCard label="Failed" value={stats?.failedCount ?? 0} accent="error" />
|
<StatCard label="Failed" value={stats?.failedCount ?? 0} accent="error" />
|
||||||
<StatCard label="Avg Duration" value={`${stats?.avgDurationMs ?? 0}ms`} />
|
<StatCard label="Avg Duration" value={`${stats?.avgDurationMs ?? 0}ms`} />
|
||||||
<StatCard label="P99 Duration" value={`${stats?.p99DurationMs ?? 0}ms`} accent="warning" />
|
<StatCard label="P99 Duration" value={`${stats?.p99LatencyMs ?? 0}ms`} accent="warning" />
|
||||||
<StatCard label="Active" value={stats?.activeCount ?? 0} accent="running" />
|
<StatCard label="Active" value={stats?.activeCount ?? 0} accent="running" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ export default function RoutesMetrics() {
|
|||||||
<div style={{ display: 'flex', gap: '1rem', marginBottom: '1.5rem', flexWrap: 'wrap' }}>
|
<div style={{ display: 'flex', gap: '1rem', marginBottom: '1.5rem', flexWrap: 'wrap' }}>
|
||||||
<StatCard label="Total Throughput" value={stats?.totalCount ?? 0} sparkline={sparklineData} />
|
<StatCard label="Total Throughput" value={stats?.totalCount ?? 0} sparkline={sparklineData} />
|
||||||
<StatCard label="Error Rate" value={stats?.totalCount ? `${(((stats.failedCount ?? 0) / stats.totalCount) * 100).toFixed(1)}%` : '0%'} accent="error" />
|
<StatCard label="Error Rate" value={stats?.totalCount ? `${(((stats.failedCount ?? 0) / stats.totalCount) * 100).toFixed(1)}%` : '0%'} accent="error" />
|
||||||
<StatCard label="P99 Latency" value={`${stats?.p99DurationMs ?? 0}ms`} accent="warning" />
|
<StatCard label="P99 Latency" value={`${stats?.p99LatencyMs ?? 0}ms`} accent="warning" />
|
||||||
<StatCard label="Success Rate" value={stats?.totalCount ? `${(((stats.totalCount - (stats.failedCount ?? 0)) / stats.totalCount) * 100).toFixed(1)}%` : '100%'} accent="success" />
|
<StatCard label="Success Rate" value={stats?.totalCount ? `${(((stats.totalCount - (stats.failedCount ?? 0)) / stats.totalCount) * 100).toFixed(1)}%` : '100%'} accent="success" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user