Commit 2b475b79 authored by StyleZhang's avatar StyleZhang

help line

parent f51f4a58
......@@ -49,6 +49,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
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<NodeSelectorProps> = ({
>
<SearchLg className='shrink-0 ml-[1px] mr-[5px] w-3.5 h-3.5 text-gray-400' />
<input
value={searchText}
className='grow px-0.5 py-[7px] text-[13px] bg-transparent appearance-none outline-none'
placeholder={t('workflow.tabs.searchBlock') || ''}
onChange={e => setSearchText(e.target.value)}
/>
</div>
</div>
<Tabs onSelect={handleSelect} />
<Tabs
onSelect={handleSelect}
searchText={searchText}
/>
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
......
......@@ -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<TabsProps> = ({
searchText,
onSelect,
}) => {
const { t } = useTranslation()
......@@ -31,14 +33,16 @@ const Tabs: FC<TabsProps> = ({
return (
<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 => (
<div
key={tab.key}
className={`
mr-4 text-[13px] font-medium cursor-pointer
${activeTab === tab.key ? 'text-gray-700' : 'text-gray-500'}
relative mr-4 h-[34px] leading-[34px] text-[13px] font-medium cursor-pointer
${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)}
>
......
......@@ -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],
})}
......
......@@ -28,6 +28,7 @@ export type ToolsMap = Record<string, ToolInWorkflow[]>
export type ToolDefaultValue = {
provider_id: string
provider_type: string
provider_name: string
tool_name: string
title: string
}
......@@ -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 = () => {
}}
>
<div>
<div className='text-xs font-medium text-gray-700'>{appDetail?.name}</div>
{
appSidebarExpand && (
<div className='text-xs font-medium text-gray-700'>{appDetail?.name}</div>
)
}
{
mode === Mode.Editing && !runTaskId && <EditingTitle />
}
......
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 (
<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 (
<div
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 = useStore(state => state.helpLine)
const helpLineHorizontal = useStore(s => s.helpLineHorizontal)
const helpLineVertical = useStore(s => s.helpLineVertical)
if (!helpLineHorizontal && !helpLineVertical)
return null
return (
<>
{
helpLine?.bottom && (
<HelpLineBase {...helpLine} />
helpLineHorizontal && (
<HelpLineHorizontal {...helpLineHorizontal} />
)
}
{
helpLine?.right && (
<HelpLineBase {...helpLine} />
helpLineVertical && (
<HelpLineVertical {...helpLineVertical} />
)
}
</>
)
}
export default HelpLine
export default memo(HelpLine)
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
}
......@@ -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
// 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
// return false
// })
const showHorizontalHelpLineNodes = nodes.filter((n) => {
if (n.id === node.id)
return false
const nY = Math.ceil(n.position.y)
const nodeY = Math.ceil(node.position.y)
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<NodeDragHandler>(() => {
const {
setIsDragging,
setHelpLine,
setHelpLineHorizontal,
setHelpLineVertical,
} = useStore.getState()
setIsDragging(false)
setHelpLine()
setHelpLineHorizontal()
setHelpLineVertical()
handleSyncWorkflowDraft()
}, [handleSyncWorkflowDraft])
......
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<string, ToolInWorkflow[]>) => void
setDraftUpdatedAt: (draftUpdatedAt: number) => void
......@@ -44,8 +49,10 @@ export const useStore = create<State & Action>(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: {},
......
......@@ -31,7 +31,7 @@ export type CommonNodeType<T = {}> = {
title: string
desc: string
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 = {
_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