mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Adjust the style of the agent canvas connection line #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -1,31 +0,0 @@
|
|||||||
.edgeButton {
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
background: #eee;
|
|
||||||
border: 1px solid #fff;
|
|
||||||
padding: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 50%;
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edgeButton:hover {
|
|
||||||
box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
.edgeButtonDark {
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
background: #0e0c0c;
|
|
||||||
border: 1px solid #fff;
|
|
||||||
padding: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 50%;
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edgeButtonDark:hover {
|
|
||||||
box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.08);
|
|
||||||
}
|
|
||||||
@ -7,12 +7,10 @@ import {
|
|||||||
} from '@xyflow/react';
|
} from '@xyflow/react';
|
||||||
import useGraphStore from '../../store';
|
import useGraphStore from '../../store';
|
||||||
|
|
||||||
import { useTheme } from '@/components/theme-provider';
|
|
||||||
import { useFetchAgent } from '@/hooks/use-agent-request';
|
import { useFetchAgent } from '@/hooks/use-agent-request';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { NodeHandleId, Operator } from '../../constant';
|
import { NodeHandleId, Operator } from '../../constant';
|
||||||
import styles from './index.less';
|
|
||||||
|
|
||||||
export function ButtonEdge({
|
export function ButtonEdge({
|
||||||
id,
|
id,
|
||||||
@ -39,9 +37,8 @@ export function ButtonEdge({
|
|||||||
targetY,
|
targetY,
|
||||||
targetPosition,
|
targetPosition,
|
||||||
});
|
});
|
||||||
const { theme } = useTheme();
|
|
||||||
const selectedStyle = useMemo(() => {
|
const selectedStyle = useMemo(() => {
|
||||||
return selected ? { strokeWidth: 2, stroke: '#1677ff' } : {};
|
return selected ? { strokeWidth: 1, stroke: 'rgba(76, 164, 231, 1)' } : {};
|
||||||
}, [selected]);
|
}, [selected]);
|
||||||
|
|
||||||
const onEdgeClick = () => {
|
const onEdgeClick = () => {
|
||||||
@ -71,7 +68,7 @@ export function ButtonEdge({
|
|||||||
// The set of elements following source
|
// The set of elements following source
|
||||||
const slicedGraphPath = graphPath.slice(idx + 1);
|
const slicedGraphPath = graphPath.slice(idx + 1);
|
||||||
if (slicedGraphPath.some((x) => x === target)) {
|
if (slicedGraphPath.some((x) => x === target)) {
|
||||||
return { strokeWidth: 2, stroke: 'red' };
|
return { strokeWidth: 1, stroke: 'red' };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
@ -91,6 +88,7 @@ export function ButtonEdge({
|
|||||||
path={edgePath}
|
path={edgePath}
|
||||||
markerEnd={markerEnd}
|
markerEnd={markerEnd}
|
||||||
style={{ ...style, ...selectedStyle, ...highlightStyle }}
|
style={{ ...style, ...selectedStyle, ...highlightStyle }}
|
||||||
|
className="text-text-sub-title"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<EdgeLabelRenderer>
|
<EdgeLabelRenderer>
|
||||||
@ -108,7 +106,7 @@ export function ButtonEdge({
|
|||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
className={cn(
|
className={cn(
|
||||||
theme === 'dark' ? styles.edgeButtonDark : styles.edgeButton,
|
'size-3.5 border border-text-delete-red text-text-delete-red rounded-full leading-none',
|
||||||
'invisible',
|
'invisible',
|
||||||
{ visible },
|
{ visible },
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -202,8 +202,8 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
|
|||||||
type: 'buttonEdge',
|
type: 'buttonEdge',
|
||||||
markerEnd: 'logo',
|
markerEnd: 'logo',
|
||||||
style: {
|
style: {
|
||||||
strokeWidth: 2,
|
strokeWidth: 1,
|
||||||
stroke: 'rgb(202 197 245)',
|
stroke: 'rgba(91, 93, 106, 1)',
|
||||||
},
|
},
|
||||||
zIndex: 1001, // https://github.com/xyflow/xyflow/discussions/3498
|
zIndex: 1001, // https://github.com/xyflow/xyflow/discussions/3498
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ function InnerAgentNode({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ToolBar selected={selected} id={id} label={data.label}>
|
<ToolBar selected={selected} id={id} label={data.label}>
|
||||||
<NodeWrapper>
|
<NodeWrapper selected={selected}>
|
||||||
{isHeadAgent && (
|
{isHeadAgent && (
|
||||||
<>
|
<>
|
||||||
<CommonHandle
|
<CommonHandle
|
||||||
|
|||||||
@ -18,12 +18,12 @@ import styles from './index.less';
|
|||||||
import { NodeWrapper } from './node-wrapper';
|
import { NodeWrapper } from './node-wrapper';
|
||||||
|
|
||||||
// TODO: do not allow other nodes to connect to this node
|
// TODO: do not allow other nodes to connect to this node
|
||||||
function InnerBeginNode({ data, id }: NodeProps<IBeginNode>) {
|
function InnerBeginNode({ data, id, selected }: NodeProps<IBeginNode>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const inputs: Record<string, BeginQuery> = get(data, 'form.inputs', {});
|
const inputs: Record<string, BeginQuery> = get(data, 'form.inputs', {});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeWrapper>
|
<NodeWrapper selected={selected}>
|
||||||
<CommonHandle
|
<CommonHandle
|
||||||
type="source"
|
type="source"
|
||||||
position={Position.Right}
|
position={Position.Right}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ export function InnerCategorizeNode({
|
|||||||
const { positions } = useBuildCategorizeHandlePositions({ data, id });
|
const { positions } = useBuildCategorizeHandlePositions({ data, id });
|
||||||
return (
|
return (
|
||||||
<ToolBar selected={selected} id={id} label={data.label}>
|
<ToolBar selected={selected} id={id} label={data.label}>
|
||||||
<NodeWrapper>
|
<NodeWrapper selected={selected}>
|
||||||
<CommonHandle
|
<CommonHandle
|
||||||
type="target"
|
type="target"
|
||||||
position={Position.Left}
|
position={Position.Left}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ function InnerRagNode({
|
|||||||
}: NodeProps<IRagNode>) {
|
}: NodeProps<IRagNode>) {
|
||||||
return (
|
return (
|
||||||
<ToolBar selected={selected} id={id} label={data.label}>
|
<ToolBar selected={selected} id={id} label={data.label}>
|
||||||
<NodeWrapper>
|
<NodeWrapper selected={selected}>
|
||||||
<CommonHandle
|
<CommonHandle
|
||||||
id={NodeHandleId.End}
|
id={NodeHandleId.End}
|
||||||
type="target"
|
type="target"
|
||||||
|
|||||||
@ -67,9 +67,10 @@ export function InnerIterationNode({
|
|||||||
function InnerIterationStartNode({
|
function InnerIterationStartNode({
|
||||||
isConnectable = true,
|
isConnectable = true,
|
||||||
id,
|
id,
|
||||||
|
selected,
|
||||||
}: NodeProps<IIterationStartNode>) {
|
}: NodeProps<IIterationStartNode>) {
|
||||||
return (
|
return (
|
||||||
<NodeWrapper className="w-20">
|
<NodeWrapper className="w-20" selected={selected}>
|
||||||
<CommonHandle
|
<CommonHandle
|
||||||
type="source"
|
type="source"
|
||||||
position={Position.Right}
|
position={Position.Right}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ export function InnerLogicNode({
|
|||||||
}: NodeProps<ILogicNode>) {
|
}: NodeProps<ILogicNode>) {
|
||||||
return (
|
return (
|
||||||
<ToolBar selected={selected} id={id} label={data.label}>
|
<ToolBar selected={selected} id={id} label={data.label}>
|
||||||
<NodeWrapper>
|
<NodeWrapper selected={selected}>
|
||||||
<CommonHandle
|
<CommonHandle
|
||||||
id="c"
|
id="c"
|
||||||
type="source"
|
type="source"
|
||||||
|
|||||||
@ -21,7 +21,7 @@ function InnerMessageNode({
|
|||||||
const messages: string[] = get(data, 'form.messages', []);
|
const messages: string[] = get(data, 'form.messages', []);
|
||||||
return (
|
return (
|
||||||
<ToolBar selected={selected} id={id} label={data.label}>
|
<ToolBar selected={selected} id={id} label={data.label}>
|
||||||
<NodeWrapper>
|
<NodeWrapper selected={selected}>
|
||||||
<CommonHandle
|
<CommonHandle
|
||||||
type="target"
|
type="target"
|
||||||
position={Position.Left}
|
position={Position.Left}
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { HTMLAttributes, PropsWithChildren } from 'react';
|
import { HTMLAttributes } from 'react';
|
||||||
|
|
||||||
export function NodeWrapper({
|
type IProps = HTMLAttributes<HTMLDivElement> & { selected?: boolean };
|
||||||
children,
|
|
||||||
className,
|
export function NodeWrapper({ children, className, selected }: IProps) {
|
||||||
}: PropsWithChildren & HTMLAttributes<HTMLDivElement>) {
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-background-header-bar p-2.5 rounded-md w-[200px] text-xs',
|
'bg-background-header-bar p-2.5 rounded-md w-[200px] text-xs',
|
||||||
|
{ 'border border-background-checked': selected },
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -24,7 +24,7 @@ const FormSchema = z.object({
|
|||||||
text: z.string(),
|
text: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
function NoteNode({ data, id }: NodeProps<INoteNode>) {
|
function NoteNode({ data, id, selected }: NodeProps<INoteNode>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof FormSchema>>({
|
const form = useForm<z.infer<typeof FormSchema>>({
|
||||||
@ -37,7 +37,10 @@ function NoteNode({ data, id }: NodeProps<INoteNode>) {
|
|||||||
useWatchFormChange(id, form);
|
useWatchFormChange(id, form);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeWrapper className="p-0 w-full h-full flex flex-col rounded-md ">
|
<NodeWrapper
|
||||||
|
className="p-0 w-full h-full flex flex-col rounded-md "
|
||||||
|
selected={selected}
|
||||||
|
>
|
||||||
<NodeResizeControl minWidth={190} minHeight={128} style={controlStyle}>
|
<NodeResizeControl minWidth={190} minHeight={128} style={controlStyle}>
|
||||||
<ResizeIcon />
|
<ResizeIcon />
|
||||||
</NodeResizeControl>
|
</NodeResizeControl>
|
||||||
|
|||||||
@ -35,7 +35,7 @@ function InnerRetrievalNode({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ToolBar selected={selected} id={id} label={data.label}>
|
<ToolBar selected={selected} id={id} label={data.label}>
|
||||||
<NodeWrapper>
|
<NodeWrapper selected={selected}>
|
||||||
<CommonHandle
|
<CommonHandle
|
||||||
id={NodeHandleId.End}
|
id={NodeHandleId.End}
|
||||||
type="target"
|
type="target"
|
||||||
|
|||||||
@ -65,7 +65,7 @@ function InnerSwitchNode({ id, data, selected }: NodeProps<ISwitchNode>) {
|
|||||||
const { positions } = useBuildSwitchHandlePositions({ data, id });
|
const { positions } = useBuildSwitchHandlePositions({ data, id });
|
||||||
return (
|
return (
|
||||||
<ToolBar selected={selected} id={id} label={data.label}>
|
<ToolBar selected={selected} id={id} label={data.label}>
|
||||||
<NodeWrapper>
|
<NodeWrapper selected={selected}>
|
||||||
<CommonHandle
|
<CommonHandle
|
||||||
type="target"
|
type="target"
|
||||||
position={Position.Left}
|
position={Position.Left}
|
||||||
|
|||||||
@ -8,7 +8,11 @@ import { useFindMcpById } from '../../hooks/use-find-mcp-by-id';
|
|||||||
import useGraphStore from '../../store';
|
import useGraphStore from '../../store';
|
||||||
import { NodeWrapper } from './node-wrapper';
|
import { NodeWrapper } from './node-wrapper';
|
||||||
|
|
||||||
function InnerToolNode({ id, isConnectable = true }: NodeProps<IToolNode>) {
|
function InnerToolNode({
|
||||||
|
id,
|
||||||
|
isConnectable = true,
|
||||||
|
selected,
|
||||||
|
}: NodeProps<IToolNode>) {
|
||||||
const { edges, getNode } = useGraphStore((state) => state);
|
const { edges, getNode } = useGraphStore((state) => state);
|
||||||
const upstreamAgentNodeId = edges.find((x) => x.target === id)?.source;
|
const upstreamAgentNodeId = edges.find((x) => x.target === id)?.source;
|
||||||
const upstreamAgentNode = getNode(upstreamAgentNodeId);
|
const upstreamAgentNode = getNode(upstreamAgentNodeId);
|
||||||
@ -29,7 +33,7 @@ function InnerToolNode({ id, isConnectable = true }: NodeProps<IToolNode>) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeWrapper>
|
<NodeWrapper selected={selected}>
|
||||||
<Handle
|
<Handle
|
||||||
id={NodeHandleId.End}
|
id={NodeHandleId.End}
|
||||||
type="target"
|
type="target"
|
||||||
|
|||||||
@ -20,15 +20,6 @@ import { BeginQueryType } from '../constant';
|
|||||||
import { BeginQuery } from '../interface';
|
import { BeginQuery } from '../interface';
|
||||||
import { FileUploadDirectUpload } from './uploader';
|
import { FileUploadDirectUpload } from './uploader';
|
||||||
|
|
||||||
export const BeginQueryComponentMap = {
|
|
||||||
[BeginQueryType.Line]: 'string',
|
|
||||||
[BeginQueryType.Paragraph]: 'string',
|
|
||||||
[BeginQueryType.Options]: 'string',
|
|
||||||
[BeginQueryType.File]: 'file',
|
|
||||||
[BeginQueryType.Integer]: 'number',
|
|
||||||
[BeginQueryType.Boolean]: 'boolean',
|
|
||||||
};
|
|
||||||
|
|
||||||
const StringFields = [
|
const StringFields = [
|
||||||
BeginQueryType.Line,
|
BeginQueryType.Line,
|
||||||
BeginQueryType.Paragraph,
|
BeginQueryType.Paragraph,
|
||||||
@ -68,7 +59,7 @@ const DebugContent = ({
|
|||||||
} else if (type === BeginQueryType.Boolean) {
|
} else if (type === BeginQueryType.Boolean) {
|
||||||
fieldSchema = z.boolean();
|
fieldSchema = z.boolean();
|
||||||
value = false;
|
value = false;
|
||||||
} else if (type === BeginQueryType.Integer) {
|
} else if (type === BeginQueryType.Integer || type === 'float') {
|
||||||
fieldSchema = z.coerce.number();
|
fieldSchema = z.coerce.number();
|
||||||
} else {
|
} else {
|
||||||
fieldSchema = z.record(z.any());
|
fieldSchema = z.record(z.any());
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import CopyToClipboard from '@/components/copy-to-clipboard';
|
import CopyToClipboard from '@/components/copy-to-clipboard';
|
||||||
import { Sheet, SheetContent, SheetHeader } from '@/components/ui/sheet';
|
import { Sheet, SheetContent, SheetHeader } from '@/components/ui/sheet';
|
||||||
import { useDebugSingle } from '@/hooks/flow-hooks';
|
import { useDebugSingle, useFetchInputForm } from '@/hooks/use-agent-request';
|
||||||
import { useFetchInputForm } from '@/hooks/use-agent-request';
|
|
||||||
import { IModalProps } from '@/interfaces/common';
|
import { IModalProps } from '@/interfaces/common';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import { X } from 'lucide-react';
|
import { X } from 'lucide-react';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
@ -10,6 +10,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
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 DebugContent from '../../debug-content';
|
import DebugContent from '../../debug-content';
|
||||||
|
import { transferInputsArrayToObject } from '../../form/begin-form/use-watch-change';
|
||||||
import { buildBeginInputListFromObject } from '../../form/begin-form/utils';
|
import { buildBeginInputListFromObject } from '../../form/begin-form/utils';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
@ -32,7 +33,10 @@ const SingleDebugSheet = ({
|
|||||||
const onOk = useCallback(
|
const onOk = useCallback(
|
||||||
(nextValues: any[]) => {
|
(nextValues: any[]) => {
|
||||||
if (componentId) {
|
if (componentId) {
|
||||||
debugSingle({ component_id: componentId, params: nextValues });
|
debugSingle({
|
||||||
|
component_id: componentId,
|
||||||
|
params: transferInputsArrayToObject(nextValues),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[componentId, debugSingle],
|
[componentId, debugSingle],
|
||||||
@ -58,7 +62,11 @@ const SingleDebugSheet = ({
|
|||||||
submitButtonDisabled={list.length === 0}
|
submitButtonDisabled={list.length === 0}
|
||||||
></DebugContent>
|
></DebugContent>
|
||||||
{!isEmpty(data) ? (
|
{!isEmpty(data) ? (
|
||||||
<div className="mt-4 rounded-md bg-slate-200 border border-neutral-200">
|
<div
|
||||||
|
className={cn('mt-4 rounded-md border', {
|
||||||
|
[`border-text-delete-red`]: !isEmpty(data._ERROR),
|
||||||
|
})}
|
||||||
|
>
|
||||||
<div className="flex justify-between p-2">
|
<div className="flex justify-between p-2">
|
||||||
<span>JSON</span>
|
<span>JSON</span>
|
||||||
<CopyToClipboard text={content}></CopyToClipboard>
|
<CopyToClipboard text={content}></CopyToClipboard>
|
||||||
@ -67,7 +75,8 @@ const SingleDebugSheet = ({
|
|||||||
src={data}
|
src={data}
|
||||||
displaySize
|
displaySize
|
||||||
collapseStringsAfterLength={100000000000}
|
collapseStringsAfterLength={100000000000}
|
||||||
className="w-full h-[800px] break-words overflow-auto p-2 bg-slate-100"
|
className="w-full h-[800px] break-words overflow-auto p-2"
|
||||||
|
dark
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
Reference in New Issue
Block a user