mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-01-02 18:45:29 +08:00
Feature:Add a loading status to the agent canvas page. (#11733)
### What problem does this PR solve? Feature:Add a loading status to the agent canvas page. ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -40,6 +40,7 @@ import { useDropdownManager } from './context';
|
||||
|
||||
import { AgentBackground } from '@/components/canvas/background';
|
||||
import Spotlight from '@/components/spotlight';
|
||||
import { useNodeLoading } from '../hooks/use-node-loading';
|
||||
import {
|
||||
useHideFormSheetOnNodeDeletion,
|
||||
useShowDrawer,
|
||||
@ -166,6 +167,8 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
|
||||
});
|
||||
const [lastSendLoading, setLastSendLoading] = useState(false);
|
||||
|
||||
const [currentSendLoading, setCurrentSendLoading] = useState(false);
|
||||
|
||||
const { handleBeforeDelete } = useBeforeDelete();
|
||||
|
||||
const { addCanvasNode, addNoteNode } = useAddNode(reactFlowInstance);
|
||||
@ -182,6 +185,7 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
|
||||
}, [chatVisible, clearEventList, currentTaskId, stopMessage]);
|
||||
|
||||
const setLastSendLoadingFunc = (loading: boolean, messageId: string) => {
|
||||
setCurrentSendLoading(!!loading);
|
||||
if (messageId === currentMessageId) {
|
||||
setLastSendLoading(loading);
|
||||
} else {
|
||||
@ -249,7 +253,10 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
|
||||
clearActiveDropdown,
|
||||
removePlaceholderNode,
|
||||
]);
|
||||
|
||||
const { lastNode, setDerivedMessages, startButNotFinishedNodeIds } =
|
||||
useNodeLoading({
|
||||
currentEventListWithoutMessageById,
|
||||
});
|
||||
return (
|
||||
<div className={cn(styles.canvasWrapper, 'px-5 pb-5')}>
|
||||
<svg
|
||||
@ -285,7 +292,15 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
|
||||
</marker>
|
||||
</defs>
|
||||
</svg>
|
||||
<AgentInstanceContext.Provider value={{ addCanvasNode, showFormDrawer }}>
|
||||
<AgentInstanceContext.Provider
|
||||
value={{
|
||||
addCanvasNode,
|
||||
showFormDrawer,
|
||||
lastNode,
|
||||
currentSendLoading,
|
||||
startButNotFinishedNodeIds,
|
||||
}}
|
||||
>
|
||||
<ReactFlow
|
||||
connectionMode={ConnectionMode.Loose}
|
||||
nodes={nodes}
|
||||
@ -380,9 +395,10 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
|
||||
></FormSheet>
|
||||
</AgentInstanceContext.Provider>
|
||||
)}
|
||||
|
||||
{chatVisible && (
|
||||
<AgentChatContext.Provider
|
||||
value={{ showLogSheet, setLastSendLoadingFunc }}
|
||||
value={{ showLogSheet, setLastSendLoadingFunc, setDerivedMessages }}
|
||||
>
|
||||
<AgentChatLogContext.Provider
|
||||
value={{ addEventList, setCurrentMessageId }}
|
||||
|
||||
@ -44,7 +44,7 @@ function InnerAgentNode({
|
||||
|
||||
return (
|
||||
<ToolBar selected={selected} id={id} label={data.label}>
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
{isHeadAgent && (
|
||||
<>
|
||||
<LeftEndHandle></LeftEndHandle>
|
||||
|
||||
@ -24,7 +24,7 @@ function InnerBeginNode({ data, id, selected }: NodeProps<IBeginNode>) {
|
||||
const inputs: Record<string, BeginQuery> = get(data, 'form.inputs', {});
|
||||
|
||||
return (
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<CommonHandle
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
|
||||
@ -18,7 +18,7 @@ export function InnerCategorizeNode({
|
||||
const { positions } = useBuildCategorizeHandlePositions({ data, id });
|
||||
return (
|
||||
<ToolBar selected={selected} id={id} label={data.label}>
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<LeftEndHandle></LeftEndHandle>
|
||||
|
||||
<NodeHeader id={id} name={data.name} label={data.label}></NodeHeader>
|
||||
|
||||
@ -14,7 +14,7 @@ export function ExitLoopNode({ id, data, selected }: NodeProps<BaseNode<any>>) {
|
||||
showRun={false}
|
||||
showCopy={false}
|
||||
>
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<LeftEndHandle></LeftEndHandle>
|
||||
<NodeHeader id={id} name={data.name} label={data.label}></NodeHeader>
|
||||
</NodeWrapper>
|
||||
|
||||
@ -23,7 +23,7 @@ function InnerFileNode({ data, id, selected }: NodeProps<IBeginNode>) {
|
||||
const inputs: Record<string, BeginQuery> = get(data, 'form.inputs', {});
|
||||
|
||||
return (
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<CommonHandle
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
|
||||
@ -26,7 +26,7 @@ function InnerRagNode({
|
||||
showRun={needsSingleStepDebugging(data.label)}
|
||||
showCopy={showCopyIcon(data.label)}
|
||||
>
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<LeftEndHandle></LeftEndHandle>
|
||||
<CommonHandle
|
||||
type="source"
|
||||
|
||||
@ -16,7 +16,7 @@ function InnerMessageNode({ id, data, selected }: NodeProps<IMessageNode>) {
|
||||
const messages: string[] = get(data, 'form.content', []);
|
||||
return (
|
||||
<ToolBar selected={selected} id={id} label={data.label}>
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<LeftEndHandle></LeftEndHandle>
|
||||
<NodeHeader
|
||||
id={id}
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
import { cn } from '@/lib/utils';
|
||||
import { HTMLAttributes } from 'react';
|
||||
import { Loader } from 'lucide-react';
|
||||
import { HTMLAttributes, useContext } from 'react';
|
||||
import { AgentInstanceContext } from '../../context';
|
||||
|
||||
type IProps = HTMLAttributes<HTMLDivElement> & { selected?: boolean };
|
||||
|
||||
export function NodeWrapper({ children, className, selected }: IProps) {
|
||||
export function NodeWrapper({ children, className, selected, id }: IProps) {
|
||||
const { currentSendLoading, startButNotFinishedNodeIds = [] } =
|
||||
useContext(AgentInstanceContext);
|
||||
return (
|
||||
<section
|
||||
className={cn(
|
||||
@ -12,6 +16,13 @@ export function NodeWrapper({ children, className, selected }: IProps) {
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{id &&
|
||||
startButNotFinishedNodeIds.indexOf(id as string) > -1 &&
|
||||
currentSendLoading && (
|
||||
<div className=" absolute right-0 left-0 top-0 flex items-start justify-end p-2">
|
||||
<Loader size={12} className=" animate-spin" />
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
</section>
|
||||
);
|
||||
|
||||
@ -19,7 +19,7 @@ function ParserNode({
|
||||
}: NodeProps<BaseNode<ParserFormSchemaType>>) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<CommonHandle
|
||||
id={NodeHandleId.End}
|
||||
type="target"
|
||||
|
||||
@ -27,7 +27,7 @@ function InnerRetrievalNode({
|
||||
|
||||
return (
|
||||
<ToolBar selected={selected} id={id} label={data.label}>
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<LeftEndHandle></LeftEndHandle>
|
||||
<CommonHandle
|
||||
id={NodeHandleId.Start}
|
||||
|
||||
@ -25,7 +25,7 @@ function InnerSplitterNode({
|
||||
showCopy={false}
|
||||
showRun={false}
|
||||
>
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<CommonHandle
|
||||
id={NodeHandleId.End}
|
||||
type="target"
|
||||
|
||||
@ -65,7 +65,7 @@ function InnerSwitchNode({ id, data, selected }: NodeProps<ISwitchNode>) {
|
||||
const { positions } = useBuildSwitchHandlePositions({ data, id });
|
||||
return (
|
||||
<ToolBar selected={selected} id={id} label={data.label} showRun={false}>
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<LeftEndHandle></LeftEndHandle>
|
||||
<NodeHeader id={id} name={data.name} label={data.label}></NodeHeader>
|
||||
<section className="gap-2.5 flex flex-col">
|
||||
|
||||
@ -27,7 +27,7 @@ function TokenizerNode({
|
||||
showRun={false}
|
||||
showCopy={false}
|
||||
>
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<CommonHandle
|
||||
id={NodeHandleId.End}
|
||||
type="target"
|
||||
|
||||
@ -44,7 +44,7 @@ function InnerToolNode({
|
||||
);
|
||||
|
||||
return (
|
||||
<NodeWrapper selected={selected}>
|
||||
<NodeWrapper selected={selected} id={id}>
|
||||
<Handle
|
||||
id={NodeHandleId.End}
|
||||
type="target"
|
||||
|
||||
Reference in New Issue
Block a user