Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
12d7ba5d
authored
Sep 26, 2024
by
heheer
Committed by
GitHub
Sep 26, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: support workflow node fold (#2797)
* feat: support workflow node fold * fix * fix
parent
5ad8c81e
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
177 additions
and
82 deletions
+177
-82
packages/global/core/workflow/type/node.d.ts
+1
-0
packages/web/components/common/Icon/constants.ts
+1
-0
packages/web/components/common/Icon/icons/core/chat/chevronRight.svg
+4
-0
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/ButtonEdge.tsx
+53
-37
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/FlowController.tsx
+29
-4
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx
+18
-5
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoop.tsx
+9
-9
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoopStart.tsx
+2
-4
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeUserSelect.tsx
+0
-5
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx
+9
-4
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/index.tsx
+3
-3
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx
+40
-7
projects/app/src/pages/app/detail/components/WorkflowComponents/context.tsx
+2
-2
projects/app/src/pages/app/detail/components/WorkflowComponents/utils.tsx
+4
-1
projects/app/src/web/core/workflow/utils.ts
+2
-1
No files found.
packages/global/core/workflow/type/node.d.ts
View file @
12d7ba5d
...
...
@@ -104,6 +104,7 @@ export type FlowNodeItemType = FlowNodeTemplateType & {
response
?:
ChatHistoryItemResType
;
isExpired
?:
boolean
;
};
isFolded
?:
boolean
;
};
// store node type
...
...
packages/web/components/common/Icon/constants.ts
View file @
12d7ba5d
...
...
@@ -123,6 +123,7 @@ export const iconPaths = {
'core/chat/chatLight'
:
()
=>
import
(
'./icons/core/chat/chatLight.svg'
),
'core/chat/chatModelTag'
:
()
=>
import
(
'./icons/core/chat/chatModelTag.svg'
),
'core/chat/chevronDown'
:
()
=>
import
(
'./icons/core/chat/chevronDown.svg'
),
'core/chat/chevronRight'
:
()
=>
import
(
'./icons/core/chat/chevronRight.svg'
),
'core/chat/chevronSelector'
:
()
=>
import
(
'./icons/core/chat/chevronSelector.svg'
),
'core/chat/chevronUp'
:
()
=>
import
(
'./icons/core/chat/chevronUp.svg'
),
'core/chat/export/pdf'
:
()
=>
import
(
'./icons/core/chat/export/pdf.svg'
),
...
...
packages/web/components/common/Icon/icons/core/chat/chevronRight.svg
0 → 100644
View file @
12d7ba5d
<svg
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 25 24"
fill=
"none"
>
<path
fill-rule=
"evenodd"
clip-rule=
"evenodd"
d=
"M9.19277 5.29289C8.80224 5.68342 8.80224 6.31658 9.19277 6.70711L14.4857 12L9.19277 17.2929C8.80224 17.6834 8.80224 18.3166 9.19277 18.7071C9.58329 19.0976 10.2165 19.0976 10.607 18.7071L16.607 12.7071C16.9975 12.3166 16.9975 11.6834 16.607 11.2929L10.607 5.29289C10.2165 4.90237 9.58329 4.90237 9.19277 5.29289Z"
/>
</svg>
\ No newline at end of file
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/ButtonEdge.tsx
View file @
12d7ba5d
import
React
,
{
useCallback
,
useMemo
}
from
'react'
;
import
{
BezierEdge
,
getBezierPath
,
EdgeLabelRenderer
,
EdgeProps
}
from
'reactflow'
;
import
{
Flex
}
from
'@chakra-ui/react'
;
import
{
Box
,
Flex
}
from
'@chakra-ui/react'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
import
{
NodeOutputKeyEnum
,
RuntimeEdgeStatusEnum
}
from
'@fastgpt/global/core/workflow/constants'
;
import
{
useContextSelector
}
from
'use-context-selector'
;
...
...
@@ -27,6 +27,16 @@ const ButtonEdge = (props: EdgeProps) => {
targetHandleId
,
style
}
=
props
;
const
parentNode
=
useMemo
(()
=>
{
for
(
const
node
of
nodeList
)
{
if
((
node
.
nodeId
===
source
||
node
.
nodeId
===
target
)
&&
node
.
parentNodeId
)
{
return
nodeList
.
find
((
parent
)
=>
parent
.
nodeId
===
node
.
parentNodeId
);
}
}
return
undefined
;
},
[
nodeList
,
source
,
target
]);
const
defaultZIndex
=
useMemo
(
()
=>
(
nodeList
.
find
((
node
)
=>
node
.
nodeId
===
source
&&
node
.
parentNodeId
)
?
1001
:
0
),
[
nodeList
,
source
]
...
...
@@ -127,55 +137,59 @@ const ButtonEdge = (props: EdgeProps) => {
})();
return
(
<
EdgeLabelRenderer
>
<
Flex
display=
{
isHover
||
highlightEdge
?
'flex'
:
'none'
}
alignItems=
{
'center'
}
justifyContent=
{
'center'
}
position=
{
'absolute'
}
transform=
{
`translate(-55%, -50%) translate(${labelX}px,${labelY}px)`
}
pointerEvents=
{
'all'
}
w=
{
'17px'
}
h=
{
'17px'
}
bg=
{
'white'
}
borderRadius=
{
'17px'
}
cursor=
{
'pointer'
}
zIndex=
{
9999
}
onClick=
{
()
=>
onDelConnect
(
id
)
}
>
<
MyIcon
name=
{
'core/workflow/closeEdge'
}
w=
{
'100%'
}
></
MyIcon
>
</
Flex
>
{
!
isToolEdge
&&
(
<
Box
hidden=
{
parentNode
?.
isFolded
}
>
<
Flex
display=
{
isHover
||
highlightEdge
?
'flex'
:
'none'
}
alignItems=
{
'center'
}
justifyContent=
{
'center'
}
position=
{
'absolute'
}
transform=
{
arrowTransform
}
transform=
{
`translate(-55%, -50%) translate(${labelX}px,${labelY}px)`
}
pointerEvents=
{
'all'
}
w=
{
highlightEdge
?
'14px'
:
'10px'
}
h=
{
highlightEdge
?
'14px'
:
'10px'
}
// bg=
{'
white
'}
zIndex=
{
highlightEdge
?
1000
:
defaultZIndex
}
w=
{
'17px'
}
h=
{
'17px'
}
bg=
{
'white'
}
borderRadius=
{
'17px'
}
cursor=
{
'pointer'
}
zIndex=
{
9999
}
onClick=
{
()
=>
onDelConnect
(
id
)
}
>
<
MyIcon
name=
{
'core/workflow/edgeArrow'
}
w=
{
'100%'
}
color=
{
edgeColor
}
{
...
(
highlightEdge
?
{
fontWeight
:
'
bold
'
}
:
{})}
></
MyIcon
>
<
MyIcon
name=
{
'core/workflow/closeEdge'
}
w=
{
'100%'
}
></
MyIcon
>
</
Flex
>
)
}
{
!
isToolEdge
&&
(
<
Flex
alignItems=
{
'center'
}
justifyContent=
{
'center'
}
position=
{
'absolute'
}
transform=
{
arrowTransform
}
pointerEvents=
{
'all'
}
w=
{
highlightEdge
?
'14px'
:
'10px'
}
h=
{
highlightEdge
?
'14px'
:
'10px'
}
// bg=
{'
white
'}
zIndex=
{
highlightEdge
?
1000
:
defaultZIndex
}
>
<
MyIcon
name=
{
'core/workflow/edgeArrow'
}
w=
{
'100%'
}
color=
{
edgeColor
}
{
...
(
highlightEdge
?
{
fontWeight
:
'
bold
'
}
:
{})}
></
MyIcon
>
</
Flex
>
)
}
</
Box
>
</
EdgeLabelRenderer
>
);
},
[
parentNode
?.
isFolded
,
isHover
,
highlightEdge
,
labelX
,
labelY
,
isToolEdge
,
defaultZIndex
,
edgeColor
,
targetPosition
,
newTargetX
,
...
...
@@ -214,7 +228,8 @@ const ButtonEdge = (props: EdgeProps) => {
targetY=
{
newTargetY
}
style=
{
{
...
edgeStyle
,
stroke
:
edgeColor
stroke
:
edgeColor
,
display
:
parentNode
?.
isFolded
?
'none'
:
'block'
}
}
/>
);
...
...
@@ -227,7 +242,8 @@ const ButtonEdge = (props: EdgeProps) => {
source
,
target
,
style
,
highlightEdge
highlightEdge
,
parentNode
?.
isFolded
]);
return
(
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/FlowController.tsx
View file @
12d7ba5d
import
React
,
{
useMemo
}
from
'react'
;
import
{
Background
,
ControlButton
,
MiniMap
,
Panel
,
useReactFlow
,
useViewport
}
from
'reactflow'
;
import
React
,
{
useCallback
,
useMemo
}
from
'react'
;
import
{
Background
,
ControlButton
,
MiniMap
,
MiniMapNodeProps
,
Panel
,
useReactFlow
,
useViewport
}
from
'reactflow'
;
import
{
useContextSelector
}
from
'use-context-selector'
;
import
{
WorkflowContext
}
from
'../../context'
;
import
MyTooltip
from
'@fastgpt/web/components/common/MyTooltip'
;
...
...
@@ -26,7 +34,8 @@ const FlowController = React.memo(function FlowController() {
canUndo
,
workflowControlMode
,
setWorkflowControlMode
,
mouseInCanvas
mouseInCanvas
,
nodeList
}
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
);
const
{
t
}
=
useTranslation
();
...
...
@@ -52,6 +61,20 @@ const FlowController = React.memo(function FlowController() {
zoomOut
();
});
const
MiniMapNode
=
useCallback
(
({
x
,
y
,
width
,
height
,
color
,
id
}:
MiniMapNodeProps
)
=>
{
const
node
=
nodeList
.
find
((
node
)
=>
node
.
nodeId
===
id
);
const
parentNode
=
nodeList
.
find
((
n
)
=>
n
.
nodeId
===
node
?.
parentNodeId
);
if
(
parentNode
?.
isFolded
)
{
return
null
;
}
return
<
rect
x=
{
x
}
y=
{
y
}
width=
{
width
}
height=
{
height
}
fill=
{
color
}
/>;
},
[
nodeList
]
);
const
Render
=
useMemo
(()
=>
{
return
(
<>
...
...
@@ -64,6 +87,7 @@ const FlowController = React.memo(function FlowController() {
boxShadow
:
'0px 0px 1px rgba(19, 51, 107, 0.10), 0px 4px 10px rgba(19, 51, 107, 0.10)'
}
}
pannable
nodeComponent=
{
MiniMapNode
}
/>
<
Panel
position=
{
'bottom-right'
}
...
...
@@ -180,9 +204,10 @@ const FlowController = React.memo(function FlowController() {
</>
);
},
[
MiniMapNode
,
workflowControlMode
,
isMac
,
t
,
isMac
,
undo
,
canUndo
,
redo
,
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx
View file @
12d7ba5d
...
...
@@ -13,7 +13,8 @@ import {
getNodesBounds
,
Rect
,
NodeRemoveChange
,
NodeSelectionChange
NodeSelectionChange
,
Position
}
from
'reactflow'
;
import
{
EDGE_TYPE
,
FlowNodeTypeEnum
}
from
'@fastgpt/global/core/workflow/node/constant'
;
import
'reactflow/dist/style.css'
;
...
...
@@ -30,6 +31,8 @@ import {
Input_Template_Node_Width
}
from
'@fastgpt/global/core/workflow/template/input'
;
import
{
FlowNodeItemType
}
from
'@fastgpt/global/core/workflow/type/node'
;
import
{
getHandleId
}
from
'@fastgpt/global/core/workflow/utils'
;
import
{
IfElseResultEnum
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/constant'
;
/*
Compute helper lines for snapping nodes to each other
...
...
@@ -367,8 +370,8 @@ export const useWorkflow = () => {
const
checkNodeOverLoopNode
=
useMemoizedFn
((
node
:
Node
)
=>
{
if
(
!
node
)
return
;
// 获取所有与当前节点相交的节点
const
intersections
=
getIntersectingNodes
(
node
);
// 获取所有与当前节点相交的节点
,不包含折叠的节点
const
intersections
=
getIntersectingNodes
(
node
)
.
filter
((
node
)
=>
!
node
.
data
.
isFolded
)
;
// 获取所有与当前节点相交的节点中,类型为 loop 的节点
const
parentNode
=
intersections
.
find
((
item
)
=>
item
.
type
===
FlowNodeTypeEnum
.
loop
);
...
...
@@ -544,9 +547,19 @@ export const useWorkflow = () => {
/* connect */
const
onConnectStart
=
useCallback
(
(
event
:
any
,
params
:
OnConnectStartParams
)
=>
{
if
(
!
params
.
nodeId
)
return
;
const
sourceNode
=
nodes
.
find
((
node
)
=>
node
.
id
===
params
.
nodeId
);
if
(
sourceNode
?.
data
.
isFolded
)
{
return
onChangeNode
({
nodeId
:
params
.
nodeId
,
type
:
'attr'
,
key
:
'isFolded'
,
value
:
false
});
}
setConnectingEdge
(
params
);
},
[
setConnectingEdg
e
]
[
nodes
,
setConnectingEdge
,
onChangeNod
e
]
);
const
onConnectEnd
=
useCallback
(()
=>
{
setConnectingEdge
(
undefined
);
...
...
@@ -581,7 +594,7 @@ export const useWorkflow = () => {
connect
});
},
[
onConnect
,
t
,
toast
]
[
onConnect
,
t
,
toast
,
nodes
]
);
/* edge */
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoop.tsx
View file @
12d7ba5d
...
...
@@ -22,7 +22,7 @@ import { WorkflowContext } from '../../../context';
const
NodeLoop
=
({
data
,
selected
}:
NodeProps
<
FlowNodeItemType
>
)
=>
{
const
{
t
}
=
useTranslation
();
const
{
nodeId
,
inputs
,
outputs
}
=
data
;
const
{
nodeId
,
inputs
,
outputs
,
isFolded
}
=
data
;
const
{
onChangeNode
,
nodeList
}
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
);
const
{
nodeWidth
,
nodeHeight
}
=
useMemo
(()
=>
{
...
...
@@ -53,14 +53,14 @@ const NodeLoop = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
return
(
<
NodeCard
selected=
{
selected
}
maxW=
{
'full'
}
minW=
{
900
}
minH=
{
900
}
w=
{
nodeWidth
}
h=
{
nodeHeight
}
menuForbid=
{
{
copy
:
true
}
}
maxW=
"full"
{
...
(!
isFolded
&&
{
minW
:
'900
px
',
minH
:
'900
px
',
w
:
nodeWidth
,
h
:
nodeHeight
})}
menuForbid=
{
{
copy
:
true
}
}
{
...
data
}
>
<
Container
position=
{
'relative'
}
flex=
{
1
}
>
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/Loop/NodeLoopStart.tsx
View file @
12d7ba5d
...
...
@@ -94,17 +94,15 @@ const NodeLoopStart = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
<
NodeCard
selected=
{
selected
}
{
...
data
}
w=
{
'420px'
}
h=
{
'176px'
}
menuForbid=
{
{
copy
:
true
,
delete
:
true
,
debug
:
true
}
}
>
<
Box
px=
{
4
}
>
<
Box
px=
{
4
}
w=
{
'420px'
}
h=
{
'116px'
}
>
{
!
loopItemInputType
?
(
<
EmptyTip
text=
{
t
(
'workflow:loop_start_tip'
)
}
py=
{
0
}
mt=
{
0
}
iconSize=
{
'32px'
}
/>
<
EmptyTip
text=
{
t
(
'workflow:loop_start_tip'
)
}
py=
{
0
}
mt=
{
4
}
iconSize=
{
'32px'
}
/>
)
:
(
<
Box
bg=
{
'white'
}
borderRadius=
{
'md'
}
overflow=
{
'hidden'
}
border=
{
'base'
}
>
<
TableContainer
>
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeUserSelect.tsx
View file @
12d7ba5d
...
...
@@ -56,11 +56,6 @@ const NodeUserSelect = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
value
:
options
.
filter
((
input
)
=>
input
.
key
!==
item
.
key
)
}
});
onChangeNode
({
nodeId
,
type
:
'delOutput'
,
key
:
item
.
key
});
}
}
/>
</
MyTooltip
>
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ConnectionHandle.tsx
View file @
12d7ba5d
...
...
@@ -6,7 +6,13 @@ import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import
{
useContextSelector
}
from
'use-context-selector'
;
import
{
WorkflowContext
}
from
'../../../../context'
;
export
const
ConnectionSourceHandle
=
({
nodeId
}:
{
nodeId
:
string
})
=>
{
export
const
ConnectionSourceHandle
=
({
nodeId
,
isFoldNode
}:
{
nodeId
:
string
;
isFoldNode
?:
boolean
;
})
=>
{
const
connectingEdge
=
useContextSelector
(
WorkflowContext
,
(
ctx
)
=>
ctx
.
connectingEdge
);
const
nodeList
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
.
nodeList
);
const
edges
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
.
edges
);
...
...
@@ -26,8 +32,7 @@ export const ConnectionSourceHandle = ({ nodeId }: { nodeId: string }) => {
const
rightTargetConnected
=
edges
.
some
(
(
edge
)
=>
edge
.
targetHandle
===
getHandleId
(
nodeId
,
'target'
,
Position
.
Right
)
);
if
(
!
node
||
!
node
?.
sourceHandle
?.
right
||
rightTargetConnected
)
return
null
;
if
(
!
isFoldNode
&&
(
!
node
||
!
node
?.
sourceHandle
?.
right
||
rightTargetConnected
))
return
null
;
return
(
<
SourceHandle
...
...
@@ -102,7 +107,7 @@ export const ConnectionSourceHandle = ({ nodeId }: { nodeId: string }) => {
TopHandlee
,
BottomHandlee
};
},
[
connectingEdge
,
edges
,
nodeId
,
nodeList
]);
},
[
connectingEdge
,
edges
,
nodeId
,
nodeList
,
isFoldNode
]);
return
showSourceHandle
?
(
<>
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/index.tsx
View file @
12d7ba5d
...
...
@@ -32,8 +32,8 @@ const MySourceHandle = React.memo(function MySourceHandle({
const
node
=
useMemo
(()
=>
nodes
.
find
((
node
)
=>
node
.
data
.
nodeId
===
nodeId
),
[
nodes
,
nodeId
]);
const
connected
=
edges
.
some
((
edge
)
=>
edge
.
sourceHandle
===
handleId
);
const
nodeFolded
=
node
?.
data
.
isFolded
&&
edges
.
some
((
edge
)
=>
edge
.
source
===
nodeId
);
const
nodeIsHover
=
hoverNodeId
===
nodeId
;
const
active
=
useMemo
(
()
=>
nodeIsHover
||
node
?.
selected
||
connectingEdge
?.
handleId
===
handleId
,
[
nodeIsHover
,
node
?.
selected
,
connectingEdge
,
handleId
]
...
...
@@ -73,7 +73,7 @@ const MySourceHandle = React.memo(function MySourceHandle({
};
}
if
(
connected
)
{
if
(
connected
||
nodeFolded
)
{
return
{
styles
:
{
...
connectedStyle
,
...
...
@@ -89,7 +89,7 @@ const MySourceHandle = React.memo(function MySourceHandle({
styles
:
undefined
,
showAddIcon
:
false
};
},
[
active
,
connected
,
highlightStyle
,
translateStr
,
transform
,
connectedStyle
]);
},
[
active
,
connected
,
nodeFolded
,
highlightStyle
,
translateStr
,
transform
,
connectedStyle
]);
const
RenderHandle
=
useMemo
(()
=>
{
return
(
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx
View file @
12d7ba5d
import
React
,
{
useCallback
,
use
Effect
,
useMemo
,
useState
}
from
'react'
;
import
React
,
{
useCallback
,
use
Memo
}
from
'react'
;
import
{
Box
,
Button
,
Card
,
Flex
,
Image
}
from
'@chakra-ui/react'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
import
Avatar
from
'@fastgpt/web/components/common/Avatar'
;
...
...
@@ -61,7 +61,8 @@ const NodeCard = (props: Props) => {
menuForbid
,
isTool
=
false
,
isError
=
false
,
debugResult
debugResult
,
isFolded
}
=
props
;
const
nodeList
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
.
nodeList
);
...
...
@@ -81,7 +82,12 @@ const NodeCard = (props: Props) => {
[
isTool
,
nodeList
]
);
const
node
=
nodeList
.
find
((
node
)
=>
node
.
nodeId
===
nodeId
);
const
{
node
,
parentNode
}
=
useMemo
(()
=>
{
const
node
=
nodeList
.
find
((
node
)
=>
node
.
nodeId
===
nodeId
);
const
parentNode
=
nodeList
.
find
((
n
)
=>
n
.
nodeId
===
node
?.
parentNodeId
);
return
{
node
,
parentNode
};
},
[
nodeList
,
nodeId
]);
const
{
openConfirm
:
onOpenConfirmSync
,
ConfirmModal
:
ConfirmSyncModal
}
=
useConfirm
({
content
:
t
(
'app:module.Confirm Sync'
)
});
...
...
@@ -155,6 +161,31 @@ const NodeCard = (props: Props) => {
{
/* avatar and name */
}
<
Flex
alignItems=
{
'center'
}
>
<
Box
mr=
{
2
}
cursor=
{
'pointer'
}
rounded=
{
'sm'
}
_hover=
{
{
bg
:
'myGray.200'
}
}
onClick=
{
()
=>
{
onChangeNode
({
nodeId
,
type
:
'attr'
,
key
:
'isFolded'
,
value
:
!
isFolded
});
}
}
>
{
!
isFolded
?
(
<
MyIcon
name=
{
'core/chat/chevronDown'
}
w=
{
'24px'
}
h=
{
'24px'
}
color=
{
'myGray.500'
}
/>
)
:
(
<
MyIcon
name=
{
'core/chat/chevronRight'
}
w=
{
'24px'
}
h=
{
'24px'
}
color=
{
'myGray.500'
}
/>
)
}
</
Box
>
<
Avatar
src=
{
avatar
}
borderRadius=
{
'sm'
}
objectFit=
{
'contain'
}
w=
{
'30px'
}
h=
{
'30px'
}
/>
<
Box
ml=
{
3
}
fontSize=
{
'md'
}
fontWeight=
{
'medium'
}
>
{
t
(
name
as
any
)
}
...
...
@@ -250,19 +281,21 @@ const NodeCard = (props: Props) => {
ConfirmSyncModal
,
onOpenCustomTitleModal
,
onChangeNode
,
toast
toast
,
isFolded
]);
const
RenderHandle
=
useMemo
(()
=>
{
return
(
<>
<
ConnectionSourceHandle
nodeId=
{
nodeId
}
/>
<
ConnectionSourceHandle
nodeId=
{
nodeId
}
isFoldNode=
{
isFolded
}
/>
<
ConnectionTargetHandle
nodeId=
{
nodeId
}
/>
</>
);
},
[
nodeId
]);
},
[
nodeId
,
isFolded
]);
return
(
<
Flex
hidden=
{
parentNode
?.
isFolded
}
flexDirection=
{
'column'
}
minW=
{
minW
}
maxW=
{
maxW
}
...
...
@@ -298,7 +331,7 @@ const NodeCard = (props: Props) => {
>
<
NodeDebugResponse
nodeId=
{
nodeId
}
debugResult=
{
debugResult
}
/>
{
Header
}
{
children
}
{
!
isFolded
&&
children
}
{
RenderHandle
}
<
EditTitleModal
maxLength=
{
20
}
/>
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/context.tsx
View file @
12d7ba5d
...
...
@@ -561,9 +561,9 @@ const WorkflowContextProvider = ({
const
checkResults
=
checkWorkflowNodeAndConnection
({
nodes
,
edges
});
if
(
!
checkResults
)
{
const
store
Nodes
=
uiWorkflow2StoreWorkflow
({
nodes
,
edges
});
const
store
Workflow
=
uiWorkflow2StoreWorkflow
({
nodes
,
edges
});
return
store
Nodes
;
return
store
Workflow
;
}
else
if
(
!
hideTip
)
{
checkResults
.
forEach
((
nodeId
)
=>
onUpdateNodeError
(
nodeId
,
true
));
toast
({
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/utils.tsx
View file @
12d7ba5d
...
...
@@ -25,7 +25,8 @@ export const uiWorkflow2StoreWorkflow = ({
version
:
item
.
data
.
version
,
inputs
:
item
.
data
.
inputs
,
outputs
:
item
.
data
.
outputs
,
pluginId
:
item
.
data
.
pluginId
pluginId
:
item
.
data
.
pluginId
,
isFolded
:
item
.
data
.
isFolded
}));
// get all handle
...
...
@@ -49,6 +50,8 @@ export const uiWorkflow2StoreWorkflow = ({
(
item
)
=>
{
// Not in react flow page
if
(
!
reactFlowViewport
)
return
true
;
const
currentSourceNode
=
nodes
.
find
((
node
)
=>
node
.
data
.
nodeId
===
item
.
source
);
if
(
currentSourceNode
?.
data
.
isFolded
)
return
true
;
return
handleIdList
.
includes
(
item
.
sourceHandle
)
&&
handleIdList
.
includes
(
item
.
targetHandle
);
}
);
...
...
projects/app/src/web/core/workflow/utils.ts
View file @
12d7ba5d
...
...
@@ -532,7 +532,8 @@ export const compareSnapshot = (
name
:
node
.
data
.
name
,
intro
:
node
.
data
.
intro
,
avatar
:
node
.
data
.
avatar
,
version
:
node
.
data
.
version
version
:
node
.
data
.
version
,
isFolded
:
node
.
data
.
isFolded
}
}));
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment