mirror of https://github.com/langgenius/dify.git
fix
This commit is contained in:
parent
30ea3cb702
commit
90e013554c
|
|
@ -743,6 +743,84 @@ export const useWorkflow = () => {
|
|||
setNodes(newNodes)
|
||||
}, [store])
|
||||
|
||||
const getTreeLeafNodes = useCallback(() => {
|
||||
const {
|
||||
getNodes,
|
||||
edges,
|
||||
} = store.getState()
|
||||
const nodes = getNodes()
|
||||
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
|
||||
|
||||
if (!startNode)
|
||||
return []
|
||||
|
||||
const list: Node[] = []
|
||||
const preOrder = (root: Node, callback: (node: Node) => void) => {
|
||||
const outgoers = getOutgoers(root, nodes, edges)
|
||||
|
||||
if (outgoers.length) {
|
||||
outgoers.forEach((outgoer) => {
|
||||
preOrder(outgoer, callback)
|
||||
})
|
||||
}
|
||||
else {
|
||||
callback(root)
|
||||
}
|
||||
}
|
||||
preOrder(startNode, (node) => {
|
||||
list.push(node)
|
||||
})
|
||||
|
||||
return list.filter((item) => {
|
||||
if (item.data.type === BlockEnum.IfElse)
|
||||
return false
|
||||
|
||||
if (item.data.type === BlockEnum.QuestionClassifier)
|
||||
return false
|
||||
|
||||
return true
|
||||
})
|
||||
}, [store])
|
||||
|
||||
const getBeforeNodesInSameBranch = useCallback((nodeId: string) => {
|
||||
const {
|
||||
getNodes,
|
||||
edges,
|
||||
} = store.getState()
|
||||
const nodes = getNodes()
|
||||
const currentNode = nodes.find(node => node.id === nodeId)!
|
||||
const list: Node[] = []
|
||||
|
||||
const traverse = (root: Node, callback: (node: Node) => void) => {
|
||||
const incomers = getIncomers(root, nodes, edges)
|
||||
|
||||
if (incomers.length) {
|
||||
incomers.forEach((node) => {
|
||||
callback(node)
|
||||
traverse(node, callback)
|
||||
})
|
||||
}
|
||||
}
|
||||
traverse(currentNode, (node) => {
|
||||
list.push(node)
|
||||
})
|
||||
|
||||
const length = list.length
|
||||
if (length && list.some(item => item.data.type === BlockEnum.Start)) {
|
||||
return list.reverse().filter((item) => {
|
||||
if (item.data.type === BlockEnum.IfElse)
|
||||
return false
|
||||
|
||||
if (item.data.type === BlockEnum.QuestionClassifier)
|
||||
return false
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
return []
|
||||
}, [store])
|
||||
|
||||
return {
|
||||
handleSyncWorkflowDraft,
|
||||
handleLayout,
|
||||
|
|
@ -769,6 +847,8 @@ export const useWorkflow = () => {
|
|||
handleEdgesChange,
|
||||
|
||||
handleRunInit,
|
||||
getTreeLeafNodes,
|
||||
getBeforeNodesInSameBranch,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -121,16 +121,18 @@ const Workflow: FC<WorkflowProps> = memo(({
|
|||
onEdgeMouseEnter={handleEdgeEnter}
|
||||
onEdgeMouseLeave={handleEdgeLeave}
|
||||
onEdgesChange={handleEdgesChange}
|
||||
multiSelectionKeyCode={null}
|
||||
connectionLineComponent={CustomConnectionLine}
|
||||
deleteKeyCode={null}
|
||||
nodeDragThreshold={1}
|
||||
defaultViewport={viewport}
|
||||
multiSelectionKeyCode={null}
|
||||
deleteKeyCode={null}
|
||||
panOnDrag={!runningStatus}
|
||||
nodesDraggable={!runningStatus}
|
||||
nodesConnectable={!runningStatus}
|
||||
nodesFocusable={!runningStatus}
|
||||
edgesFocusable={!runningStatus}
|
||||
zoomOnPinch={!runningStatus}
|
||||
zoomOnScroll={!runningStatus}
|
||||
zoomOnDoubleClick={!runningStatus}
|
||||
>
|
||||
<Background
|
||||
gap={[14, 14]}
|
||||
|
|
@ -204,7 +206,7 @@ const WorkflowWrap: FC<WorkflowProps> = ({
|
|||
handleFetchCollectionList()
|
||||
}, [])
|
||||
|
||||
if (error && !error.bodyUsed && appDetail) {
|
||||
if (error && error.json && !error.bodyUsed && appDetail) {
|
||||
error.json().then((err: any) => {
|
||||
if (err.code === 'draft_workflow_not_exist') {
|
||||
syncWorkflowDraft({
|
||||
|
|
|
|||
|
|
@ -1,12 +1,22 @@
|
|||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { MiniMap } from 'reactflow'
|
||||
import { useWorkflow } from '../hooks'
|
||||
import { useStore } from '../store'
|
||||
import ZoomInOut from './zoom-in-out'
|
||||
import { OrganizeGrid } from '@/app/components/base/icons/src/vender/line/layout'
|
||||
import TooltipPlus from '@/app/components/base/tooltip-plus'
|
||||
|
||||
const Operator = () => {
|
||||
const { t } = useTranslation()
|
||||
const runningStatus = useStore(s => s.runningStatus)
|
||||
const { handleLayout } = useWorkflow()
|
||||
|
||||
const goLayout = () => {
|
||||
if (runningStatus)
|
||||
return
|
||||
handleLayout()
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`
|
||||
|
|
@ -22,7 +32,13 @@ const Operator = () => {
|
|||
<div className='flex items-center mt-1 p-0.5 rounded-lg border-[0.5px] border-gray-100 bg-white shadow-lg text-gray-500'>
|
||||
<ZoomInOut />
|
||||
<TooltipPlus popupContent={t('workflow.panel.organizeBlocks')}>
|
||||
<div className='ml-[1px] flex items-center justify-center w-8 h-8 cursor-pointer hover:bg-black/5 rounded-lg'>
|
||||
<div
|
||||
className={`
|
||||
ml-[1px] flex items-center justify-center w-8 h-8 cursor-pointer hover:bg-black/5 rounded-lg
|
||||
${runningStatus && '!cursor-not-allowed'}
|
||||
`}
|
||||
onClick={goLayout}
|
||||
>
|
||||
<OrganizeGrid className='w-4 h-4' />
|
||||
</div>
|
||||
</TooltipPlus>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import type { FC } from 'react'
|
|||
import {
|
||||
Fragment,
|
||||
memo,
|
||||
useCallback,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
|
@ -10,6 +11,7 @@ import {
|
|||
useViewport,
|
||||
} from 'reactflow'
|
||||
import { useWorkflow } from '../hooks'
|
||||
import { useStore } from '../store'
|
||||
import {
|
||||
PortalToFollowElem,
|
||||
PortalToFollowElemContent,
|
||||
|
|
@ -29,6 +31,7 @@ const ZoomInOut: FC = () => {
|
|||
const { zoom } = useViewport()
|
||||
const { handleSyncWorkflowDraft } = useWorkflow()
|
||||
const [open, setOpen] = useState(false)
|
||||
const runningStatus = useStore(s => s.runningStatus)
|
||||
|
||||
const ZOOM_IN_OUT_OPTIONS = [
|
||||
[
|
||||
|
|
@ -60,6 +63,8 @@ const ZoomInOut: FC = () => {
|
|||
]
|
||||
|
||||
const handleZoom = (type: string) => {
|
||||
if (runningStatus)
|
||||
return
|
||||
if (type === 'in')
|
||||
zoomIn()
|
||||
|
||||
|
|
@ -78,6 +83,12 @@ const ZoomInOut: FC = () => {
|
|||
handleSyncWorkflowDraft()
|
||||
}
|
||||
|
||||
const handleTrigger = useCallback(() => {
|
||||
if (runningStatus)
|
||||
return
|
||||
setOpen(v => !v)
|
||||
}, [runningStatus])
|
||||
|
||||
return (
|
||||
<PortalToFollowElem
|
||||
placement='top-start'
|
||||
|
|
@ -85,10 +96,11 @@ const ZoomInOut: FC = () => {
|
|||
onOpenChange={setOpen}
|
||||
offset={4}
|
||||
>
|
||||
<PortalToFollowElemTrigger asChild onClick={() => setOpen(v => !v)}>
|
||||
<PortalToFollowElemTrigger asChild onClick={handleTrigger}>
|
||||
<div className={`
|
||||
flex items-center px-2 h-8 cursor-pointer text-[13px] hover:bg-gray-50 rounded-lg
|
||||
${open && 'bg-gray-50'}
|
||||
${runningStatus && '!cursor-not-allowed'}
|
||||
`}>
|
||||
<SearchLg className='mr-1 w-4 h-4' />
|
||||
<div className='w-[34px]'>{parseFloat(`${zoom * 100}`).toFixed(0)}%</div>
|
||||
|
|
|
|||
|
|
@ -170,58 +170,3 @@ export const canRunBySingle = (nodeType: BlockEnum) => {
|
|||
|| nodeType === BlockEnum.HttpRequest
|
||||
|| nodeType === BlockEnum.Tool
|
||||
}
|
||||
|
||||
export const getTreeLeafNodes = (nodes: Node[], edges: Edge[]) => {
|
||||
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
|
||||
|
||||
if (!startNode)
|
||||
return []
|
||||
|
||||
const list: Node[] = []
|
||||
const preOrder = (root: Node, callback: (node: Node) => void) => {
|
||||
const outgoers = getOutgoers(root, nodes, edges)
|
||||
|
||||
if (outgoers.length) {
|
||||
outgoers.forEach((outgoer) => {
|
||||
preOrder(outgoer, callback)
|
||||
})
|
||||
}
|
||||
else {
|
||||
callback(root)
|
||||
}
|
||||
}
|
||||
preOrder(startNode, (node) => {
|
||||
list.push(node)
|
||||
})
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
export const getBeforeNodesInSameBranch = (nodeId: string, targetHandle: string, nodes: Node[], edges: Edge[]) => {
|
||||
const currentNode = nodes.find(node => node.id === nodeId)!
|
||||
const list: Node[] = []
|
||||
|
||||
const traverse = (root: Node, callback: (node: Node) => void) => {
|
||||
const connectedEdges = getConnectedEdges([root], edges)
|
||||
const sourceEdge = connectedEdges.filter(edge => edge.targetHandle === targetHandle)
|
||||
const sourceEdgeLength = sourceEdge.length
|
||||
|
||||
if (sourceEdgeLength === 1) {
|
||||
const before = nodes.find(node => node.id === sourceEdge[0].source)
|
||||
|
||||
if (before) {
|
||||
callback(before)
|
||||
traverse(before, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
traverse(currentNode, (node) => {
|
||||
list.push(node)
|
||||
})
|
||||
|
||||
const length = list.length
|
||||
if (length && list[length - 1].data.type === BlockEnum.Start)
|
||||
return list.reverse()
|
||||
|
||||
return []
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue