diff --git a/web/package-lock.json b/web/package-lock.json index f06080d39..6f7074d10 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -70,6 +70,7 @@ "mammoth": "^1.7.2", "next-themes": "^0.4.6", "openai-speech-stream-player": "^1.0.8", + "pptx-preview": "^1.0.5", "rc-tween-one": "^3.0.6", "react-copy-to-clipboard": "^5.1.0", "react-dropzone": "^14.3.5", @@ -15819,6 +15820,22 @@ "node": ">=4" } }, + "node_modules/echarts": { + "version": "5.6.0", + "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz", + "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "5.6.1" + } + }, + "node_modules/echarts/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", @@ -26241,6 +26258,32 @@ "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/pptx-preview": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/pptx-preview/-/pptx-preview-1.0.5.tgz", + "integrity": "sha512-4SafvnLUpwpAY9pHHTHzzU77DANTnxZQgnLK51g3qqv0CMSOAV6f9SVc9ANYXJ0+vyTwakt780xY4s/mbRO/KQ==", + "license": "ISC", + "dependencies": { + "echarts": "^5.5.1", + "jszip": "^3.10.1", + "lodash": "^4.17.21", + "tslib": "^2.7.0", + "uuid": "^10.0.0" + } + }, + "node_modules/pptx-preview/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -33925,6 +33968,21 @@ "url": "https://github.com/sponsors/colinhacks" } }, + "node_modules/zrender": { + "version": "5.6.1", + "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz", + "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==", + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } + }, + "node_modules/zrender/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, "node_modules/zustand": { "version": "4.5.2", "resolved": "https://registry.npmmirror.com/zustand/-/zustand-4.5.2.tgz", diff --git a/web/src/hooks/use-agent-request.ts b/web/src/hooks/use-agent-request.ts index 9570625dc..772cfc847 100644 --- a/web/src/hooks/use-agent-request.ts +++ b/web/src/hooks/use-agent-request.ts @@ -318,7 +318,7 @@ export const useFetchMessageTrace = () => { refetchOnWindowFocus: false, gcTime: 0, enabled: !!id && !!messageId, - refetchInterval: 2000, + refetchInterval: 3000, queryFn: async () => { const { data } = await flowService.trace({ canvas_id: id, diff --git a/web/src/pages/agent/canvas/index.tsx b/web/src/pages/agent/canvas/index.tsx index 829ed30ec..61c4caa75 100644 --- a/web/src/pages/agent/canvas/index.tsx +++ b/web/src/pages/agent/canvas/index.tsx @@ -1,11 +1,21 @@ +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from '@/components/ui/tooltip'; +import { cn } from '@/lib/utils'; import { Background, ConnectionMode, + ControlButton, + Controls, NodeTypes, ReactFlow, } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; -import { useEffect } from 'react'; +import { NotebookPen } from 'lucide-react'; +import { useCallback, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; import { ChatSheet } from '../chat/chat-sheet'; import { AgentChatContext, @@ -21,6 +31,7 @@ import { import { useAddNode } from '../hooks/use-add-node'; import { useBeforeDelete } from '../hooks/use-before-delete'; import { useCacheChatLog } from '../hooks/use-cache-chat-log'; +import { useMoveNote } from '../hooks/use-move-note'; import { useShowDrawer, useShowLogSheet } from '../hooks/use-show-drawer'; import { LogSheet } from '../log-sheet'; import RunSheet from '../run-sheet'; @@ -77,6 +88,7 @@ interface IProps { } function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { + const { t } = useTranslation(); const { nodes, edges, @@ -94,7 +106,6 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { const { onNodeClick, - onPaneClick, clickedNode, formDrawerVisible, hideFormDrawer, @@ -124,7 +135,17 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { const { handleBeforeDelete } = useBeforeDelete(); - const { addCanvasNode } = useAddNode(reactFlowInstance); + const { addCanvasNode, addNoteNode } = useAddNode(reactFlowInstance); + + const { ref, showImage, hideImage, imgVisible, mouse } = useMoveNote(); + + const onPaneClick = useCallback(() => { + hideFormDrawer(); + if (imgVisible) { + addNoteNode(mouse); + hideImage(); + } + }, [addNoteNode, hideFormDrawer, hideImage, imgVisible, mouse]); useEffect(() => { if (!chatVisible) { @@ -176,6 +197,7 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { onEdgeMouseEnter={onEdgeMouseEnter} onEdgeMouseLeave={onEdgeMouseLeave} className="h-full" + colorMode="dark" defaultEdgeOptions={{ type: 'buttonEdge', markerEnd: 'logo', @@ -189,8 +211,22 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { onBeforeDelete={handleBeforeDelete} > + + + + + + + {t('flow.note')} + + + + {formDrawerVisible && ( - - - - - - - ); -} - -const controlStyle = { - background: 'transparent', - border: 'none', - cursor: 'nwse-resize', -}; - export function InnerIterationNode({ id, data, diff --git a/web/src/pages/agent/canvas/node/note-node.tsx b/web/src/pages/agent/canvas/node/note-node.tsx deleted file mode 100644 index 237942133..000000000 --- a/web/src/pages/agent/canvas/node/note-node.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { NodeProps, NodeResizeControl } from '@xyflow/react'; -import { Flex, Form, Input } from 'antd'; -import classNames from 'classnames'; -import NodeDropdown from './dropdown'; - -import SvgIcon from '@/components/svg-icon'; -import { useTheme } from '@/components/theme-provider'; -import { INoteNode } from '@/interfaces/database/flow'; -import { memo, useEffect } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useHandleNodeNameChange } from '../../hooks'; -import { useHandleFormValuesChange } from '../../hooks/use-watch-form-change'; -import styles from './index.less'; - -const { TextArea } = Input; - -const controlStyle = { - background: 'transparent', - border: 'none', -}; - -function NoteNode({ data, id }: NodeProps) { - const { t } = useTranslation(); - const [form] = Form.useForm(); - const { theme } = useTheme(); - - const { name, handleNameBlur, handleNameChange } = useHandleNodeNameChange({ - id, - data, - }); - const { handleValuesChange } = useHandleFormValuesChange(id); - - useEffect(() => { - form.setFieldsValue(data?.form); - }, [form, data?.form]); - - return ( - <> - - - -
- - - - - -
- -