mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 20:48:01 +08:00
help line
This commit is contained in:
parent
f51f4a5843
commit
2b475b7916
@ -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> = ({
|
|||||||
>
|
>
|
||||||
<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'
|
|||||||
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> = ({
|
|||||||
|
|
||||||
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 = ({
|
|||||||
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[]>
|
|||||||
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'
|
|||||||
|
|
||||||
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 = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div>
|
<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 />
|
mode === Mode.Editing && !runTaskId && <EditingTitle />
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,37 +1,72 @@
|
|||||||
|
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)
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
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 = () => {
|
|||||||
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!
|
|
||||||
// )
|
|
||||||
// return true
|
|
||||||
|
|
||||||
// return false
|
const nY = Math.ceil(n.position.y)
|
||||||
// })
|
const nodeY = Math.ceil(node.position.y)
|
||||||
// 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
|
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 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 = () => {
|
|||||||
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])
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
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 = {
|
|||||||
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 = {
|
|||||||
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 => ({
|
|||||||
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 = {}> = {
|
|||||||
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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user