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 { useParams, useNavigate } from 'react-router';
|
||||||
import {
|
import {
|
||||||
Badge, StatusDot, MonoText, CodeBlock, InfoCallout,
|
Badge, StatusDot, MonoText, CodeBlock, InfoCallout,
|
||||||
ProcessorTimeline, Breadcrumb, Spinner,
|
ProcessorTimeline, Breadcrumb, Spinner, SegmentedTabs, RouteFlow,
|
||||||
} from '@cameleer/design-system';
|
} from '@cameleer/design-system';
|
||||||
import { useExecutionDetail, useProcessorSnapshot } from '../../api/queries/executions';
|
import { useExecutionDetail, useProcessorSnapshot } from '../../api/queries/executions';
|
||||||
import { useCorrelationChain } from '../../api/queries/correlation';
|
import { useCorrelationChain } from '../../api/queries/correlation';
|
||||||
|
import { useDiagramByRoute } from '../../api/queries/diagrams';
|
||||||
|
import { mapDiagramToRouteNodes } from '../../utils/diagram-mapping';
|
||||||
import styles from './ExchangeDetail.module.css';
|
import styles from './ExchangeDetail.module.css';
|
||||||
|
|
||||||
function countProcessors(nodes: any[]): number {
|
function countProcessors(nodes: any[]): number {
|
||||||
@@ -17,8 +19,10 @@ export default function ExchangeDetail() {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { data: detail, isLoading } = useExecutionDetail(id ?? null);
|
const { data: detail, isLoading } = useExecutionDetail(id ?? null);
|
||||||
const [selectedProcessor, setSelectedProcessor] = useState<number | null>(null);
|
const [selectedProcessor, setSelectedProcessor] = useState<number | null>(null);
|
||||||
|
const [viewMode, setViewMode] = useState<'timeline' | 'flow'>('timeline');
|
||||||
const { data: snapshot } = useProcessorSnapshot(id ?? null, selectedProcessor);
|
const { data: snapshot } = useProcessorSnapshot(id ?? null, selectedProcessor);
|
||||||
const { data: correlationData } = useCorrelationChain(detail?.correlationId ?? null);
|
const { data: correlationData } = useCorrelationChain(detail?.correlationId ?? null);
|
||||||
|
const { data: diagram } = useDiagramByRoute(detail?.groupName, detail?.routeId);
|
||||||
|
|
||||||
const processors = useMemo(() => {
|
const processors = useMemo(() => {
|
||||||
if (!detail?.children) return [];
|
if (!detail?.children) return [];
|
||||||
@@ -115,10 +119,19 @@ export default function ExchangeDetail() {
|
|||||||
|
|
||||||
<div className={styles.timelineSection}>
|
<div className={styles.timelineSection}>
|
||||||
<div className={styles.timelineHeader}>
|
<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>
|
||||||
<div className={styles.timelineBody}>
|
<div className={styles.timelineBody}>
|
||||||
{processors.length > 0 ? (
|
{viewMode === 'timeline' ? (
|
||||||
|
processors.length > 0 ? (
|
||||||
<ProcessorTimeline
|
<ProcessorTimeline
|
||||||
processors={processors}
|
processors={processors}
|
||||||
totalMs={detail.durationMs}
|
totalMs={detail.durationMs}
|
||||||
@@ -127,6 +140,17 @@ export default function ExchangeDetail() {
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user