feat: add Timeline/Flow toggle to Exchange Detail
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,12 @@ import React, { useState, useMemo } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router';
|
||||
import {
|
||||
Badge, StatusDot, MonoText, CodeBlock, InfoCallout,
|
||||
ProcessorTimeline, Breadcrumb, Spinner,
|
||||
ProcessorTimeline, Breadcrumb, Spinner, SegmentedTabs, RouteFlow,
|
||||
} from '@cameleer/design-system';
|
||||
import { useExecutionDetail, useProcessorSnapshot } from '../../api/queries/executions';
|
||||
import { useCorrelationChain } from '../../api/queries/correlation';
|
||||
import { useDiagramByRoute } from '../../api/queries/diagrams';
|
||||
import { mapDiagramToRouteNodes } from '../../utils/diagram-mapping';
|
||||
import styles from './ExchangeDetail.module.css';
|
||||
|
||||
function countProcessors(nodes: any[]): number {
|
||||
@@ -17,8 +19,10 @@ export default function ExchangeDetail() {
|
||||
const navigate = useNavigate();
|
||||
const { data: detail, isLoading } = useExecutionDetail(id ?? null);
|
||||
const [selectedProcessor, setSelectedProcessor] = useState<number | null>(null);
|
||||
const [viewMode, setViewMode] = useState<'timeline' | 'flow'>('timeline');
|
||||
const { data: snapshot } = useProcessorSnapshot(id ?? null, selectedProcessor);
|
||||
const { data: correlationData } = useCorrelationChain(detail?.correlationId ?? null);
|
||||
const { data: diagram } = useDiagramByRoute(detail?.groupName, detail?.routeId);
|
||||
|
||||
const processors = useMemo(() => {
|
||||
if (!detail?.children) return [];
|
||||
@@ -115,18 +119,38 @@ export default function ExchangeDetail() {
|
||||
|
||||
<div className={styles.timelineSection}>
|
||||
<div className={styles.timelineHeader}>
|
||||
<span className={styles.timelineTitle}>Processor Timeline</span>
|
||||
<span className={styles.timelineTitle}>Processors</span>
|
||||
<SegmentedTabs
|
||||
tabs={[
|
||||
{ label: 'Timeline', value: 'timeline' },
|
||||
{ label: 'Flow', value: 'flow' },
|
||||
]}
|
||||
active={viewMode}
|
||||
onChange={(v) => setViewMode(v as 'timeline' | 'flow')}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.timelineBody}>
|
||||
{processors.length > 0 ? (
|
||||
<ProcessorTimeline
|
||||
processors={processors}
|
||||
totalMs={detail.durationMs}
|
||||
onProcessorClick={(_p, i) => setSelectedProcessor(i)}
|
||||
selectedIndex={selectedProcessor ?? undefined}
|
||||
/>
|
||||
{viewMode === 'timeline' ? (
|
||||
processors.length > 0 ? (
|
||||
<ProcessorTimeline
|
||||
processors={processors}
|
||||
totalMs={detail.durationMs}
|
||||
onProcessorClick={(_p, i) => setSelectedProcessor(i)}
|
||||
selectedIndex={selectedProcessor ?? undefined}
|
||||
/>
|
||||
) : (
|
||||
<InfoCallout>No processor data available</InfoCallout>
|
||||
)
|
||||
) : (
|
||||
<InfoCallout>No processor data available</InfoCallout>
|
||||
diagram ? (
|
||||
<RouteFlow
|
||||
nodes={mapDiagramToRouteNodes(diagram.nodes || [], detail.processors || detail.children || [])}
|
||||
onNodeClick={(_node, i) => setSelectedProcessor(i)}
|
||||
selectedIndex={selectedProcessor ?? undefined}
|
||||
/>
|
||||
) : (
|
||||
<Spinner />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user