mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-22 14:16:42 +08:00
### 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:
@ -1,7 +1,6 @@
|
||||
import {
|
||||
Timeline,
|
||||
TimelineContent,
|
||||
TimelineDate,
|
||||
TimelineHeader,
|
||||
TimelineIndicator,
|
||||
TimelineItem,
|
||||
@ -9,45 +8,10 @@ import {
|
||||
TimelineTitle,
|
||||
} from '@/components/originui/timeline';
|
||||
import { ITraceData } from '@/interfaces/database/agent';
|
||||
import { Aperture } from 'lucide-react';
|
||||
|
||||
const items = [
|
||||
{
|
||||
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',
|
||||
},
|
||||
];
|
||||
import { useCallback } from 'react';
|
||||
import { Operator } from '../constant';
|
||||
import OperatorIcon from '../operator-icon';
|
||||
import useGraphStore from '../store';
|
||||
|
||||
export type DataflowTimelineProps = {
|
||||
traceList?: ITraceData[];
|
||||
@ -61,36 +25,73 @@ interface DataflowTrace {
|
||||
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 (
|
||||
<Timeline>
|
||||
{items.map((item) => (
|
||||
<TimelineItem
|
||||
key={item.id}
|
||||
step={item.id}
|
||||
className="group-data-[orientation=vertical]/timeline:ms-10 group-data-[orientation=vertical]/timeline:not-last:pb-8"
|
||||
>
|
||||
<TimelineHeader>
|
||||
<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" />
|
||||
<TimelineTitle className="">
|
||||
{/* {item.title}
|
||||
<span className="text-muted-foreground text-sm font-normal">
|
||||
{item.action}
|
||||
</span> */}
|
||||
<TimelineContent className="text-foreground mt-2 rounded-lg border px-4 py-3">
|
||||
{item.description}
|
||||
<TimelineDate className="mt-1 mb-0">{item.date}</TimelineDate>
|
||||
</TimelineContent>
|
||||
</TimelineTitle>
|
||||
<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">
|
||||
<Aperture className="size-6 rounded-full" />
|
||||
</TimelineIndicator>
|
||||
</TimelineHeader>
|
||||
{/* <TimelineContent className="text-foreground mt-2 rounded-lg border px-4 py-3">
|
||||
{item.description}
|
||||
<TimelineDate className="mt-1 mb-0">{item.date}</TimelineDate>
|
||||
</TimelineContent> */}
|
||||
</TimelineItem>
|
||||
))}
|
||||
{Array.isArray(traceList) &&
|
||||
traceList?.map((item, index) => {
|
||||
const traces = item.trace as DataflowTrace[];
|
||||
const nodeLabel = getNodeLabel(item.component_id);
|
||||
|
||||
return (
|
||||
<TimelineItem
|
||||
key={item.component_id}
|
||||
step={index}
|
||||
className="group-data-[orientation=vertical]/timeline:ms-10 group-data-[orientation=vertical]/timeline:not-last:pb-8"
|
||||
>
|
||||
<TimelineHeader>
|
||||
<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" />
|
||||
<TimelineTitle className="">
|
||||
<TimelineContent className="text-foreground mt-2 rounded-lg border px-4 py-3">
|
||||
<p className="mb-2">
|
||||
{getNodeData(item.component_id)?.name || 'END'}
|
||||
</p>
|
||||
<div className="divide-y space-y-1">
|
||||
{traces.map((x, idx) => (
|
||||
<section
|
||||
key={idx}
|
||||
className="text-text-secondary text-xs"
|
||||
>
|
||||
<div className="space-x-2">
|
||||
<span>{x.datetime}</span>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
||||
@ -37,20 +37,20 @@ export function LogSheet({ hideModal, messageId }: LogSheetProps) {
|
||||
<SheetContent className={cn('top-20')}>
|
||||
<SheetHeader>
|
||||
<SheetTitle className="flex items-center gap-1">
|
||||
<NotebookText className="size-4" />
|
||||
<NotebookText className="size-4" /> {t('flow.log')}
|
||||
</SheetTitle>
|
||||
</SheetHeader>
|
||||
<section className="max-h-[82vh] overflow-auto mt-6">
|
||||
<DataflowTimeline traceList={data}></DataflowTimeline>
|
||||
<Button
|
||||
onClick={handleDownloadJson}
|
||||
disabled={isEndOutputEmpty(data)}
|
||||
className="w-full mt-8"
|
||||
>
|
||||
<SquareArrowOutUpRight />
|
||||
{t('dataflow.exportJson')}
|
||||
</Button>
|
||||
</section>
|
||||
<Button
|
||||
onClick={handleDownloadJson}
|
||||
disabled={isEndOutputEmpty(data)}
|
||||
className="w-full mt-8"
|
||||
>
|
||||
<SquareArrowOutUpRight />
|
||||
{t('dataflow.exportJson')}
|
||||
</Button>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user