Feat: Display the log after the data flow runs #9869 (#10232)

### What problem does this PR solve?

Feat: Display the log after the data flow runs #9869

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-09-23 19:30:47 +08:00
committed by GitHub
parent f20dca2895
commit 8f465525f7
2 changed files with 78 additions and 77 deletions

View File

@ -1,7 +1,6 @@
import { import {
Timeline, Timeline,
TimelineContent, TimelineContent,
TimelineDate,
TimelineHeader, TimelineHeader,
TimelineIndicator, TimelineIndicator,
TimelineItem, TimelineItem,
@ -9,45 +8,10 @@ import {
TimelineTitle, TimelineTitle,
} from '@/components/originui/timeline'; } from '@/components/originui/timeline';
import { ITraceData } from '@/interfaces/database/agent'; import { ITraceData } from '@/interfaces/database/agent';
import { Aperture } from 'lucide-react'; import { useCallback } from 'react';
import { Operator } from '../constant';
const items = [ import OperatorIcon from '../operator-icon';
{ import useGraphStore from '../store';
id: 1,
date: '15 minutes ago',
title: 'Hannah Kandell',
action: 'opened a new issue',
description:
"I'm having trouble with the new component library. It's not rendering properly.",
image: '/avatar-40-01.jpg',
},
{
id: 2,
date: '10 minutes ago',
title: 'Chris Tompson',
action: 'commented on',
description:
"Hey Hannah, I'm having trouble with the new component library. It's not rendering properly.",
image: '/avatar-40-02.jpg',
},
{
id: 3,
date: '5 minutes ago',
title: 'Emma Davis',
action: 'assigned you to',
description:
'The new component library is not rendering properly. Can you take a look?',
image: '/avatar-40-03.jpg',
},
{
id: 4,
date: '2 minutes ago',
title: 'Alex Morgan',
action: 'closed the issue',
description: 'The issue has been fixed. Please review the changes.',
image: '/avatar-40-05.jpg',
},
];
export type DataflowTimelineProps = { export type DataflowTimelineProps = {
traceList?: ITraceData[]; traceList?: ITraceData[];
@ -61,36 +25,73 @@ interface DataflowTrace {
timestamp: number; timestamp: number;
} }
export function DataflowTimeline({ traceList }: DataflowTimelineProps) { 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 ( return (
<Timeline> <Timeline>
{items.map((item) => ( {Array.isArray(traceList) &&
<TimelineItem traceList?.map((item, index) => {
key={item.id} const traces = item.trace as DataflowTrace[];
step={item.id} const nodeLabel = getNodeLabel(item.component_id);
className="group-data-[orientation=vertical]/timeline:ms-10 group-data-[orientation=vertical]/timeline:not-last:pb-8"
> return (
<TimelineHeader> <TimelineItem
<TimelineSeparator className="group-data-[orientation=vertical]/timeline:-left-7 group-data-[orientation=vertical]/timeline:h-[calc(100%-1.5rem-0.25rem)] group-data-[orientation=vertical]/timeline:translate-y-7" /> key={item.component_id}
<TimelineTitle className=""> step={index}
{/* {item.title} className="group-data-[orientation=vertical]/timeline:ms-10 group-data-[orientation=vertical]/timeline:not-last:pb-8"
<span className="text-muted-foreground text-sm font-normal"> >
{item.action} <TimelineHeader>
</span> */} <TimelineSeparator className="group-data-[orientation=vertical]/timeline:-left-7 group-data-[orientation=vertical]/timeline:h-[calc(100%-1.5rem-0.25rem)] group-data-[orientation=vertical]/timeline:translate-y-7 bg-accent-primary" />
<TimelineContent className="text-foreground mt-2 rounded-lg border px-4 py-3"> <TimelineTitle className="">
{item.description} <TimelineContent className="text-foreground mt-2 rounded-lg border px-4 py-3">
<TimelineDate className="mt-1 mb-0">{item.date}</TimelineDate> <p className="mb-2">
</TimelineContent> {getNodeData(item.component_id)?.name || 'END'}
</TimelineTitle> </p>
<TimelineIndicator className="bg-primary/10 group-data-completed/timeline-item:bg-primary group-data-completed/timeline-item:text-primary-foreground flex size-6 items-center justify-center border-none group-data-[orientation=vertical]/timeline:-left-7"> <div className="divide-y space-y-1">
<Aperture className="size-6 rounded-full" /> {traces.map((x, idx) => (
</TimelineIndicator> <section
</TimelineHeader> key={idx}
{/* <TimelineContent className="text-foreground mt-2 rounded-lg border px-4 py-3"> className="text-text-secondary text-xs"
{item.description} >
<TimelineDate className="mt-1 mb-0">{item.date}</TimelineDate> <div className="space-x-2">
</TimelineContent> */} <span>{x.datetime}</span>
</TimelineItem> <span>{x.progress * 100}%</span>
))} <span>{x.elapsed_time.toString().slice(0, 6)}</span>
</div>
{item.component_id !== 'END' && (
<div>{x.message}</div>
)}
</section>
))}
</div>
</TimelineContent>
</TimelineTitle>
<TimelineIndicator className="border border-accent-primary group-data-completed/timeline-item:bg-primary group-data-completed/timeline-item:text-primary-foreground flex size-6 items-center justify-center group-data-[orientation=vertical]/timeline:-left-7">
{nodeLabel && (
<OperatorIcon
name={nodeLabel}
className="size-6 rounded-full"
></OperatorIcon>
)}
</TimelineIndicator>
</TimelineHeader>
</TimelineItem>
);
})}
</Timeline> </Timeline>
); );
} }

View File

@ -37,20 +37,20 @@ export function LogSheet({ hideModal, messageId }: LogSheetProps) {
<SheetContent className={cn('top-20')}> <SheetContent className={cn('top-20')}>
<SheetHeader> <SheetHeader>
<SheetTitle className="flex items-center gap-1"> <SheetTitle className="flex items-center gap-1">
<NotebookText className="size-4" /> <NotebookText className="size-4" /> {t('flow.log')}
</SheetTitle> </SheetTitle>
</SheetHeader> </SheetHeader>
<section className="max-h-[82vh] overflow-auto mt-6"> <section className="max-h-[82vh] overflow-auto mt-6">
<DataflowTimeline traceList={data}></DataflowTimeline> <DataflowTimeline traceList={data}></DataflowTimeline>
<Button
onClick={handleDownloadJson}
disabled={isEndOutputEmpty(data)}
className="w-full mt-8"
>
<SquareArrowOutUpRight />
{t('dataflow.exportJson')}
</Button>
</section> </section>
<Button
onClick={handleDownloadJson}
disabled={isEndOutputEmpty(data)}
className="w-full mt-8"
>
<SquareArrowOutUpRight />
{t('dataflow.exportJson')}
</Button>
</SheetContent> </SheetContent>
</Sheet> </Sheet>
); );