From 2b475b791607422dc9c24a2c8c49d4310079bf1c Mon Sep 17 00:00:00 2001 From: StyleZhang Date: Fri, 8 Mar 2024 16:02:01 +0800 Subject: [PATCH] help line --- .../workflow/block-selector/index.tsx | 8 +- .../workflow/block-selector/tabs.tsx | 10 +- .../workflow/block-selector/tools/item.tsx | 1 + .../workflow/block-selector/types.ts | 1 + web/app/components/workflow/header/index.tsx | 9 +- .../components/workflow/help-line/index.tsx | 61 +++++++--- .../components/workflow/help-line/types.ts | 11 +- web/app/components/workflow/hooks.ts | 107 ++++++++++++++---- web/app/components/workflow/store.ts | 17 ++- web/app/components/workflow/types.ts | 2 +- 10 files changed, 176 insertions(+), 51 deletions(-) diff --git a/web/app/components/workflow/block-selector/index.tsx b/web/app/components/workflow/block-selector/index.tsx index 0ad854335e..8c9cf7f8fb 100644 --- a/web/app/components/workflow/block-selector/index.tsx +++ b/web/app/components/workflow/block-selector/index.tsx @@ -49,6 +49,7 @@ const NodeSelector: FC = ({ asChild, }) => { const { t } = useTranslation() + const [searchText, setSearchText] = useState('') const [localOpen, setLocalOpen] = useState(false) const open = openFromProps === undefined ? localOpen : openFromProps const handleOpenChange = useCallback((newOpen: boolean) => { @@ -103,12 +104,17 @@ const NodeSelector: FC = ({ > setSearchText(e.target.value)} /> - + diff --git a/web/app/components/workflow/block-selector/tabs.tsx b/web/app/components/workflow/block-selector/tabs.tsx index c3342a03fc..9f87fdcd66 100644 --- a/web/app/components/workflow/block-selector/tabs.tsx +++ b/web/app/components/workflow/block-selector/tabs.tsx @@ -18,9 +18,11 @@ import { TabsEnum } from './types' import Tools from './tools' export type TabsProps = { + searchText: string onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void } const Tabs: FC = ({ + searchText, onSelect, }) => { const { t } = useTranslation() @@ -31,14 +33,16 @@ const Tabs: FC = ({ return (
e.stopPropagation()}> -
+
{ tabs.map(tab => (
setActiveTab(tab.key)} > diff --git a/web/app/components/workflow/block-selector/tools/item.tsx b/web/app/components/workflow/block-selector/tools/item.tsx index e9e4606944..6fdd0739ca 100644 --- a/web/app/components/workflow/block-selector/tools/item.tsx +++ b/web/app/components/workflow/block-selector/tools/item.tsx @@ -104,6 +104,7 @@ const Item = ({ onClick={() => onSelect(BlockEnum.Tool, { provider_id: data.id, provider_type: data.type, + provider_name: data.name, tool_name: tool.name, title: tool.label[language], })} diff --git a/web/app/components/workflow/block-selector/types.ts b/web/app/components/workflow/block-selector/types.ts index 4f4c60d30a..12a70cdaca 100644 --- a/web/app/components/workflow/block-selector/types.ts +++ b/web/app/components/workflow/block-selector/types.ts @@ -28,6 +28,7 @@ export type ToolsMap = Record export type ToolDefaultValue = { provider_id: string provider_type: string + provider_name: string tool_name: string title: string } diff --git a/web/app/components/workflow/header/index.tsx b/web/app/components/workflow/header/index.tsx index 5e8bf8dc8a..f5cc8d889d 100644 --- a/web/app/components/workflow/header/index.tsx +++ b/web/app/components/workflow/header/index.tsx @@ -18,7 +18,8 @@ import { Mode } from '@/app/components/workflow/types' const Header: FC = () => { const { t } = useTranslation() - const appDetail = useAppStore(state => state.appDetail) + const appDetail = useAppStore(s => s.appDetail) + const appSidebarExpand = useAppStore(s => s.appSidebarExpand) const isChatMode = useIsChatMode() const mode = useStore(state => state.mode) const runTaskId = useStore(state => state.runTaskId) @@ -35,7 +36,11 @@ const Header: FC = () => { }} >
-
{appDetail?.name}
+ { + appSidebarExpand && ( +
{appDetail?.name}
+ ) + } { mode === Mode.Editing && !runTaskId && } diff --git a/web/app/components/workflow/help-line/index.tsx b/web/app/components/workflow/help-line/index.tsx index b188dce5a0..769f5489c2 100644 --- a/web/app/components/workflow/help-line/index.tsx +++ b/web/app/components/workflow/help-line/index.tsx @@ -1,37 +1,72 @@ +import { memo } from 'react' +import { useViewport } from 'reactflow' import { useStore } from '../store' -import type { HelpLinePosition } from './types' +import type { + HelpLineHorizontalPosition, + HelpLineVerticalPosition, +} from './types' -const HelpLineBase = ({ +const HelpLineHorizontal = memo(({ top, - right, - bottom, left, -}: HelpLinePosition) => { + width, +}: HelpLineHorizontalPosition) => { + const { x, y, zoom } = useViewport() + + return ( +
+ ) +}) +HelpLineHorizontal.displayName = 'HelpLineBase' + +const HelpLineVertical = memo(({ + top, + left, + height, +}: HelpLineVerticalPosition) => { + const { x, y, zoom } = useViewport() + return (
) -} +}) +HelpLineVertical.displayName = 'HelpLineVertical' const HelpLine = () => { - const helpLine = useStore(state => state.helpLine) + const helpLineHorizontal = useStore(s => s.helpLineHorizontal) + const helpLineVertical = useStore(s => s.helpLineVertical) + + if (!helpLineHorizontal && !helpLineVertical) + return null return ( <> { - helpLine?.bottom && ( - + helpLineHorizontal && ( + ) } { - helpLine?.right && ( - + helpLineVertical && ( + ) } ) } -export default HelpLine +export default memo(HelpLine) diff --git a/web/app/components/workflow/help-line/types.ts b/web/app/components/workflow/help-line/types.ts index a96d4c089b..0e8253dcba 100644 --- a/web/app/components/workflow/help-line/types.ts +++ b/web/app/components/workflow/help-line/types.ts @@ -1,6 +1,11 @@ -export type HelpLinePosition = { +export type HelpLineHorizontalPosition = { top: number - right?: number - bottom?: number left: number + width: number +} + +export type HelpLineVerticalPosition = { + top: number + left: number + height: number } diff --git a/web/app/components/workflow/hooks.ts b/web/app/components/workflow/hooks.ts index 44343c32c4..eb1ab8b886 100644 --- a/web/app/components/workflow/hooks.ts +++ b/web/app/components/workflow/hooks.ts @@ -138,37 +138,96 @@ export const useWorkflow = () => { getNodes, setNodes, } = store.getState() - // const { setHelpLine } = useStore.getState() + const { + setHelpLineHorizontal, + setHelpLineVertical, + } = useStore.getState() e.stopPropagation() const nodes = getNodes() - // const showVerticalHelpLineNodes = nodes.filter((n) => { - // if ( - // n.position.x === node.position.x - // || n.position.x + n.width! === node.position.x - // || n.position.x === node.position.x + node.width! - // ) - // return true + const showHorizontalHelpLineNodes = nodes.filter((n) => { + if (n.id === node.id) + return false - // return false - // }) - // const showHorizontalHelpLineNodes = nodes.filter((n) => { - // if ( - // n.position.y === node.position.y - // || n.position.y === node.position.y + node.height! - // || n.position.y + n.height! === node.position.y - // || n.position.y + n.height! === node.position.y + node.height! - // ) - // return true + const nY = Math.ceil(n.position.y) + const nodeY = Math.ceil(node.position.y) - // return false - // }) + if (nY - nodeY < 5 && nY - nodeY > -5) + return true + + return false + }).sort((a, b) => a.position.x - b.position.x) + const showHorizontalHelpLineNodesLength = showHorizontalHelpLineNodes.length + if (showHorizontalHelpLineNodesLength > 0) { + const first = showHorizontalHelpLineNodes[0] + const last = showHorizontalHelpLineNodes[showHorizontalHelpLineNodesLength - 1] + + const helpLine = { + top: first.position.y, + left: first.position.x, + width: last.position.x + last.width! - first.position.x, + } + + if (node.position.x < first.position.x) { + helpLine.left = node.position.x + helpLine.width = first.position.x + first.width! - node.position.x + } + + if (node.position.x > last.position.x) + helpLine.width = node.position.x + node.width! - first.position.x + + setHelpLineHorizontal(helpLine) + } + else { + setHelpLineHorizontal() + } + + const showVerticalHelpLineNodes = nodes.filter((n) => { + if (n.id === node.id) + return false + + const nX = Math.ceil(n.position.x) + const nodeX = Math.ceil(node.position.x) + + if (nX - nodeX < 5 && nX - nodeX > -5) + return true + + return false + }).sort((a, b) => a.position.x - b.position.x) + const showVerticalHelpLineNodesLength = showVerticalHelpLineNodes.length + + if (showVerticalHelpLineNodesLength > 0) { + const first = showVerticalHelpLineNodes[0] + const last = showVerticalHelpLineNodes[showVerticalHelpLineNodesLength - 1] + + const helpLine = { + top: first.position.y, + left: first.position.x, + height: last.position.y + last.height! - first.position.y, + } + + if (node.position.y < first.position.y) { + helpLine.top = node.position.y + helpLine.height = first.position.y + first.height! - node.position.y + } + + if (node.position.y > last.position.y) + helpLine.height = node.position.y + node.height! - first.position.y + + setHelpLineVertical(helpLine) + } + else { + setHelpLineVertical() + } const newNodes = produce(nodes, (draft) => { const currentNode = draft.find(n => n.id === node.id)! - currentNode.position = node.position + currentNode.position = { + x: showVerticalHelpLineNodesLength > 0 ? showVerticalHelpLineNodes[0].position.x : node.position.x, + y: showHorizontalHelpLineNodesLength > 0 ? showHorizontalHelpLineNodes[0].position.y : node.position.y, + } }) setNodes(newNodes) @@ -177,10 +236,12 @@ export const useWorkflow = () => { const handleNodeDragStop = useCallback(() => { const { setIsDragging, - setHelpLine, + setHelpLineHorizontal, + setHelpLineVertical, } = useStore.getState() setIsDragging(false) - setHelpLine() + setHelpLineHorizontal() + setHelpLineVertical() handleSyncWorkflowDraft() }, [handleSyncWorkflowDraft]) diff --git a/web/app/components/workflow/store.ts b/web/app/components/workflow/store.ts index 16511f649c..27a2d264e7 100644 --- a/web/app/components/workflow/store.ts +++ b/web/app/components/workflow/store.ts @@ -1,5 +1,8 @@ import { create } from 'zustand' -import type { HelpLinePosition } from './help-line/types' +import type { + HelpLineHorizontalPosition, + HelpLineVerticalPosition, +} from './help-line/types' import type { CollectionWithExpanded, ToolInWorkflow, @@ -13,7 +16,8 @@ type State = { showRunHistory: boolean showFeaturesPanel: boolean isDragging: boolean - helpLine?: HelpLinePosition + helpLineHorizontal?: HelpLineHorizontalPosition + helpLineVertical?: HelpLineVerticalPosition toolsets: CollectionWithExpanded[] toolsMap: ToolsMap draftUpdatedAt: number @@ -26,7 +30,8 @@ type Action = { setShowRunHistory: (showRunHistory: boolean) => void setShowFeaturesPanel: (showFeaturesPanel: boolean) => void setIsDragging: (isDragging: boolean) => void - setHelpLine: (helpLine?: HelpLinePosition) => void + setHelpLineHorizontal: (helpLineHorizontal?: HelpLineHorizontalPosition) => void + setHelpLineVertical: (helpLineVertical?: HelpLineVerticalPosition) => void setToolsets: (toolsets: CollectionWithExpanded[]) => void setToolsMap: (toolsMap: Record) => void setDraftUpdatedAt: (draftUpdatedAt: number) => void @@ -44,8 +49,10 @@ export const useStore = create(set => ({ setShowFeaturesPanel: showFeaturesPanel => set(() => ({ showFeaturesPanel })), isDragging: false, setIsDragging: isDragging => set(() => ({ isDragging })), - helpLine: undefined, - setHelpLine: helpLine => set(() => ({ helpLine })), + helpLineHorizontal: undefined, + setHelpLineHorizontal: helpLineHorizontal => set(() => ({ helpLineHorizontal })), + helpLineVertical: undefined, + setHelpLineVertical: helpLineVertical => set(() => ({ helpLineVertical })), toolsets: [], setToolsets: toolsets => set(() => ({ toolsets })), toolsMap: {}, diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts index 87e3409f94..2d6f0690be 100644 --- a/web/app/components/workflow/types.ts +++ b/web/app/components/workflow/types.ts @@ -31,7 +31,7 @@ export type CommonNodeType = { title: string desc: string type: BlockEnum -} & T & Partial> +} & T & Partial> export type CommonEdgeType = { _hovering: boolean