import { Timeline, TimelineContent, TimelineHeader, TimelineIndicator, TimelineItem, TimelineSeparator, TimelineTitle, } from '@/components/originui/timeline'; import { Progress } from '@/components/ui/progress'; import { ITraceData } from '@/interfaces/database/agent'; import { cn } from '@/lib/utils'; import { isEmpty } from 'lodash'; import { File } from 'lucide-react'; import { useCallback } from 'react'; import { Operator } from '../constant'; import OperatorIcon from '../operator-icon'; import useGraphStore from '../store'; export type DataflowTimelineProps = { traceList?: ITraceData[]; }; const END = 'END'; interface DataflowTrace { datetime: string; elapsed_time: number; message: string; progress: number; timestamp: number; } export function DataflowTimeline({ traceList }: DataflowTimelineProps) { const getNode = useGraphStore((state) => state.getNode); const getNodeData = useCallback( (componentId: string) => { return getNode(componentId)?.data; }, [getNode], ); const getNodeLabel = useCallback( (componentId: string) => { return getNodeData(componentId)?.label as Operator; }, [getNodeData], ); return ( {Array.isArray(traceList) && traceList?.map((item, index) => { const traces = item.trace as DataflowTrace[]; const nodeLabel = getNodeLabel(item.component_id); const latest = traces[traces.length - 1]; const progress = latest.progress * 100; return (
{getNodeData(item.component_id)?.name || END}
{progress.toFixed(2)}%
{traces .filter((x) => !isEmpty(x.message)) .map((x, idx) => (
{x.datetime} {item.component_id !== 'END' && ( {x.message} )} {x.elapsed_time.toString().slice(0, 6)}s
))}
{item.component_id === END ? ( ) : nodeLabel === Operator.Begin ? ( ) : ( )}
); })}
); }