feat: show tracing badges on processor nodes
Update design system to 0.1.8 and pass NodeBadge[] to both ProcessorTimeline and RouteFlow. Traced processors display a blue "TRACED" badge that updates reactively via Zustand store. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
8
ui/package-lock.json
generated
8
ui/package-lock.json
generated
@@ -8,7 +8,7 @@
|
||||
"name": "ui",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@cameleer/design-system": "^0.1.7",
|
||||
"@cameleer/design-system": "^0.1.8",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
"openapi-fetch": "^0.17.0",
|
||||
"react": "^19.2.4",
|
||||
@@ -276,9 +276,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@cameleer/design-system": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://gitea.siegeln.net/api/packages/cameleer/npm/%40cameleer%2Fdesign-system/-/0.1.7/design-system-0.1.7.tgz",
|
||||
"integrity": "sha512-Q+CFFVuMqnF4xKB0Rtz4VZRQeaHqXjfK/M0DMCE0FIfW6q/bpTFBioPI5r7fDjBjIByG2hDB5XztL//I8o2RNA==",
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://gitea.siegeln.net/api/packages/cameleer/npm/%40cameleer%2Fdesign-system/-/0.1.8/design-system-0.1.8.tgz",
|
||||
"integrity": "sha512-mc7IQOYYez0UItvwiNbbYFrJehG3JtdVlOUsdLXcN8zmgtpImleVro4MsPxCX4/OOGI4EGoX1oIVpFi91qEI6A==",
|
||||
"dependencies": {
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"generate-api:live": "curl -s http://localhost:8081/api/v1/api-docs -o src/api/openapi.json && openapi-typescript src/api/openapi.json -o src/api/schema.d.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cameleer/design-system": "^0.1.7",
|
||||
"@cameleer/design-system": "^0.1.8",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
"openapi-fetch": "^0.17.0",
|
||||
"react": "^19.2.4",
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
Badge, StatusDot, MonoText, CodeBlock, InfoCallout,
|
||||
ProcessorTimeline, Breadcrumb, Spinner, RouteFlow, useToast,
|
||||
} from '@cameleer/design-system'
|
||||
import type { ProcessorStep, RouteNode } from '@cameleer/design-system'
|
||||
import type { ProcessorStep, RouteNode, NodeBadge } from '@cameleer/design-system'
|
||||
import { useExecutionDetail, useProcessorSnapshot } from '../../api/queries/executions'
|
||||
import { useCorrelationChain } from '../../api/queries/correlation'
|
||||
import { useDiagramLayout } from '../../api/queries/diagrams'
|
||||
@@ -74,25 +74,35 @@ export default function ExchangeDetail() {
|
||||
? (detail.processors?.length ? detail.processors : (detail.children ?? []))
|
||||
: []
|
||||
|
||||
// Subscribe to tracing state for badge rendering
|
||||
const tracedMap = useTracingStore((s) => s.tracedProcessors[detail?.applicationName ?? ''])
|
||||
|
||||
function badgesFor(processorId: string): NodeBadge[] | undefined {
|
||||
if (!tracedMap || !(processorId in tracedMap)) return undefined
|
||||
return [{ label: 'Traced', variant: 'info' }]
|
||||
}
|
||||
|
||||
// Flatten processor tree into ProcessorStep[]
|
||||
const processors: ProcessorStep[] = useMemo(() => {
|
||||
if (!procList.length) return []
|
||||
const result: ProcessorStep[] = []
|
||||
let offset = 0
|
||||
function walk(node: any) {
|
||||
const pid = node.processorId || node.processorType
|
||||
result.push({
|
||||
name: node.processorId || node.processorType,
|
||||
name: pid,
|
||||
type: node.processorType,
|
||||
durationMs: node.durationMs ?? 0,
|
||||
status: procStatusToStep(node.status ?? ''),
|
||||
startMs: offset,
|
||||
badges: badgesFor(node.processorId || ''),
|
||||
})
|
||||
offset += node.durationMs ?? 0
|
||||
if (node.children) node.children.forEach(walk)
|
||||
}
|
||||
procList.forEach(walk)
|
||||
return result
|
||||
}, [procList])
|
||||
}, [procList, tracedMap])
|
||||
|
||||
// Default selected processor: first failed, or 0
|
||||
const defaultIndex = useMemo(() => {
|
||||
@@ -121,7 +131,20 @@ export default function ExchangeDetail() {
|
||||
// Build RouteFlow nodes from diagram + execution data
|
||||
const routeNodes: RouteNode[] = useMemo(() => {
|
||||
if (diagram?.nodes) {
|
||||
return mapDiagramToRouteNodes(diagram.nodes, procList)
|
||||
// Flatten processors to build diagramNodeId → processorId lookup
|
||||
const flatProcs: Array<{ diagramNodeId?: string; processorId?: string }> = []
|
||||
function flattenProcs(nodes: any[]) {
|
||||
for (const n of nodes) { flatProcs.push(n); if (n.children) flattenProcs(n.children) }
|
||||
}
|
||||
flattenProcs(procList)
|
||||
const pidLookup = new Map(flatProcs
|
||||
.filter(p => p.diagramNodeId && p.processorId)
|
||||
.map(p => [p.diagramNodeId!, p.processorId!]))
|
||||
|
||||
return mapDiagramToRouteNodes(diagram.nodes, procList).map((node, i) => ({
|
||||
...node,
|
||||
badges: badgesFor(pidLookup.get(diagram.nodes[i]?.id ?? '') ?? diagram.nodes[i]?.id ?? ''),
|
||||
}))
|
||||
}
|
||||
// Fallback: build from processor list
|
||||
return processors.map((p) => ({
|
||||
@@ -129,8 +152,9 @@ export default function ExchangeDetail() {
|
||||
type: 'process' as RouteNode['type'],
|
||||
durationMs: p.durationMs,
|
||||
status: p.status,
|
||||
badges: badgesFor(p.name),
|
||||
}))
|
||||
}, [diagram, processors, procList])
|
||||
}, [diagram, processors, procList, tracedMap])
|
||||
|
||||
// ProcessorId lookup: timeline index → processorId
|
||||
const processorIds: string[] = useMemo(() => {
|
||||
|
||||
Reference in New Issue
Block a user