Files
cameleer-server/ui/src/pages/routes/diagram/DiagramLegend.tsx
hsiegeln a108b57591
Some checks failed
CI / build (push) Successful in 1m12s
CI / deploy (push) Has been cancelled
CI / docker (push) Has been cancelled
Fix route diagram open issues: bugs, visual polish, interactive features
Batch 1 — Bug fixes:
- #51: Pass group+routeId to stats/timeseries API for route-scoped data
- #55: Propagate processor FAILED status to diagram error node highlighting

Batch 2 — Visual polish:
- #56: Brighter canvas background with amber/cyan radial gradients
- #57: Stronger glow filters (stdDeviation 3→6, opacity 0.4→0.6)
- #58: Uniform 200×40px leaf nodes with label truncation at 22 chars
- #59: Diagram legend (node types, edge types, overlay indicators)
- #64: SVG <title> tooltips on all nodes showing type, status, duration

Batch 3 — Interactive features:
- #60: Draggable minimap viewport (click-to-center, drag-to-pan)
- #62: CSS View Transitions slide animation, back arrow, Backspace key

Batch 4 — Advanced features:
- #50: Execution picker dropdown scoped to group+routeId
- #49: Iteration count badge (×N) on compound nodes
- #63: Route header stats (Executions Today, Success Rate, Avg, P99)

Closes #49 #50 #51 #55 #56 #57 #58 #59 #60 #62 #63 #64

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 22:14:23 +01:00

74 lines
2.3 KiB
TypeScript

import styles from './diagram.module.css';
interface LegendItem {
label: string;
color: string;
dashed?: boolean;
shape?: 'circle' | 'line';
}
const NODE_TYPES: LegendItem[] = [
{ label: 'Endpoint', color: '#58a6ff', shape: 'circle' },
{ label: 'EIP Pattern', color: '#b87aff', shape: 'circle' },
{ label: 'Processor', color: '#3fb950', shape: 'circle' },
{ label: 'Error Handler', color: '#f85149', shape: 'circle' },
{ label: 'Cross-route', color: '#39d2e0', shape: 'circle', dashed: true },
];
const EDGE_TYPES: LegendItem[] = [
{ label: 'Flow', color: '#4a5e7a', shape: 'line' },
{ label: 'Error', color: '#f85149', shape: 'line', dashed: true },
{ label: 'Cross-route', color: '#39d2e0', shape: 'line', dashed: true },
];
const OVERLAY_TYPES: LegendItem[] = [
{ label: 'Executed', color: '#3fb950', shape: 'circle' },
{ label: 'Execution path', color: '#3fb950', shape: 'line' },
{ label: 'Not executed', color: '#4a5e7a', shape: 'circle' },
];
function LegendRow({ item }: { item: LegendItem }) {
return (
<div className={styles.legendRow}>
{item.shape === 'circle' ? (
<span
className={styles.legendDot}
style={{
background: item.color,
border: item.dashed ? `1px dashed ${item.color}` : undefined,
opacity: item.label === 'Not executed' ? 0.3 : 1,
}}
/>
) : (
<span
className={styles.legendLine}
style={{
background: item.color,
borderStyle: item.dashed ? 'dashed' : 'solid',
}}
/>
)}
<span className={styles.legendLabel}>{item.label}</span>
</div>
);
}
export function DiagramLegend() {
return (
<div className={styles.legend}>
<div className={styles.legendSection}>
<span className={styles.legendTitle}>Nodes</span>
{NODE_TYPES.map((t) => <LegendRow key={t.label} item={t} />)}
</div>
<div className={styles.legendSection}>
<span className={styles.legendTitle}>Edges</span>
{EDGE_TYPES.map((t) => <LegendRow key={t.label} item={t} />)}
</div>
<div className={styles.legendSection}>
<span className={styles.legendTitle}>Overlay</span>
{OVERLAY_TYPES.map((t) => <LegendRow key={t.label} item={t} />)}
</div>
</div>
);
}