mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-08-14 03:55:58 +08:00
### What problem does this PR solve? feat: Display input parameters on operator nodes #3240 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
4097912d59
commit
d3bb5e9f3d
37
web/package-lock.json
generated
37
web/package-lock.json
generated
@ -17,6 +17,7 @@
|
|||||||
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
||||||
"@radix-ui/react-icons": "^1.3.1",
|
"@radix-ui/react-icons": "^1.3.1",
|
||||||
"@radix-ui/react-label": "^2.1.0",
|
"@radix-ui/react-label": "^2.1.0",
|
||||||
|
"@radix-ui/react-popover": "^1.1.2",
|
||||||
"@radix-ui/react-select": "^2.1.2",
|
"@radix-ui/react-select": "^2.1.2",
|
||||||
"@radix-ui/react-separator": "^1.1.0",
|
"@radix-ui/react-separator": "^1.1.0",
|
||||||
"@radix-ui/react-slot": "^1.1.0",
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
@ -4370,6 +4371,42 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-popover": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@radix-ui/react-popover/-/react-popover-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-u2HRUyWW+lOiA2g0Le0tMmT55FGOEWHwPFt1EPfbLly7uXQExFo5duNKqG2DzmFXIdqOeNd+TpE8baHWJCyP9w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.0",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
|
"@radix-ui/react-context": "1.1.1",
|
||||||
|
"@radix-ui/react-dismissable-layer": "1.1.1",
|
||||||
|
"@radix-ui/react-focus-guards": "1.1.1",
|
||||||
|
"@radix-ui/react-focus-scope": "1.1.0",
|
||||||
|
"@radix-ui/react-id": "1.1.0",
|
||||||
|
"@radix-ui/react-popper": "1.2.0",
|
||||||
|
"@radix-ui/react-portal": "1.1.2",
|
||||||
|
"@radix-ui/react-presence": "1.1.1",
|
||||||
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
|
"@radix-ui/react-slot": "1.1.0",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||||
|
"aria-hidden": "^1.1.1",
|
||||||
|
"react-remove-scroll": "2.6.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-popper": {
|
"node_modules/@radix-ui/react-popper": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
||||||
"@radix-ui/react-icons": "^1.3.1",
|
"@radix-ui/react-icons": "^1.3.1",
|
||||||
"@radix-ui/react-label": "^2.1.0",
|
"@radix-ui/react-label": "^2.1.0",
|
||||||
|
"@radix-ui/react-popover": "^1.1.2",
|
||||||
"@radix-ui/react-select": "^2.1.2",
|
"@radix-ui/react-select": "^2.1.2",
|
||||||
"@radix-ui/react-separator": "^1.1.0",
|
"@radix-ui/react-separator": "^1.1.0",
|
||||||
"@radix-ui/react-slot": "^1.1.0",
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
|
31
web/src/components/ui/popover.tsx
Normal file
31
web/src/components/ui/popover.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
|
const Popover = PopoverPrimitive.Root;
|
||||||
|
|
||||||
|
const PopoverTrigger = PopoverPrimitive.Trigger;
|
||||||
|
|
||||||
|
const PopoverContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof PopoverPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
||||||
|
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
|
||||||
|
<PopoverPrimitive.Portal>
|
||||||
|
<PopoverPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
align={align}
|
||||||
|
sideOffset={sideOffset}
|
||||||
|
className={cn(
|
||||||
|
'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</PopoverPrimitive.Portal>
|
||||||
|
));
|
||||||
|
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
||||||
|
|
||||||
|
export { Popover, PopoverContent, PopoverTrigger };
|
117
web/src/components/ui/table.tsx
Normal file
117
web/src/components/ui/table.tsx
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
|
const Table = React.forwardRef<
|
||||||
|
HTMLTableElement,
|
||||||
|
React.HTMLAttributes<HTMLTableElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<div className="relative w-full overflow-auto">
|
||||||
|
<table
|
||||||
|
ref={ref}
|
||||||
|
className={cn('w-full caption-bottom text-sm', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
|
Table.displayName = 'Table';
|
||||||
|
|
||||||
|
const TableHeader = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<thead ref={ref} className={cn('[&_tr]:border-b', className)} {...props} />
|
||||||
|
));
|
||||||
|
TableHeader.displayName = 'TableHeader';
|
||||||
|
|
||||||
|
const TableBody = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tbody
|
||||||
|
ref={ref}
|
||||||
|
className={cn('[&_tr:last-child]:border-0', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableBody.displayName = 'TableBody';
|
||||||
|
|
||||||
|
const TableFooter = React.forwardRef<
|
||||||
|
HTMLTableSectionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableSectionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tfoot
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableFooter.displayName = 'TableFooter';
|
||||||
|
|
||||||
|
const TableRow = React.forwardRef<
|
||||||
|
HTMLTableRowElement,
|
||||||
|
React.HTMLAttributes<HTMLTableRowElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<tr
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableRow.displayName = 'TableRow';
|
||||||
|
|
||||||
|
const TableHead = React.forwardRef<
|
||||||
|
HTMLTableCellElement,
|
||||||
|
React.ThHTMLAttributes<HTMLTableCellElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<th
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
'h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableHead.displayName = 'TableHead';
|
||||||
|
|
||||||
|
const TableCell = React.forwardRef<
|
||||||
|
HTMLTableCellElement,
|
||||||
|
React.TdHTMLAttributes<HTMLTableCellElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<td
|
||||||
|
ref={ref}
|
||||||
|
className={cn('p-4 align-middle [&:has([role=checkbox])]:pr-0', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableCell.displayName = 'TableCell';
|
||||||
|
|
||||||
|
const TableCaption = React.forwardRef<
|
||||||
|
HTMLTableCaptionElement,
|
||||||
|
React.HTMLAttributes<HTMLTableCaptionElement>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<caption
|
||||||
|
ref={ref}
|
||||||
|
className={cn('mt-4 text-sm text-muted-foreground', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableCaption.displayName = 'TableCaption';
|
||||||
|
|
||||||
|
export {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCaption,
|
||||||
|
TableCell,
|
||||||
|
TableFooter,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
};
|
@ -11,7 +11,8 @@ export interface BaseState {
|
|||||||
|
|
||||||
export interface IModalProps<T> {
|
export interface IModalProps<T> {
|
||||||
showModal?(): void;
|
showModal?(): void;
|
||||||
hideModal(): void;
|
hideModal?(): void;
|
||||||
|
switchVisible?(visible: boolean): void;
|
||||||
visible?: boolean;
|
visible?: boolean;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
onOk?(payload?: T): Promise<any> | void;
|
onOk?(payload?: T): Promise<any> | void;
|
||||||
|
@ -1031,8 +1031,11 @@ The above is the content you need to summarize.`,
|
|||||||
'If the response is HTML formatted and only the primary content wanted, please toggle it on.',
|
'If the response is HTML formatted and only the primary content wanted, please toggle it on.',
|
||||||
reference: 'Reference',
|
reference: 'Reference',
|
||||||
input: 'Input',
|
input: 'Input',
|
||||||
|
output: 'Output',
|
||||||
parameter: 'Parameter',
|
parameter: 'Parameter',
|
||||||
howUseId: 'How to use agent ID?',
|
howUseId: 'How to use agent ID?',
|
||||||
|
content: 'Content',
|
||||||
|
operationResults: 'Operation Results',
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
profile: 'All rights reserved @ React',
|
profile: 'All rights reserved @ React',
|
||||||
|
@ -979,8 +979,11 @@ export default {
|
|||||||
cleanHtmlTip: '如果回應是 HTML 格式並且只需要主要內容,請將其開啟。',
|
cleanHtmlTip: '如果回應是 HTML 格式並且只需要主要內容,請將其開啟。',
|
||||||
reference: '引用',
|
reference: '引用',
|
||||||
input: '輸入',
|
input: '輸入',
|
||||||
|
output: '輸出',
|
||||||
parameter: '參數',
|
parameter: '參數',
|
||||||
howUseId: '如何使用Agent ID?',
|
howUseId: '如何使用Agent ID?',
|
||||||
|
content: '內容',
|
||||||
|
operationResults: '運行結果',
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
profile: '“保留所有權利 @ react”',
|
profile: '“保留所有權利 @ react”',
|
||||||
|
@ -999,8 +999,11 @@ export default {
|
|||||||
cleanHtmlTip: '如果响应是 HTML 格式且只需要主要内容,请将其打开。',
|
cleanHtmlTip: '如果响应是 HTML 格式且只需要主要内容,请将其打开。',
|
||||||
reference: '引用',
|
reference: '引用',
|
||||||
input: '输入',
|
input: '输入',
|
||||||
|
output: '输出',
|
||||||
parameter: '参数',
|
parameter: '参数',
|
||||||
howUseId: '如何使用Agent ID?',
|
howUseId: '如何使用Agent ID?',
|
||||||
|
content: '内容',
|
||||||
|
operationResults: '运行结果',
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
profile: 'All rights reserved @ React',
|
profile: 'All rights reserved @ React',
|
||||||
|
57
web/src/pages/flow/canvas/node/card.tsx
Normal file
57
web/src/pages/flow/canvas/node/card.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from '@/components/ui/card';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
|
||||||
|
export function CardWithForm() {
|
||||||
|
return (
|
||||||
|
<Card className="w-[350px]">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Create project</CardTitle>
|
||||||
|
<CardDescription>Deploy your new project in one-click.</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<form>
|
||||||
|
<div className="grid w-full items-center gap-4">
|
||||||
|
<div className="flex flex-col space-y-1.5">
|
||||||
|
<Label htmlFor="name">Name</Label>
|
||||||
|
<Input id="name" placeholder="Name of your project" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col space-y-1.5">
|
||||||
|
<Label htmlFor="framework">Framework</Label>
|
||||||
|
<Select>
|
||||||
|
<SelectTrigger id="framework">
|
||||||
|
<SelectValue placeholder="Select" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent position="popper">
|
||||||
|
<SelectItem value="next">Next.js</SelectItem>
|
||||||
|
<SelectItem value="sveltekit">SvelteKit</SelectItem>
|
||||||
|
<SelectItem value="astro">Astro</SelectItem>
|
||||||
|
<SelectItem value="nuxt">Nuxt.js</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter className="flex justify-between">
|
||||||
|
<Button variant="outline">Cancel</Button>
|
||||||
|
<Button>Deploy</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
@ -8,55 +8,52 @@ import { RightHandleStyle } from './handle-icon';
|
|||||||
import { useBuildCategorizeHandlePositions } from './hooks';
|
import { useBuildCategorizeHandlePositions } from './hooks';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import NodeHeader from './node-header';
|
import NodeHeader from './node-header';
|
||||||
import NodePopover from './popover';
|
|
||||||
|
|
||||||
export function CategorizeNode({ id, data, selected }: NodeProps<NodeData>) {
|
export function CategorizeNode({ id, data, selected }: NodeProps<NodeData>) {
|
||||||
const { positions } = useBuildCategorizeHandlePositions({ data, id });
|
const { positions } = useBuildCategorizeHandlePositions({ data, id });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodePopover nodeId={id}>
|
<section
|
||||||
<section
|
className={classNames(styles.logicNode, {
|
||||||
className={classNames(styles.logicNode, {
|
[styles.selectedNode]: selected,
|
||||||
[styles.selectedNode]: selected,
|
})}
|
||||||
|
>
|
||||||
|
<Handle
|
||||||
|
type="target"
|
||||||
|
position={Position.Left}
|
||||||
|
isConnectable
|
||||||
|
className={styles.handle}
|
||||||
|
id={'a'}
|
||||||
|
></Handle>
|
||||||
|
|
||||||
|
<NodeHeader
|
||||||
|
id={id}
|
||||||
|
name={data.name}
|
||||||
|
label={data.label}
|
||||||
|
className={styles.nodeHeader}
|
||||||
|
></NodeHeader>
|
||||||
|
|
||||||
|
<Flex vertical gap={8}>
|
||||||
|
<div className={styles.nodeText}>
|
||||||
|
<LLMLabel value={get(data, 'form.llm_id')}></LLMLabel>
|
||||||
|
</div>
|
||||||
|
{positions.map((position, idx) => {
|
||||||
|
return (
|
||||||
|
<div key={idx}>
|
||||||
|
<div className={styles.nodeText}>{position.text}</div>
|
||||||
|
<Handle
|
||||||
|
key={position.text}
|
||||||
|
id={position.text}
|
||||||
|
type="source"
|
||||||
|
position={Position.Right}
|
||||||
|
isConnectable
|
||||||
|
className={styles.handle}
|
||||||
|
style={{ ...RightHandleStyle, top: position.top }}
|
||||||
|
></Handle>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
>
|
</Flex>
|
||||||
<Handle
|
</section>
|
||||||
type="target"
|
|
||||||
position={Position.Left}
|
|
||||||
isConnectable
|
|
||||||
className={styles.handle}
|
|
||||||
id={'a'}
|
|
||||||
></Handle>
|
|
||||||
|
|
||||||
<NodeHeader
|
|
||||||
id={id}
|
|
||||||
name={data.name}
|
|
||||||
label={data.label}
|
|
||||||
className={styles.nodeHeader}
|
|
||||||
></NodeHeader>
|
|
||||||
|
|
||||||
<Flex vertical gap={8}>
|
|
||||||
<div className={styles.nodeText}>
|
|
||||||
<LLMLabel value={get(data, 'form.llm_id')}></LLMLabel>
|
|
||||||
</div>
|
|
||||||
{positions.map((position, idx) => {
|
|
||||||
return (
|
|
||||||
<div key={idx}>
|
|
||||||
<div className={styles.nodeText}>{position.text}</div>
|
|
||||||
<Handle
|
|
||||||
key={position.text}
|
|
||||||
id={position.text}
|
|
||||||
type="source"
|
|
||||||
position={Position.Right}
|
|
||||||
isConnectable
|
|
||||||
className={styles.handle}
|
|
||||||
style={{ ...RightHandleStyle, top: position.top }}
|
|
||||||
></Handle>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Flex>
|
|
||||||
</section>
|
|
||||||
</NodePopover>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import { IGenerateParameter, NodeData } from '../../interface';
|
|||||||
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import NodeHeader from './node-header';
|
import NodeHeader from './node-header';
|
||||||
import NodePopover from './popover';
|
|
||||||
|
|
||||||
export function GenerateNode({
|
export function GenerateNode({
|
||||||
id,
|
id,
|
||||||
@ -20,55 +19,53 @@ export function GenerateNode({
|
|||||||
const getLabel = useGetComponentLabelByValue(id);
|
const getLabel = useGetComponentLabelByValue(id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodePopover nodeId={id}>
|
<section
|
||||||
<section
|
className={classNames(styles.logicNode, {
|
||||||
className={classNames(styles.logicNode, {
|
[styles.selectedNode]: selected,
|
||||||
[styles.selectedNode]: selected,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<Handle
|
||||||
<Handle
|
id="c"
|
||||||
id="c"
|
type="source"
|
||||||
type="source"
|
position={Position.Left}
|
||||||
position={Position.Left}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
style={LeftHandleStyle}
|
||||||
style={LeftHandleStyle}
|
></Handle>
|
||||||
></Handle>
|
<Handle
|
||||||
<Handle
|
type="source"
|
||||||
type="source"
|
position={Position.Right}
|
||||||
position={Position.Right}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
style={RightHandleStyle}
|
||||||
style={RightHandleStyle}
|
id="b"
|
||||||
id="b"
|
></Handle>
|
||||||
></Handle>
|
|
||||||
|
|
||||||
<NodeHeader
|
<NodeHeader
|
||||||
id={id}
|
id={id}
|
||||||
name={data.name}
|
name={data.name}
|
||||||
label={data.label}
|
label={data.label}
|
||||||
className={styles.nodeHeader}
|
className={styles.nodeHeader}
|
||||||
></NodeHeader>
|
></NodeHeader>
|
||||||
|
|
||||||
<div className={styles.nodeText}>
|
<div className={styles.nodeText}>
|
||||||
<LLMLabel value={get(data, 'form.llm_id')}></LLMLabel>
|
<LLMLabel value={get(data, 'form.llm_id')}></LLMLabel>
|
||||||
</div>
|
</div>
|
||||||
<Flex gap={8} vertical className={styles.generateParameters}>
|
<Flex gap={8} vertical className={styles.generateParameters}>
|
||||||
{parameters.map((x) => (
|
{parameters.map((x) => (
|
||||||
<Flex
|
<Flex
|
||||||
key={x.id}
|
key={x.id}
|
||||||
align="center"
|
align="center"
|
||||||
gap={6}
|
gap={6}
|
||||||
className={styles.conditionBlock}
|
className={styles.conditionBlock}
|
||||||
>
|
>
|
||||||
<label htmlFor="">{x.key}</label>
|
<label htmlFor="">{x.key}</label>
|
||||||
<span className={styles.parameterValue}>
|
<span className={styles.parameterValue}>
|
||||||
{getLabel(x.component_id)}
|
{getLabel(x.component_id)}
|
||||||
</span>
|
</span>
|
||||||
</Flex>
|
</Flex>
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
</section>
|
</section>
|
||||||
</NodePopover>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import { NodeData } from '../../interface';
|
|||||||
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import NodeHeader from './node-header';
|
import NodeHeader from './node-header';
|
||||||
import NodePopover from './popover';
|
|
||||||
|
|
||||||
export function RagNode({
|
export function RagNode({
|
||||||
id,
|
id,
|
||||||
@ -13,30 +12,28 @@ export function RagNode({
|
|||||||
selected,
|
selected,
|
||||||
}: NodeProps<NodeData>) {
|
}: NodeProps<NodeData>) {
|
||||||
return (
|
return (
|
||||||
<NodePopover nodeId={id}>
|
<section
|
||||||
<section
|
className={classNames(styles.ragNode, {
|
||||||
className={classNames(styles.ragNode, {
|
[styles.selectedNode]: selected,
|
||||||
[styles.selectedNode]: selected,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<Handle
|
||||||
<Handle
|
id="c"
|
||||||
id="c"
|
type="source"
|
||||||
type="source"
|
position={Position.Left}
|
||||||
position={Position.Left}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
style={LeftHandleStyle}
|
||||||
style={LeftHandleStyle}
|
></Handle>
|
||||||
></Handle>
|
<Handle
|
||||||
<Handle
|
type="source"
|
||||||
type="source"
|
position={Position.Right}
|
||||||
position={Position.Right}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
id="b"
|
||||||
id="b"
|
style={RightHandleStyle}
|
||||||
style={RightHandleStyle}
|
></Handle>
|
||||||
></Handle>
|
<NodeHeader id={id} name={data.name} label={data.label}></NodeHeader>
|
||||||
<NodeHeader id={id} name={data.name} label={data.label}></NodeHeader>
|
</section>
|
||||||
</section>
|
|
||||||
</NodePopover>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import { NodeData } from '../../interface';
|
|||||||
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import NodeHeader from './node-header';
|
import NodeHeader from './node-header';
|
||||||
import NodePopover from './popover';
|
|
||||||
|
|
||||||
export function InvokeNode({
|
export function InvokeNode({
|
||||||
id,
|
id,
|
||||||
@ -18,39 +17,37 @@ export function InvokeNode({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const url = get(data, 'form.url');
|
const url = get(data, 'form.url');
|
||||||
return (
|
return (
|
||||||
<NodePopover nodeId={id}>
|
<section
|
||||||
<section
|
className={classNames(styles.ragNode, {
|
||||||
className={classNames(styles.ragNode, {
|
[styles.selectedNode]: selected,
|
||||||
[styles.selectedNode]: selected,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<Handle
|
||||||
<Handle
|
id="c"
|
||||||
id="c"
|
type="source"
|
||||||
type="source"
|
position={Position.Left}
|
||||||
position={Position.Left}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
style={LeftHandleStyle}
|
||||||
style={LeftHandleStyle}
|
></Handle>
|
||||||
></Handle>
|
<Handle
|
||||||
<Handle
|
type="source"
|
||||||
type="source"
|
position={Position.Right}
|
||||||
position={Position.Right}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
id="b"
|
||||||
id="b"
|
style={RightHandleStyle}
|
||||||
style={RightHandleStyle}
|
></Handle>
|
||||||
></Handle>
|
<NodeHeader
|
||||||
<NodeHeader
|
id={id}
|
||||||
id={id}
|
name={data.name}
|
||||||
name={data.name}
|
label={data.label}
|
||||||
label={data.label}
|
className={styles.nodeHeader}
|
||||||
className={styles.nodeHeader}
|
></NodeHeader>
|
||||||
></NodeHeader>
|
<Flex vertical>
|
||||||
<Flex vertical>
|
<div>{t('flow.url')}</div>
|
||||||
<div>{t('flow.url')}</div>
|
<div className={styles.nodeText}>{url}</div>
|
||||||
<div className={styles.nodeText}>{url}</div>
|
</Flex>
|
||||||
</Flex>
|
</section>
|
||||||
</section>
|
|
||||||
</NodePopover>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import { NodeData } from '../../interface';
|
|||||||
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import NodeHeader from './node-header';
|
import NodeHeader from './node-header';
|
||||||
import NodePopover from './popover';
|
|
||||||
|
|
||||||
export function KeywordNode({
|
export function KeywordNode({
|
||||||
id,
|
id,
|
||||||
@ -15,40 +14,38 @@ export function KeywordNode({
|
|||||||
selected,
|
selected,
|
||||||
}: NodeProps<NodeData>) {
|
}: NodeProps<NodeData>) {
|
||||||
return (
|
return (
|
||||||
<NodePopover nodeId={id}>
|
<section
|
||||||
<section
|
className={classNames(styles.logicNode, {
|
||||||
className={classNames(styles.logicNode, {
|
[styles.selectedNode]: selected,
|
||||||
[styles.selectedNode]: selected,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<Handle
|
||||||
<Handle
|
id="c"
|
||||||
id="c"
|
type="source"
|
||||||
type="source"
|
position={Position.Left}
|
||||||
position={Position.Left}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
style={LeftHandleStyle}
|
||||||
style={LeftHandleStyle}
|
></Handle>
|
||||||
></Handle>
|
<Handle
|
||||||
<Handle
|
type="source"
|
||||||
type="source"
|
position={Position.Right}
|
||||||
position={Position.Right}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
style={RightHandleStyle}
|
||||||
style={RightHandleStyle}
|
id="b"
|
||||||
id="b"
|
></Handle>
|
||||||
></Handle>
|
|
||||||
|
|
||||||
<NodeHeader
|
<NodeHeader
|
||||||
id={id}
|
id={id}
|
||||||
name={data.name}
|
name={data.name}
|
||||||
label={data.label}
|
label={data.label}
|
||||||
className={styles.nodeHeader}
|
className={styles.nodeHeader}
|
||||||
></NodeHeader>
|
></NodeHeader>
|
||||||
|
|
||||||
<div className={styles.nodeText}>
|
<div className={styles.nodeText}>
|
||||||
<LLMLabel value={get(data, 'form.llm_id')}></LLMLabel>
|
<LLMLabel value={get(data, 'form.llm_id')}></LLMLabel>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</NodePopover>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import { NodeData } from '../../interface';
|
|||||||
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import NodeHeader from './node-header';
|
import NodeHeader from './node-header';
|
||||||
import NodePopover from './popover';
|
|
||||||
|
|
||||||
export function LogicNode({
|
export function LogicNode({
|
||||||
id,
|
id,
|
||||||
@ -13,30 +12,28 @@ export function LogicNode({
|
|||||||
selected,
|
selected,
|
||||||
}: NodeProps<NodeData>) {
|
}: NodeProps<NodeData>) {
|
||||||
return (
|
return (
|
||||||
<NodePopover nodeId={id}>
|
<section
|
||||||
<section
|
className={classNames(styles.logicNode, {
|
||||||
className={classNames(styles.logicNode, {
|
[styles.selectedNode]: selected,
|
||||||
[styles.selectedNode]: selected,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<Handle
|
||||||
<Handle
|
id="c"
|
||||||
id="c"
|
type="source"
|
||||||
type="source"
|
position={Position.Left}
|
||||||
position={Position.Left}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
style={LeftHandleStyle}
|
||||||
style={LeftHandleStyle}
|
></Handle>
|
||||||
></Handle>
|
<Handle
|
||||||
<Handle
|
type="source"
|
||||||
type="source"
|
position={Position.Right}
|
||||||
position={Position.Right}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
style={RightHandleStyle}
|
||||||
style={RightHandleStyle}
|
id="b"
|
||||||
id="b"
|
></Handle>
|
||||||
></Handle>
|
<NodeHeader id={id} name={data.name} label={data.label}></NodeHeader>
|
||||||
<NodeHeader id={id} name={data.name} label={data.label}></NodeHeader>
|
</section>
|
||||||
</section>
|
|
||||||
</NodePopover>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import { NodeData } from '../../interface';
|
|||||||
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import NodeHeader from './node-header';
|
import NodeHeader from './node-header';
|
||||||
import NodePopover from './popover';
|
|
||||||
|
|
||||||
export function MessageNode({
|
export function MessageNode({
|
||||||
id,
|
id,
|
||||||
@ -17,47 +16,45 @@ export function MessageNode({
|
|||||||
const messages: string[] = get(data, 'form.messages', []);
|
const messages: string[] = get(data, 'form.messages', []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodePopover nodeId={id}>
|
<section
|
||||||
<section
|
className={classNames(styles.logicNode, {
|
||||||
className={classNames(styles.logicNode, {
|
[styles.selectedNode]: selected,
|
||||||
[styles.selectedNode]: selected,
|
})}
|
||||||
|
>
|
||||||
|
<Handle
|
||||||
|
id="c"
|
||||||
|
type="source"
|
||||||
|
position={Position.Left}
|
||||||
|
isConnectable={isConnectable}
|
||||||
|
className={styles.handle}
|
||||||
|
style={LeftHandleStyle}
|
||||||
|
></Handle>
|
||||||
|
<Handle
|
||||||
|
type="source"
|
||||||
|
position={Position.Right}
|
||||||
|
isConnectable={isConnectable}
|
||||||
|
className={styles.handle}
|
||||||
|
style={RightHandleStyle}
|
||||||
|
id="b"
|
||||||
|
></Handle>
|
||||||
|
<NodeHeader
|
||||||
|
id={id}
|
||||||
|
name={data.name}
|
||||||
|
label={data.label}
|
||||||
|
className={classNames({
|
||||||
|
[styles.nodeHeader]: messages.length > 0,
|
||||||
})}
|
})}
|
||||||
>
|
></NodeHeader>
|
||||||
<Handle
|
|
||||||
id="c"
|
|
||||||
type="source"
|
|
||||||
position={Position.Left}
|
|
||||||
isConnectable={isConnectable}
|
|
||||||
className={styles.handle}
|
|
||||||
style={LeftHandleStyle}
|
|
||||||
></Handle>
|
|
||||||
<Handle
|
|
||||||
type="source"
|
|
||||||
position={Position.Right}
|
|
||||||
isConnectable={isConnectable}
|
|
||||||
className={styles.handle}
|
|
||||||
style={RightHandleStyle}
|
|
||||||
id="b"
|
|
||||||
></Handle>
|
|
||||||
<NodeHeader
|
|
||||||
id={id}
|
|
||||||
name={data.name}
|
|
||||||
label={data.label}
|
|
||||||
className={classNames({
|
|
||||||
[styles.nodeHeader]: messages.length > 0,
|
|
||||||
})}
|
|
||||||
></NodeHeader>
|
|
||||||
|
|
||||||
<Flex vertical gap={8} className={styles.messageNodeContainer}>
|
<Flex vertical gap={8} className={styles.messageNodeContainer}>
|
||||||
{messages.map((message, idx) => {
|
{messages.map((message, idx) => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.nodeText} key={idx}>
|
<div className={styles.nodeText} key={idx}>
|
||||||
{message}
|
{message}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Flex>
|
</Flex>
|
||||||
</section>
|
</section>
|
||||||
</NodePopover>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,52 @@
|
|||||||
import { Flex } from 'antd';
|
import { Flex } from 'antd';
|
||||||
|
|
||||||
import { Operator, operatorMap } from '../../constant';
|
import { Operator, operatorMap } from '../../constant';
|
||||||
import OperatorIcon from '../../operator-icon';
|
import OperatorIcon from '../../operator-icon';
|
||||||
import NodeDropdown from './dropdown';
|
import NodeDropdown from './dropdown';
|
||||||
|
|
||||||
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
import { NextNodePopover } from './popover';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label?: string;
|
||||||
name: string;
|
name?: string;
|
||||||
gap?: number;
|
gap?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function RunStatus({ id, name }: IProps) {
|
||||||
|
const { t } = useTranslate('flow');
|
||||||
|
return (
|
||||||
|
<section className="flex justify-end items-center pb-1 ">
|
||||||
|
<NextNodePopover nodeId={id} name={name}>
|
||||||
|
<span className="text-blue-600 cursor-pointer text-[10px]">
|
||||||
|
{t('operationResults')}
|
||||||
|
</span>
|
||||||
|
</NextNodePopover>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const NodeHeader = ({ label, id, name, gap = 4, className }: IProps) => {
|
const NodeHeader = ({ label, id, name, gap = 4, className }: IProps) => {
|
||||||
return (
|
return (
|
||||||
<Flex
|
<section className="haha">
|
||||||
flex={1}
|
{label !== Operator.Answer && <RunStatus id={id} name={name}></RunStatus>}
|
||||||
align="center"
|
<Flex
|
||||||
justify={'space-between'}
|
flex={1}
|
||||||
gap={gap}
|
align="center"
|
||||||
className={className}
|
justify={'space-between'}
|
||||||
>
|
gap={gap}
|
||||||
<OperatorIcon
|
className={className}
|
||||||
name={label as Operator}
|
>
|
||||||
color={operatorMap[label as Operator].color}
|
<OperatorIcon
|
||||||
></OperatorIcon>
|
name={label as Operator}
|
||||||
<span className={styles.nodeTitle}>{name}</span>
|
color={operatorMap[label as Operator].color}
|
||||||
<NodeDropdown id={id}></NodeDropdown>
|
></OperatorIcon>
|
||||||
</Flex>
|
<span className={styles.nodeTitle}>{name}</span>
|
||||||
|
<NodeDropdown id={id}></NodeDropdown>
|
||||||
|
</Flex>
|
||||||
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,49 +1,98 @@
|
|||||||
import { useFetchFlow } from '@/hooks/flow-hooks';
|
import { useFetchFlow } from '@/hooks/flow-hooks';
|
||||||
import { Popover } from 'antd';
|
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import React, { useMemo } from 'react';
|
import React, { MouseEventHandler, useCallback, useMemo } from 'react';
|
||||||
import JsonView from 'react18-json-view';
|
import JsonView from 'react18-json-view';
|
||||||
import 'react18-json-view/src/style.css';
|
import 'react18-json-view/src/style.css';
|
||||||
import { Operator } from '../../constant';
|
|
||||||
import { useReplaceIdWithText } from '../../hooks';
|
import { useReplaceIdWithText } from '../../hooks';
|
||||||
|
|
||||||
import styles from './index.less';
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from '@/components/ui/popover';
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from '@/components/ui/table';
|
||||||
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
|
|
||||||
interface IProps extends React.PropsWithChildren {
|
interface IProps extends React.PropsWithChildren {
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
|
name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NodePopover = ({ children, nodeId }: IProps) => {
|
export function NextNodePopover({ children, nodeId, name }: IProps) {
|
||||||
|
const { t } = useTranslate('flow');
|
||||||
|
|
||||||
const { data } = useFetchFlow();
|
const { data } = useFetchFlow();
|
||||||
const component = useMemo(() => {
|
const component = useMemo(() => {
|
||||||
return get(data, ['dsl', 'components', nodeId], {});
|
return get(data, ['dsl', 'components', nodeId], {});
|
||||||
}, [nodeId, data]);
|
}, [nodeId, data]);
|
||||||
|
|
||||||
|
const inputs: Array<{ component_id: string; content: string }> = get(
|
||||||
|
component,
|
||||||
|
['obj', 'params', 'inputs'],
|
||||||
|
[],
|
||||||
|
);
|
||||||
const output = get(component, ['obj', 'params', 'output'], {});
|
const output = get(component, ['obj', 'params', 'output'], {});
|
||||||
const componentName = get(component, ['obj', 'component_name'], '');
|
const { replacedOutput, getNameById } = useReplaceIdWithText(output);
|
||||||
const replacedOutput = useReplaceIdWithText(output);
|
const stopPropagation: MouseEventHandler = useCallback((e) => {
|
||||||
|
e.stopPropagation();
|
||||||
const content =
|
}, []);
|
||||||
componentName !== Operator.Answer ? (
|
|
||||||
<div
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<JsonView
|
|
||||||
src={replacedOutput}
|
|
||||||
displaySize={30}
|
|
||||||
className={styles.jsonView}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : undefined;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover content={content} placement="right" destroyTooltipOnHide>
|
<Popover>
|
||||||
{children}
|
<PopoverTrigger onClick={stopPropagation} asChild>
|
||||||
|
{children}
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent
|
||||||
|
align={'start'}
|
||||||
|
side={'right'}
|
||||||
|
sideOffset={20}
|
||||||
|
onClick={stopPropagation}
|
||||||
|
className="w-[400px]"
|
||||||
|
>
|
||||||
|
<div className="mb-3 font-semibold text-[16px]">
|
||||||
|
{name} {t('operationResults')}
|
||||||
|
</div>
|
||||||
|
<div className="flex w-full gap-4 flex-col">
|
||||||
|
<div className="flex flex-col space-y-1.5">
|
||||||
|
<span className="font-semibold text-[14px]">{t('input')}</span>
|
||||||
|
<div className="bg-gray-100 p-1 rounded">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>{t('componentId')}</TableHead>
|
||||||
|
<TableHead className="w-[60px]">{t('content')}</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{inputs.map((x, idx) => (
|
||||||
|
<TableRow key={idx}>
|
||||||
|
<TableCell>{getNameById(x.component_id)}</TableCell>
|
||||||
|
<TableCell className="truncate">{x.content}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col space-y-1.5">
|
||||||
|
<span className="font-semibold text-[14px]">{t('output')}</span>
|
||||||
|
<div className="bg-gray-100 p-1 rounded">
|
||||||
|
<JsonView
|
||||||
|
src={replacedOutput}
|
||||||
|
displaySize={30}
|
||||||
|
className="w-full max-h-[300px] break-words overflow-auto"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default NodePopover;
|
|
||||||
|
@ -3,7 +3,6 @@ import classNames from 'classnames';
|
|||||||
import { Handle, NodeProps, Position } from 'reactflow';
|
import { Handle, NodeProps, Position } from 'reactflow';
|
||||||
import { NodeData } from '../../interface';
|
import { NodeData } from '../../interface';
|
||||||
import { RightHandleStyle } from './handle-icon';
|
import { RightHandleStyle } from './handle-icon';
|
||||||
import NodePopover from './popover';
|
|
||||||
|
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
@ -13,53 +12,51 @@ export function RelevantNode({ id, data, selected }: NodeProps<NodeData>) {
|
|||||||
const yes = get(data, 'form.yes');
|
const yes = get(data, 'form.yes');
|
||||||
const no = get(data, 'form.no');
|
const no = get(data, 'form.no');
|
||||||
return (
|
return (
|
||||||
<NodePopover nodeId={id}>
|
<section
|
||||||
<section
|
className={classNames(styles.logicNode, {
|
||||||
className={classNames(styles.logicNode, {
|
[styles.selectedNode]: selected,
|
||||||
[styles.selectedNode]: selected,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<Handle
|
||||||
<Handle
|
type="target"
|
||||||
type="target"
|
position={Position.Left}
|
||||||
position={Position.Left}
|
isConnectable
|
||||||
isConnectable
|
className={styles.handle}
|
||||||
className={styles.handle}
|
id={'a'}
|
||||||
id={'a'}
|
></Handle>
|
||||||
></Handle>
|
<Handle
|
||||||
<Handle
|
type="source"
|
||||||
type="source"
|
position={Position.Right}
|
||||||
position={Position.Right}
|
isConnectable
|
||||||
isConnectable
|
className={styles.handle}
|
||||||
className={styles.handle}
|
id={'yes'}
|
||||||
id={'yes'}
|
style={{ ...RightHandleStyle, top: 59 }}
|
||||||
style={{ ...RightHandleStyle, top: 59 }}
|
></Handle>
|
||||||
></Handle>
|
<Handle
|
||||||
<Handle
|
type="source"
|
||||||
type="source"
|
position={Position.Right}
|
||||||
position={Position.Right}
|
isConnectable
|
||||||
isConnectable
|
className={styles.handle}
|
||||||
className={styles.handle}
|
id={'no'}
|
||||||
id={'no'}
|
style={{ ...RightHandleStyle, top: 112 }}
|
||||||
style={{ ...RightHandleStyle, top: 112 }}
|
></Handle>
|
||||||
></Handle>
|
<NodeHeader
|
||||||
<NodeHeader
|
id={id}
|
||||||
id={id}
|
name={data.name}
|
||||||
name={data.name}
|
label={data.label}
|
||||||
label={data.label}
|
className={styles.nodeHeader}
|
||||||
className={styles.nodeHeader}
|
></NodeHeader>
|
||||||
></NodeHeader>
|
|
||||||
|
|
||||||
<Flex vertical gap={10}>
|
<Flex vertical gap={10}>
|
||||||
<Flex vertical>
|
<Flex vertical>
|
||||||
<div className={styles.relevantLabel}>Yes</div>
|
<div className={styles.relevantLabel}>Yes</div>
|
||||||
<div className={styles.nodeText}>{yes}</div>
|
<div className={styles.nodeText}>{yes}</div>
|
||||||
</Flex>
|
|
||||||
<Flex vertical>
|
|
||||||
<div className={styles.relevantLabel}>No</div>
|
|
||||||
<div className={styles.nodeText}>{no}</div>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</section>
|
<Flex vertical>
|
||||||
</NodePopover>
|
<div className={styles.relevantLabel}>No</div>
|
||||||
|
<div className={styles.nodeText}>{no}</div>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import { NodeData } from '../../interface';
|
|||||||
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import NodeHeader from './node-header';
|
import NodeHeader from './node-header';
|
||||||
import NodePopover from './popover';
|
|
||||||
|
|
||||||
export function RetrievalNode({
|
export function RetrievalNode({
|
||||||
id,
|
id,
|
||||||
@ -31,55 +30,53 @@ export function RetrievalNode({
|
|||||||
}, [knowledgeList, knowledgeBaseIds]);
|
}, [knowledgeList, knowledgeBaseIds]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodePopover nodeId={id}>
|
<section
|
||||||
<section
|
className={classNames(styles.logicNode, {
|
||||||
className={classNames(styles.logicNode, {
|
[styles.selectedNode]: selected,
|
||||||
[styles.selectedNode]: selected,
|
})}
|
||||||
|
>
|
||||||
|
<Handle
|
||||||
|
id="c"
|
||||||
|
type="source"
|
||||||
|
position={Position.Left}
|
||||||
|
isConnectable={isConnectable}
|
||||||
|
className={styles.handle}
|
||||||
|
style={LeftHandleStyle}
|
||||||
|
></Handle>
|
||||||
|
<Handle
|
||||||
|
type="source"
|
||||||
|
position={Position.Right}
|
||||||
|
isConnectable={isConnectable}
|
||||||
|
className={styles.handle}
|
||||||
|
style={RightHandleStyle}
|
||||||
|
id="b"
|
||||||
|
></Handle>
|
||||||
|
<NodeHeader
|
||||||
|
id={id}
|
||||||
|
name={data.name}
|
||||||
|
label={data.label}
|
||||||
|
className={classNames({
|
||||||
|
[styles.nodeHeader]: knowledgeBaseIds.length > 0,
|
||||||
})}
|
})}
|
||||||
>
|
></NodeHeader>
|
||||||
<Handle
|
<Flex vertical gap={8}>
|
||||||
id="c"
|
{knowledgeBases.map((knowledge) => {
|
||||||
type="source"
|
return (
|
||||||
position={Position.Left}
|
<div className={styles.nodeText} key={knowledge.id}>
|
||||||
isConnectable={isConnectable}
|
<Flex align={'center'} gap={6}>
|
||||||
className={styles.handle}
|
<Avatar
|
||||||
style={LeftHandleStyle}
|
size={26}
|
||||||
></Handle>
|
icon={<UserOutlined />}
|
||||||
<Handle
|
src={knowledge.avatar}
|
||||||
type="source"
|
/>
|
||||||
position={Position.Right}
|
<Flex className={styles.knowledgeNodeName} flex={1}>
|
||||||
isConnectable={isConnectable}
|
{knowledge.name}
|
||||||
className={styles.handle}
|
|
||||||
style={RightHandleStyle}
|
|
||||||
id="b"
|
|
||||||
></Handle>
|
|
||||||
<NodeHeader
|
|
||||||
id={id}
|
|
||||||
name={data.name}
|
|
||||||
label={data.label}
|
|
||||||
className={classNames({
|
|
||||||
[styles.nodeHeader]: knowledgeBaseIds.length > 0,
|
|
||||||
})}
|
|
||||||
></NodeHeader>
|
|
||||||
<Flex vertical gap={8}>
|
|
||||||
{knowledgeBases.map((knowledge) => {
|
|
||||||
return (
|
|
||||||
<div className={styles.nodeText} key={knowledge.id}>
|
|
||||||
<Flex align={'center'} gap={6}>
|
|
||||||
<Avatar
|
|
||||||
size={26}
|
|
||||||
icon={<UserOutlined />}
|
|
||||||
src={knowledge.avatar}
|
|
||||||
/>
|
|
||||||
<Flex className={styles.knowledgeNodeName} flex={1}>
|
|
||||||
{knowledge.name}
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</div>
|
</Flex>
|
||||||
);
|
</div>
|
||||||
})}
|
);
|
||||||
</Flex>
|
})}
|
||||||
</section>
|
</Flex>
|
||||||
</NodePopover>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import { NodeData } from '../../interface';
|
|||||||
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import NodeHeader from './node-header';
|
import NodeHeader from './node-header';
|
||||||
import NodePopover from './popover';
|
|
||||||
|
|
||||||
export function RewriteNode({
|
export function RewriteNode({
|
||||||
id,
|
id,
|
||||||
@ -15,40 +14,38 @@ export function RewriteNode({
|
|||||||
selected,
|
selected,
|
||||||
}: NodeProps<NodeData>) {
|
}: NodeProps<NodeData>) {
|
||||||
return (
|
return (
|
||||||
<NodePopover nodeId={id}>
|
<section
|
||||||
<section
|
className={classNames(styles.logicNode, {
|
||||||
className={classNames(styles.logicNode, {
|
[styles.selectedNode]: selected,
|
||||||
[styles.selectedNode]: selected,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<Handle
|
||||||
<Handle
|
id="c"
|
||||||
id="c"
|
type="source"
|
||||||
type="source"
|
position={Position.Left}
|
||||||
position={Position.Left}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
style={LeftHandleStyle}
|
||||||
style={LeftHandleStyle}
|
></Handle>
|
||||||
></Handle>
|
<Handle
|
||||||
<Handle
|
type="source"
|
||||||
type="source"
|
position={Position.Right}
|
||||||
position={Position.Right}
|
isConnectable={isConnectable}
|
||||||
isConnectable={isConnectable}
|
className={styles.handle}
|
||||||
className={styles.handle}
|
style={RightHandleStyle}
|
||||||
style={RightHandleStyle}
|
id="b"
|
||||||
id="b"
|
></Handle>
|
||||||
></Handle>
|
|
||||||
|
|
||||||
<NodeHeader
|
<NodeHeader
|
||||||
id={id}
|
id={id}
|
||||||
name={data.name}
|
name={data.name}
|
||||||
label={data.label}
|
label={data.label}
|
||||||
className={styles.nodeHeader}
|
className={styles.nodeHeader}
|
||||||
></NodeHeader>
|
></NodeHeader>
|
||||||
|
|
||||||
<div className={styles.nodeText}>
|
<div className={styles.nodeText}>
|
||||||
<LLMLabel value={get(data, 'form.llm_id')}></LLMLabel>
|
<LLMLabel value={get(data, 'form.llm_id')}></LLMLabel>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</NodePopover>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import { RightHandleStyle } from './handle-icon';
|
|||||||
import { useBuildSwitchHandlePositions } from './hooks';
|
import { useBuildSwitchHandlePositions } from './hooks';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import NodeHeader from './node-header';
|
import NodeHeader from './node-header';
|
||||||
import NodePopover from './popover';
|
|
||||||
|
|
||||||
const getConditionKey = (idx: number, length: number) => {
|
const getConditionKey = (idx: number, length: number) => {
|
||||||
if (idx === 0 && length !== 1) {
|
if (idx === 0 && length !== 1) {
|
||||||
@ -58,55 +57,53 @@ export function SwitchNode({ id, data, selected }: NodeProps<NodeData>) {
|
|||||||
const { positions } = useBuildSwitchHandlePositions({ data, id });
|
const { positions } = useBuildSwitchHandlePositions({ data, id });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodePopover nodeId={id}>
|
<section
|
||||||
<section
|
className={classNames(styles.logicNode, {
|
||||||
className={classNames(styles.logicNode, {
|
[styles.selectedNode]: selected,
|
||||||
[styles.selectedNode]: selected,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<Handle
|
||||||
<Handle
|
type="target"
|
||||||
type="target"
|
position={Position.Left}
|
||||||
position={Position.Left}
|
isConnectable
|
||||||
isConnectable
|
className={styles.handle}
|
||||||
className={styles.handle}
|
id={'a'}
|
||||||
id={'a'}
|
></Handle>
|
||||||
></Handle>
|
<NodeHeader
|
||||||
<NodeHeader
|
id={id}
|
||||||
id={id}
|
name={data.name}
|
||||||
name={data.name}
|
label={data.label}
|
||||||
label={data.label}
|
className={styles.nodeHeader}
|
||||||
className={styles.nodeHeader}
|
></NodeHeader>
|
||||||
></NodeHeader>
|
<Flex vertical gap={10}>
|
||||||
<Flex vertical gap={10}>
|
{positions.map((position, idx) => {
|
||||||
{positions.map((position, idx) => {
|
return (
|
||||||
return (
|
<div key={idx}>
|
||||||
<div key={idx}>
|
<Flex vertical>
|
||||||
<Flex vertical>
|
<Flex justify={'space-between'}>
|
||||||
<Flex justify={'space-between'}>
|
<span>{idx < positions.length - 1 && position.text}</span>
|
||||||
<span>{idx < positions.length - 1 && position.text}</span>
|
<span>{getConditionKey(idx, positions.length)}</span>
|
||||||
<span>{getConditionKey(idx, positions.length)}</span>
|
|
||||||
</Flex>
|
|
||||||
{position.condition && (
|
|
||||||
<ConditionBlock
|
|
||||||
nodeId={id}
|
|
||||||
condition={position.condition}
|
|
||||||
></ConditionBlock>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<Handle
|
{position.condition && (
|
||||||
key={position.text}
|
<ConditionBlock
|
||||||
id={position.text}
|
nodeId={id}
|
||||||
type="source"
|
condition={position.condition}
|
||||||
position={Position.Right}
|
></ConditionBlock>
|
||||||
isConnectable
|
)}
|
||||||
className={styles.handle}
|
</Flex>
|
||||||
style={{ ...RightHandleStyle, top: position.top }}
|
<Handle
|
||||||
></Handle>
|
key={position.text}
|
||||||
</div>
|
id={position.text}
|
||||||
);
|
type="source"
|
||||||
})}
|
position={Position.Right}
|
||||||
</Flex>
|
isConnectable
|
||||||
</section>
|
className={styles.handle}
|
||||||
</NodePopover>
|
style={{ ...RightHandleStyle, top: position.top }}
|
||||||
|
></Handle>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Flex>
|
||||||
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -524,7 +524,10 @@ export const useReplaceIdWithText = (output: unknown) => {
|
|||||||
return getNode(id)?.data.name;
|
return getNode(id)?.data.name;
|
||||||
};
|
};
|
||||||
|
|
||||||
return replaceIdWithText(output, getNameById);
|
return {
|
||||||
|
replacedOutput: replaceIdWithText(output, getNameById),
|
||||||
|
getNameById,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user