Commit 2b475b79 authored by StyleZhang's avatar StyleZhang

help line

parent f51f4a58
...@@ -49,6 +49,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({ ...@@ -49,6 +49,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
asChild, asChild,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const [searchText, setSearchText] = useState('')
const [localOpen, setLocalOpen] = useState(false) const [localOpen, setLocalOpen] = useState(false)
const open = openFromProps === undefined ? localOpen : openFromProps const open = openFromProps === undefined ? localOpen : openFromProps
const handleOpenChange = useCallback((newOpen: boolean) => { const handleOpenChange = useCallback((newOpen: boolean) => {
...@@ -103,12 +104,17 @@ const NodeSelector: FC<NodeSelectorProps> = ({ ...@@ -103,12 +104,17 @@ const NodeSelector: FC<NodeSelectorProps> = ({
> >
<SearchLg className='shrink-0 ml-[1px] mr-[5px] w-3.5 h-3.5 text-gray-400' /> <SearchLg className='shrink-0 ml-[1px] mr-[5px] w-3.5 h-3.5 text-gray-400' />
<input <input
value={searchText}
className='grow px-0.5 py-[7px] text-[13px] bg-transparent appearance-none outline-none' className='grow px-0.5 py-[7px] text-[13px] bg-transparent appearance-none outline-none'
placeholder={t('workflow.tabs.searchBlock') || ''} placeholder={t('workflow.tabs.searchBlock') || ''}
onChange={e => setSearchText(e.target.value)}
/> />
</div> </div>
</div> </div>
<Tabs onSelect={handleSelect} /> <Tabs
onSelect={handleSelect}
searchText={searchText}
/>
</div> </div>
</PortalToFollowElemContent> </PortalToFollowElemContent>
</PortalToFollowElem> </PortalToFollowElem>
......
...@@ -18,9 +18,11 @@ import { TabsEnum } from './types' ...@@ -18,9 +18,11 @@ import { TabsEnum } from './types'
import Tools from './tools' import Tools from './tools'
export type TabsProps = { export type TabsProps = {
searchText: string
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
} }
const Tabs: FC<TabsProps> = ({ const Tabs: FC<TabsProps> = ({
searchText,
onSelect, onSelect,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
...@@ -31,14 +33,16 @@ const Tabs: FC<TabsProps> = ({ ...@@ -31,14 +33,16 @@ const Tabs: FC<TabsProps> = ({
return ( return (
<div onClick={e => e.stopPropagation()}> <div onClick={e => e.stopPropagation()}>
<div className='flex items-center px-3 h-[34px] border-b-[0.5px] border-b-black/5'> <div className='flex items-center px-3 border-b-[0.5px] border-b-black/5'>
{ {
tabs.map(tab => ( tabs.map(tab => (
<div <div
key={tab.key} key={tab.key}
className={` className={`
mr-4 text-[13px] font-medium cursor-pointer relative mr-4 h-[34px] leading-[34px] text-[13px] font-medium cursor-pointer
${activeTab === tab.key ? 'text-gray-700' : 'text-gray-500'} ${activeTab === tab.key
? 'text-gray-700 after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-full after:bg-primary-600'
: 'text-gray-500'}
`} `}
onClick={() => setActiveTab(tab.key)} onClick={() => setActiveTab(tab.key)}
> >
......
...@@ -104,6 +104,7 @@ const Item = ({ ...@@ -104,6 +104,7 @@ const Item = ({
onClick={() => onSelect(BlockEnum.Tool, { onClick={() => onSelect(BlockEnum.Tool, {
provider_id: data.id, provider_id: data.id,
provider_type: data.type, provider_type: data.type,
provider_name: data.name,
tool_name: tool.name, tool_name: tool.name,
title: tool.label[language], title: tool.label[language],
})} })}
......
...@@ -28,6 +28,7 @@ export type ToolsMap = Record<string, ToolInWorkflow[]> ...@@ -28,6 +28,7 @@ export type ToolsMap = Record<string, ToolInWorkflow[]>
export type ToolDefaultValue = { export type ToolDefaultValue = {
provider_id: string provider_id: string
provider_type: string provider_type: string
provider_name: string
tool_name: string tool_name: string
title: string title: string
} }
...@@ -18,7 +18,8 @@ import { Mode } from '@/app/components/workflow/types' ...@@ -18,7 +18,8 @@ import { Mode } from '@/app/components/workflow/types'
const Header: FC = () => { const Header: FC = () => {
const { t } = useTranslation() 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 isChatMode = useIsChatMode()
const mode = useStore(state => state.mode) const mode = useStore(state => state.mode)
const runTaskId = useStore(state => state.runTaskId) const runTaskId = useStore(state => state.runTaskId)
...@@ -35,7 +36,11 @@ const Header: FC = () => { ...@@ -35,7 +36,11 @@ const Header: FC = () => {
}} }}
> >
<div> <div>
{
appSidebarExpand && (
<div className='text-xs font-medium text-gray-700'>{appDetail?.name}</div> <div className='text-xs font-medium text-gray-700'>{appDetail?.name}</div>
)
}
{ {
mode === Mode.Editing && !runTaskId && <EditingTitle /> mode === Mode.Editing && !runTaskId && <EditingTitle />
} }
......
import { memo } from 'react'
import { useViewport } from 'reactflow'
import { useStore } from '../store' import { useStore } from '../store'
import type { HelpLinePosition } from './types' import type {
HelpLineHorizontalPosition,
HelpLineVerticalPosition,
} from './types'
const HelpLineBase = ({ const HelpLineHorizontal = memo(({
top, top,
right,
bottom,
left, left,
}: HelpLinePosition) => { width,
}: HelpLineHorizontalPosition) => {
const { x, y, zoom } = useViewport()
return (
<div
className='absolute h-[1px] bg-primary-300 z-[9]'
style={{
top: top * zoom + y,
left: left * zoom + x,
width: width * zoom,
}}
/>
)
})
HelpLineHorizontal.displayName = 'HelpLineBase'
const HelpLineVertical = memo(({
top,
left,
height,
}: HelpLineVerticalPosition) => {
const { x, y, zoom } = useViewport()
return ( return (
<div <div
className='absolute w-[1px] bg-primary-300 z-[9]' className='absolute w-[1px] bg-primary-300 z-[9]'
style={{ top, right, bottom, left }} style={{
top: top * zoom + y,
left: left * zoom + x,
height: height * zoom,
}}
/> />
) )
} })
HelpLineVertical.displayName = 'HelpLineVertical'
const HelpLine = () => { 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 ( return (
<> <>
{ {
helpLine?.bottom && ( helpLineHorizontal && (
<HelpLineBase {...helpLine} /> <HelpLineHorizontal {...helpLineHorizontal} />
) )
} }
{ {
helpLine?.right && ( helpLineVertical && (
<HelpLineBase {...helpLine} /> <HelpLineVertical {...helpLineVertical} />
) )
} }
</> </>
) )
} }
export default HelpLine export default memo(HelpLine)
export type HelpLinePosition = { export type HelpLineHorizontalPosition = {
top: number top: number
right?: number
bottom?: number
left: number left: number
width: number
}
export type HelpLineVerticalPosition = {
top: number
left: number
height: number
} }
...@@ -138,37 +138,96 @@ export const useWorkflow = () => { ...@@ -138,37 +138,96 @@ export const useWorkflow = () => {
getNodes, getNodes,
setNodes, setNodes,
} = store.getState() } = store.getState()
// const { setHelpLine } = useStore.getState() const {
setHelpLineHorizontal,
setHelpLineVertical,
} = useStore.getState()
e.stopPropagation() e.stopPropagation()
const nodes = getNodes() const nodes = getNodes()
// const showVerticalHelpLineNodes = nodes.filter((n) => { const showHorizontalHelpLineNodes = nodes.filter((n) => {
// if ( if (n.id === node.id)
// n.position.x === node.position.x return false
// || n.position.x + n.width! === node.position.x
// || n.position.x === node.position.x + node.width! const nY = Math.ceil(n.position.y)
// ) const nodeY = Math.ceil(node.position.y)
// return true
if (nY - nodeY < 5 && nY - nodeY > -5)
// return false return true
// })
// const showHorizontalHelpLineNodes = nodes.filter((n) => { return false
// if ( }).sort((a, b) => a.position.x - b.position.x)
// n.position.y === node.position.y const showHorizontalHelpLineNodesLength = showHorizontalHelpLineNodes.length
// || n.position.y === node.position.y + node.height! if (showHorizontalHelpLineNodesLength > 0) {
// || n.position.y + n.height! === node.position.y const first = showHorizontalHelpLineNodes[0]
// || n.position.y + n.height! === node.position.y + node.height! const last = showHorizontalHelpLineNodes[showHorizontalHelpLineNodesLength - 1]
// )
// return true const helpLine = {
top: first.position.y,
// return false 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 newNodes = produce(nodes, (draft) => {
const currentNode = draft.find(n => n.id === node.id)! 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) setNodes(newNodes)
...@@ -177,10 +236,12 @@ export const useWorkflow = () => { ...@@ -177,10 +236,12 @@ export const useWorkflow = () => {
const handleNodeDragStop = useCallback<NodeDragHandler>(() => { const handleNodeDragStop = useCallback<NodeDragHandler>(() => {
const { const {
setIsDragging, setIsDragging,
setHelpLine, setHelpLineHorizontal,
setHelpLineVertical,
} = useStore.getState() } = useStore.getState()
setIsDragging(false) setIsDragging(false)
setHelpLine() setHelpLineHorizontal()
setHelpLineVertical()
handleSyncWorkflowDraft() handleSyncWorkflowDraft()
}, [handleSyncWorkflowDraft]) }, [handleSyncWorkflowDraft])
......
import { create } from 'zustand' import { create } from 'zustand'
import type { HelpLinePosition } from './help-line/types' import type {
HelpLineHorizontalPosition,
HelpLineVerticalPosition,
} from './help-line/types'
import type { import type {
CollectionWithExpanded, CollectionWithExpanded,
ToolInWorkflow, ToolInWorkflow,
...@@ -13,7 +16,8 @@ type State = { ...@@ -13,7 +16,8 @@ type State = {
showRunHistory: boolean showRunHistory: boolean
showFeaturesPanel: boolean showFeaturesPanel: boolean
isDragging: boolean isDragging: boolean
helpLine?: HelpLinePosition helpLineHorizontal?: HelpLineHorizontalPosition
helpLineVertical?: HelpLineVerticalPosition
toolsets: CollectionWithExpanded[] toolsets: CollectionWithExpanded[]
toolsMap: ToolsMap toolsMap: ToolsMap
draftUpdatedAt: number draftUpdatedAt: number
...@@ -26,7 +30,8 @@ type Action = { ...@@ -26,7 +30,8 @@ type Action = {
setShowRunHistory: (showRunHistory: boolean) => void setShowRunHistory: (showRunHistory: boolean) => void
setShowFeaturesPanel: (showFeaturesPanel: boolean) => void setShowFeaturesPanel: (showFeaturesPanel: boolean) => void
setIsDragging: (isDragging: boolean) => void setIsDragging: (isDragging: boolean) => void
setHelpLine: (helpLine?: HelpLinePosition) => void setHelpLineHorizontal: (helpLineHorizontal?: HelpLineHorizontalPosition) => void
setHelpLineVertical: (helpLineVertical?: HelpLineVerticalPosition) => void
setToolsets: (toolsets: CollectionWithExpanded[]) => void setToolsets: (toolsets: CollectionWithExpanded[]) => void
setToolsMap: (toolsMap: Record<string, ToolInWorkflow[]>) => void setToolsMap: (toolsMap: Record<string, ToolInWorkflow[]>) => void
setDraftUpdatedAt: (draftUpdatedAt: number) => void setDraftUpdatedAt: (draftUpdatedAt: number) => void
...@@ -44,8 +49,10 @@ export const useStore = create<State & Action>(set => ({ ...@@ -44,8 +49,10 @@ export const useStore = create<State & Action>(set => ({
setShowFeaturesPanel: showFeaturesPanel => set(() => ({ showFeaturesPanel })), setShowFeaturesPanel: showFeaturesPanel => set(() => ({ showFeaturesPanel })),
isDragging: false, isDragging: false,
setIsDragging: isDragging => set(() => ({ isDragging })), setIsDragging: isDragging => set(() => ({ isDragging })),
helpLine: undefined, helpLineHorizontal: undefined,
setHelpLine: helpLine => set(() => ({ helpLine })), setHelpLineHorizontal: helpLineHorizontal => set(() => ({ helpLineHorizontal })),
helpLineVertical: undefined,
setHelpLineVertical: helpLineVertical => set(() => ({ helpLineVertical })),
toolsets: [], toolsets: [],
setToolsets: toolsets => set(() => ({ toolsets })), setToolsets: toolsets => set(() => ({ toolsets })),
toolsMap: {}, toolsMap: {},
......
...@@ -31,7 +31,7 @@ export type CommonNodeType<T = {}> = { ...@@ -31,7 +31,7 @@ export type CommonNodeType<T = {}> = {
title: string title: string
desc: string desc: string
type: BlockEnum type: BlockEnum
} & T & Partial<Pick<ToolDefaultValue, 'provider_id' | 'provider_type' | 'tool_name'>> } & T & Partial<Pick<ToolDefaultValue, 'provider_id' | 'provider_type' | 'provider_name' | 'tool_name'>>
export type CommonEdgeType = { export type CommonEdgeType = {
_hovering: boolean _hovering: boolean
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment