Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
dify
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tech
dify
Commits
94cda3e8
Commit
94cda3e8
authored
Feb 22, 2024
by
StyleZhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore
parent
f09f91e2
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
661 additions
and
356 deletions
+661
-356
page.tsx
web/app/(commonLayout)/workflow/page.tsx
+3
-0
index.tsx
web/app/components/workflow/block-selector/index.tsx
+4
-2
context.tsx
web/app/components/workflow/context.tsx
+1
-9
custom-edge.tsx
web/app/components/workflow/custom-edge.tsx
+34
-19
hooks.ts
web/app/components/workflow/hooks.ts
+4
-18
index.tsx
web/app/components/workflow/index.tsx
+16
-15
node.tsx
web/app/components/workflow/nodes/_base/node.tsx
+7
-7
panel.tsx
web/app/components/workflow/nodes/_base/panel.tsx
+9
-3
index.tsx
web/app/components/workflow/panel/index.tsx
+8
-2
store.ts
web/app/components/workflow/store.ts
+21
-0
zoom-in-out.tsx
web/app/components/workflow/zoom-in-out.tsx
+2
-2
package.json
web/package.json
+2
-1
yarn.lock
web/yarn.lock
+550
-278
No files found.
web/app/(commonLayout)/workflow/page.tsx
View file @
94cda3e8
...
@@ -34,16 +34,19 @@ const initialNodes = [
...
@@ -34,16 +34,19 @@ const initialNodes = [
const
initialEdges
=
[
const
initialEdges
=
[
{
{
id
:
'0'
,
id
:
'0'
,
type
:
'custom'
,
source
:
'1'
,
source
:
'1'
,
target
:
'2'
,
target
:
'2'
,
},
},
{
{
id
:
'1'
,
id
:
'1'
,
type
:
'custom'
,
source
:
'2'
,
source
:
'2'
,
target
:
'3'
,
target
:
'3'
,
},
},
{
{
id
:
'2'
,
id
:
'2'
,
type
:
'custom'
,
source
:
'2'
,
source
:
'2'
,
target
:
'4'
,
target
:
'4'
,
},
},
...
...
web/app/components/workflow/block-selector/index.tsx
View file @
94cda3e8
...
@@ -24,6 +24,7 @@ type NodeSelectorProps = {
...
@@ -24,6 +24,7 @@ type NodeSelectorProps = {
trigger
?:
(
open
:
boolean
)
=>
React
.
ReactNode
trigger
?:
(
open
:
boolean
)
=>
React
.
ReactNode
placement
?:
Placement
placement
?:
Placement
offset
?:
OffsetOptions
offset
?:
OffsetOptions
triggerStyle
?:
React
.
CSSProperties
popupClassName
?:
string
popupClassName
?:
string
asChild
?:
boolean
asChild
?:
boolean
}
}
...
@@ -32,6 +33,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
...
@@ -32,6 +33,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({
trigger
,
trigger
,
placement
=
'right'
,
placement
=
'right'
,
offset
=
6
,
offset
=
6
,
triggerStyle
,
popupClassName
,
popupClassName
,
asChild
,
asChild
,
})
=>
{
})
=>
{
...
@@ -50,10 +52,10 @@ const NodeSelector: FC<NodeSelectorProps> = ({
...
@@ -50,10 +52,10 @@ const NodeSelector: FC<NodeSelectorProps> = ({
:
(
:
(
<
div
<
div
className=
{
`
className=
{
`
hidden absolute -right-2 top-4
items-center justify-center
flex
items-center justify-center
w-4 h-4 rounded-full bg-primary-600 cursor-pointer z-10 group-hover:flex
w-4 h-4 rounded-full bg-primary-600 cursor-pointer z-10 group-hover:flex
${open && '!flex'}
`
}
`
}
style=
{
triggerStyle
}
>
>
<
Plus02
className=
'w-2.5 h-2.5 text-white'
/>
<
Plus02
className=
'w-2.5 h-2.5 text-white'
/>
</
div
>
</
div
>
...
...
web/app/components/workflow/context.tsx
View file @
94cda3e8
'use client'
'use client'
import
{
createContext
,
useContext
}
from
'use-context-selector'
import
{
createContext
,
useContext
}
from
'use-context-selector'
import
type
{
import
type
{
Edge
}
from
'reactflow'
Edge
,
ReactFlowInstance
,
}
from
'reactflow'
import
type
{
import
type
{
BlockEnum
,
BlockEnum
,
Node
,
Node
,
...
@@ -12,11 +9,8 @@ import type {
...
@@ -12,11 +9,8 @@ import type {
export
type
WorkflowContextValue
=
{
export
type
WorkflowContextValue
=
{
mode
:
string
mode
:
string
reactFlow
:
ReactFlowInstance
nodes
:
Node
[]
nodes
:
Node
[]
edges
:
Edge
[]
edges
:
Edge
[]
selectedNodeId
?:
string
handleSelectedNodeIdChange
:
(
nodeId
:
string
)
=>
void
selectedNode
?:
Node
selectedNode
?:
Node
handleAddNextNode
:
(
prevNode
:
Node
,
nextNodeType
:
BlockEnum
)
=>
void
handleAddNextNode
:
(
prevNode
:
Node
,
nextNodeType
:
BlockEnum
)
=>
void
handleUpdateNodeData
:
(
nodeId
:
string
,
data
:
Node
[
'data'
])
=>
void
handleUpdateNodeData
:
(
nodeId
:
string
,
data
:
Node
[
'data'
])
=>
void
...
@@ -24,10 +18,8 @@ export type WorkflowContextValue = {
...
@@ -24,10 +18,8 @@ export type WorkflowContextValue = {
export
const
WorkflowContext
=
createContext
<
WorkflowContextValue
>
({
export
const
WorkflowContext
=
createContext
<
WorkflowContextValue
>
({
mode
:
'workflow'
,
mode
:
'workflow'
,
reactFlow
:
null
as
any
,
nodes
:
[],
nodes
:
[],
edges
:
[],
edges
:
[],
handleSelectedNodeIdChange
:
()
=>
{},
handleAddNextNode
:
()
=>
{},
handleAddNextNode
:
()
=>
{},
handleUpdateNodeData
:
()
=>
{},
handleUpdateNodeData
:
()
=>
{},
})
})
...
...
web/app/components/workflow/custom-edge.tsx
View file @
94cda3e8
...
@@ -3,8 +3,11 @@ import type { EdgeProps } from 'reactflow'
...
@@ -3,8 +3,11 @@ import type { EdgeProps } from 'reactflow'
import
{
import
{
BaseEdge
,
BaseEdge
,
EdgeLabelRenderer
,
EdgeLabelRenderer
,
getSmoothStepPath
,
Position
,
getSimpleBezierPath
,
}
from
'reactflow'
}
from
'reactflow'
import
BlockSelector
from
'./block-selector'
import
{
useStore
}
from
'./store'
const
CustomEdge
=
({
const
CustomEdge
=
({
id
,
id
,
...
@@ -12,38 +15,50 @@ const CustomEdge = ({
...
@@ -12,38 +15,50 @@ const CustomEdge = ({
sourceY
,
sourceY
,
targetX
,
targetX
,
targetY
,
targetY
,
selected
,
}:
EdgeProps
)
=>
{
}:
EdgeProps
)
=>
{
const
hoveringEdgeId
=
useStore
(
state
=>
state
.
hoveringEdgeId
)
const
[
const
[
edgePath
,
edgePath
,
labelX
,
labelX
,
labelY
,
labelY
,
]
=
getS
moothStep
Path
({
]
=
getS
impleBezier
Path
({
sourceX
,
sourceX
,
sourceY
,
sourceY
,
sourcePosition
:
Position
.
Right
,
targetX
,
targetX
,
targetY
,
targetY
,
borderRadius
:
30
,
targetPosition
:
Position
.
Left
,
offset
:
-
20
,
})
})
return
(
return
(
<>
<>
<
BaseEdge
id=
{
id
}
path=
{
edgePath
}
style=
{
{
strokeWidth
:
5
}
}
/>
<
BaseEdge
id=
{
id
}
path=
{
edgePath
}
style=
{
{
stroke
:
selected
?
'#2970FF'
:
'#D0D5DD'
,
strokeWidth
:
2
,
}
}
/>
<
EdgeLabelRenderer
>
<
EdgeLabelRenderer
>
<
div
{
className=
{
`
hoveringEdgeId
===
id
&&
(
flex items-center px-2 h-6 bg-white rounded-lg shadow-xs
<
div
text-[10px] font-semibold text-gray-700
className=
'nopan nodrag'
nodrag nopan
style=
{
{
`
}
position
:
'absolute'
,
style=
{
{
transform
:
`translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`
,
position
:
'absolute'
,
pointerEvents
:
'all'
,
transform
:
`translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`
,
}
}
pointerEvents
:
'all'
,
>
}
}
<
BlockSelector
>
asChild
Topic 2
onSelect=
{
()
=>
{}
}
</
div
>
/>
</
div
>
)
}
</
EdgeLabelRenderer
>
</
EdgeLabelRenderer
>
</>
</>
)
)
...
...
web/app/components/workflow/hooks.ts
View file @
94cda3e8
...
@@ -2,13 +2,11 @@ import type {
...
@@ -2,13 +2,11 @@ import type {
Dispatch
,
Dispatch
,
SetStateAction
,
SetStateAction
,
}
from
'react'
}
from
'react'
import
{
import
{
useCallback
}
from
'react'
useCallback
,
useMemo
,
useState
,
}
from
'react'
import
produce
from
'immer'
import
produce
from
'immer'
import
type
{
Edge
}
from
'reactflow'
import
type
{
Edge
,
}
from
'reactflow'
import
type
{
import
type
{
BlockEnum
,
BlockEnum
,
Node
,
Node
,
...
@@ -20,16 +18,7 @@ export const useWorkflow = (
...
@@ -20,16 +18,7 @@ export const useWorkflow = (
edges
:
Edge
[],
edges
:
Edge
[],
setNodes
:
Dispatch
<
SetStateAction
<
Node
[]
>>
,
setNodes
:
Dispatch
<
SetStateAction
<
Node
[]
>>
,
setEdges
:
Dispatch
<
SetStateAction
<
Edge
[]
>>
,
setEdges
:
Dispatch
<
SetStateAction
<
Edge
[]
>>
,
initialSelectedNodeId
?:
string
,
)
=>
{
)
=>
{
const
[
selectedNodeId
,
setSelectedNodeId
]
=
useState
(
initialSelectedNodeId
)
const
handleSelectedNodeIdChange
=
useCallback
((
nodeId
:
string
)
=>
setSelectedNodeId
(
nodeId
),
[])
const
selectedNode
=
useMemo
(()
=>
{
return
nodes
.
find
(
node
=>
node
.
id
===
selectedNodeId
)
},
[
nodes
,
selectedNodeId
])
const
handleAddNextNode
=
useCallback
((
prevNode
:
Node
,
nextNodeType
:
BlockEnum
)
=>
{
const
handleAddNextNode
=
useCallback
((
prevNode
:
Node
,
nextNodeType
:
BlockEnum
)
=>
{
const
nextNode
=
{
const
nextNode
=
{
id
:
`node-
${
Date
.
now
()}
`
,
id
:
`node-
${
Date
.
now
()}
`
,
...
@@ -68,9 +57,6 @@ export const useWorkflow = (
...
@@ -68,9 +57,6 @@ export const useWorkflow = (
},
[
setNodes
])
},
[
setNodes
])
return
{
return
{
selectedNodeId
,
selectedNode
,
handleSelectedNodeIdChange
,
handleAddNextNode
,
handleAddNextNode
,
handleUpdateNodeData
,
handleUpdateNodeData
,
}
}
...
...
web/app/components/workflow/index.tsx
View file @
94cda3e8
import
type
{
FC
}
from
'react'
import
type
{
FC
}
from
'react'
import
{
memo
}
from
'react'
import
type
{
Edge
}
from
'reactflow'
import
type
{
Edge
}
from
'reactflow'
import
ReactFlow
,
{
import
ReactFlow
,
{
Background
,
Background
,
ReactFlowProvider
,
ReactFlowProvider
,
useEdgesState
,
useEdgesState
,
useNodesState
,
useNodesState
,
useReactFlow
,
}
from
'reactflow'
}
from
'reactflow'
import
'reactflow/dist/style.css'
import
'reactflow/dist/style.css'
import
'./style.css'
import
'./style.css'
...
@@ -20,6 +20,7 @@ import ZoomInOut from './zoom-in-out'
...
@@ -20,6 +20,7 @@ import ZoomInOut from './zoom-in-out'
import
CustomEdge
from
'./custom-edge'
import
CustomEdge
from
'./custom-edge'
import
Panel
from
'./panel'
import
Panel
from
'./panel'
import
type
{
Node
}
from
'./types'
import
type
{
Node
}
from
'./types'
import
{
useStore
}
from
'./store'
const
nodeTypes
=
{
const
nodeTypes
=
{
custom
:
CustomNode
,
custom
:
CustomNode
,
...
@@ -28,11 +29,13 @@ const edgeTypes = {
...
@@ -28,11 +29,13 @@ const edgeTypes = {
custom
:
CustomEdge
,
custom
:
CustomEdge
,
}
}
const
Workflow
=
()
=>
{
const
Workflow
=
memo
(
()
=>
{
const
{
const
{
nodes
,
nodes
,
edges
,
edges
,
}
=
useWorkflowContext
()
}
=
useWorkflowContext
()
const
handleEnterEdge
=
useStore
(
state
=>
state
.
handleEnterEdge
)
const
handleLeaveEdge
=
useStore
(
state
=>
state
.
handleLeaveEdge
)
return
(
return
(
<
div
className=
'relative w-full h-full'
>
<
div
className=
'relative w-full h-full'
>
...
@@ -44,6 +47,8 @@ const Workflow = () => {
...
@@ -44,6 +47,8 @@ const Workflow = () => {
edgeTypes=
{
edgeTypes
}
edgeTypes=
{
edgeTypes
}
nodes=
{
nodes
}
nodes=
{
nodes
}
edges=
{
edges
}
edges=
{
edges
}
onEdgeMouseEnter=
{
handleEnterEdge
}
onEdgeMouseLeave=
{
handleLeaveEdge
}
>
>
<
Background
<
Background
gap=
{
[
14
,
14
]
}
gap=
{
[
14
,
14
]
}
...
@@ -52,24 +57,23 @@ const Workflow = () => {
...
@@ -52,24 +57,23 @@ const Workflow = () => {
</
ReactFlow
>
</
ReactFlow
>
</
div
>
</
div
>
)
)
}
})
Workflow
.
displayName
=
'Workflow'
type
WorkflowWrapProps
=
{
type
WorkflowWrapProps
=
{
selectedNodeId
?:
string
selectedNodeId
?:
string
nodes
:
Node
[]
nodes
:
Node
[]
edges
:
Edge
[]
edges
:
Edge
[]
}
}
const
WorkflowWrap
:
FC
<
WorkflowWrapProps
>
=
({
const
WorkflowWrap
:
FC
<
WorkflowWrapProps
>
=
memo
(
({
nodes
:
initialNodes
,
nodes
:
initialNodes
,
edges
:
initialEdges
,
edges
:
initialEdges
,
selectedNodeId
:
initialSelectedNodeId
,
selectedNodeId
:
initialSelectedNodeId
,
})
=>
{
})
=>
{
const
reactFlow
=
useReactFlow
()
const
[
nodes
,
setNodes
]
=
useNodesState
(
initialNodes
)
const
[
nodes
,
setNodes
]
=
useNodesState
(
initialNodes
)
const
[
edges
,
setEdges
]
=
useEdgesState
(
initialEdges
)
const
[
edges
,
setEdges
]
=
useEdgesState
(
initialEdges
)
const
{
const
{
selectedNodeId
,
handleSelectedNodeIdChange
,
selectedNode
,
handleAddNextNode
,
handleAddNextNode
,
handleUpdateNodeData
,
handleUpdateNodeData
,
}
=
useWorkflow
(
}
=
useWorkflow
(
...
@@ -77,16 +81,11 @@ const WorkflowWrap: FC<WorkflowWrapProps> = ({
...
@@ -77,16 +81,11 @@ const WorkflowWrap: FC<WorkflowWrapProps> = ({
edges
,
edges
,
setNodes
,
setNodes
,
setEdges
,
setEdges
,
initialSelectedNodeId
,
)
)
return
(
return
(
<
WorkflowContext
.
Provider
value=
{
{
<
WorkflowContext
.
Provider
value=
{
{
mode
:
'workflow'
,
mode
:
'workflow'
,
reactFlow
,
selectedNodeId
,
handleSelectedNodeIdChange
,
selectedNode
,
nodes
,
nodes
,
edges
,
edges
,
handleAddNextNode
,
handleAddNextNode
,
...
@@ -95,7 +94,9 @@ const WorkflowWrap: FC<WorkflowWrapProps> = ({
...
@@ -95,7 +94,9 @@ const WorkflowWrap: FC<WorkflowWrapProps> = ({
<
Workflow
/>
<
Workflow
/>
</
WorkflowContext
.
Provider
>
</
WorkflowContext
.
Provider
>
)
)
}
})
WorkflowWrap
.
displayName
=
'WorkflowWrap'
const
WorkflowWrapWithReactFlowProvider
:
FC
<
WorkflowWrapProps
>
=
({
const
WorkflowWrapWithReactFlowProvider
:
FC
<
WorkflowWrapProps
>
=
({
selectedNodeId
,
selectedNodeId
,
...
@@ -114,4 +115,4 @@ const WorkflowWrapWithReactFlowProvider: FC<WorkflowWrapProps> = ({
...
@@ -114,4 +115,4 @@ const WorkflowWrapWithReactFlowProvider: FC<WorkflowWrapProps> = ({
)
)
}
}
export
default
WorkflowWrapWithReactFlowProvider
export
default
memo
(
WorkflowWrapWithReactFlowProvider
)
web/app/components/workflow/nodes/_base/node.tsx
View file @
94cda3e8
...
@@ -8,7 +8,9 @@ import {
...
@@ -8,7 +8,9 @@ import {
useMemo
,
useMemo
,
}
from
'react'
}
from
'react'
import
type
{
NodeProps
}
from
'reactflow'
import
type
{
NodeProps
}
from
'reactflow'
import
{
useWorkflowContext
}
from
'../../context'
import
{
useNodes
}
from
'reactflow'
import
{
useStore
}
from
'../../store'
import
type
{
NodeData
}
from
'../../types'
import
BlockIcon
from
'../../block-icon'
import
BlockIcon
from
'../../block-icon'
import
BlockSelector
from
'../../block-selector'
import
BlockSelector
from
'../../block-selector'
import
NodeControl
from
'./components/node-control'
import
NodeControl
from
'./components/node-control'
...
@@ -22,11 +24,9 @@ const BaseNode: FC<BaseNodeProps> = ({
...
@@ -22,11 +24,9 @@ const BaseNode: FC<BaseNodeProps> = ({
data
,
data
,
children
,
children
,
})
=>
{
})
=>
{
const
{
const
nodes
=
useNodes
<
NodeData
>
()
nodes
,
const
selectedNodeId
=
useStore
(
state
=>
state
.
selectedNodeId
)
selectedNodeId
,
const
handleSelectedNodeId
=
useStore
(
state
=>
state
.
handleSelectedNodeId
)
handleSelectedNodeIdChange
,
}
=
useWorkflowContext
()
const
currentNode
=
useMemo
(()
=>
{
const
currentNode
=
useMemo
(()
=>
{
return
nodes
.
find
(
node
=>
node
.
id
===
nodeId
)
return
nodes
.
find
(
node
=>
node
.
id
===
nodeId
)
},
[
nodeId
,
nodes
])
},
[
nodeId
,
nodes
])
...
@@ -38,7 +38,7 @@ const BaseNode: FC<BaseNodeProps> = ({
...
@@ -38,7 +38,7 @@ const BaseNode: FC<BaseNodeProps> = ({
hover:shadow-lg
hover:shadow-lg
${selectedNodeId === nodeId ? 'border-[2px] border-primary-600' : 'border border-white'}
${selectedNodeId === nodeId ? 'border-[2px] border-primary-600' : 'border border-white'}
`
}
`
}
onClick=
{
()
=>
handleSelectedNodeId
Change
(
nodeId
||
''
)
}
onClick=
{
()
=>
handleSelectedNodeId
(
nodeId
||
''
)
}
>
>
<
NodeControl
/>
<
NodeControl
/>
<
div
className=
'flex items-center px-3 pt-3 pb-2'
>
<
div
className=
'flex items-center px-3 pt-3 pb-2'
>
...
...
web/app/components/workflow/nodes/_base/panel.tsx
View file @
94cda3e8
...
@@ -5,9 +5,11 @@ import type {
...
@@ -5,9 +5,11 @@ import type {
import
{
import
{
cloneElement
,
cloneElement
,
memo
,
memo
,
useMemo
,
}
from
'react'
}
from
'react'
import
type
{
NodeProps
}
from
'reactflow'
import
type
{
NodeProps
}
from
'reactflow'
import
{
useWorkflowContext
}
from
'../../context'
import
{
useWorkflowContext
}
from
'../../context'
import
{
useStore
}
from
'../../store'
import
BlockIcon
from
'../../block-icon'
import
BlockIcon
from
'../../block-icon'
import
NextStep
from
'./components/next-step'
import
NextStep
from
'./components/next-step'
import
{
import
{
...
@@ -26,9 +28,13 @@ const BasePanel: FC<BasePanelProps> = ({
...
@@ -26,9 +28,13 @@ const BasePanel: FC<BasePanelProps> = ({
children
,
children
,
})
=>
{
})
=>
{
const
{
const
{
handleSelectedNodeIdChange
,
nodes
,
selectedNode
,
}
=
useWorkflowContext
()
}
=
useWorkflowContext
()
const
selectedNodeId
=
useStore
(
state
=>
state
.
selectedNodeId
)
const
handleSelectedNodeId
=
useStore
(
state
=>
state
.
handleSelectedNodeId
)
const
selectedNode
=
useMemo
(()
=>
{
return
nodes
.
find
(
node
=>
node
.
id
===
selectedNodeId
)
},
[
nodes
,
selectedNodeId
])
return
(
return
(
<
div
className=
'mr-2 w-[420px] h-full bg-white shadow-lg border-[0.5px] border-gray-200 rounded-2xl z-10 overflow-y-auto'
>
<
div
className=
'mr-2 w-[420px] h-full bg-white shadow-lg border-[0.5px] border-gray-200 rounded-2xl z-10 overflow-y-auto'
>
...
@@ -47,7 +53,7 @@ const BasePanel: FC<BasePanelProps> = ({
...
@@ -47,7 +53,7 @@ const BasePanel: FC<BasePanelProps> = ({
<
div
className=
'mx-3 w-[1px] h-3.5 bg-gray-200'
/>
<
div
className=
'mx-3 w-[1px] h-3.5 bg-gray-200'
/>
<
div
<
div
className=
'flex items-center justify-center w-6 h-6 cursor-pointer'
className=
'flex items-center justify-center w-6 h-6 cursor-pointer'
onClick=
{
()
=>
handleSelectedNodeId
Change
(
''
)
}
onClick=
{
()
=>
handleSelectedNodeId
(
''
)
}
>
>
<
XClose
className=
'w-4 h-4'
/>
<
XClose
className=
'w-4 h-4'
/>
</
div
>
</
div
>
...
...
web/app/components/workflow/panel/index.tsx
View file @
94cda3e8
...
@@ -3,16 +3,22 @@ import {
...
@@ -3,16 +3,22 @@ import {
memo
,
memo
,
useMemo
,
useMemo
,
}
from
'react'
}
from
'react'
import
{
useNodes
}
from
'reactflow'
import
{
useWorkflowContext
}
from
'../context'
import
{
useWorkflowContext
}
from
'../context'
import
{
Panel
as
NodePanel
}
from
'../nodes'
import
{
Panel
as
NodePanel
}
from
'../nodes'
import
{
useStore
}
from
'../store'
import
WorkflowInfo
from
'./workflow-info'
import
WorkflowInfo
from
'./workflow-info'
import
DebugAndPreview
from
'./debug-and-preview'
import
DebugAndPreview
from
'./debug-and-preview'
const
Panel
:
FC
=
()
=>
{
const
Panel
:
FC
=
()
=>
{
const
{
const
{
mode
,
mode
,
selectedNode
,
}
=
useWorkflowContext
()
}
=
useWorkflowContext
()
const
nodes
=
useNodes
()
const
selectedNodeId
=
useStore
(
state
=>
state
.
selectedNodeId
)
const
selectedNode
=
useMemo
(()
=>
{
return
nodes
.
find
(
node
=>
node
.
id
===
selectedNodeId
)
},
[
nodes
,
selectedNodeId
])
const
{
const
{
showWorkflowInfoPanel
,
showWorkflowInfoPanel
,
showNodePanel
,
showNodePanel
,
...
@@ -29,7 +35,7 @@ const Panel: FC = () => {
...
@@ -29,7 +35,7 @@ const Panel: FC = () => {
<
div
className=
'absolute top-14 right-0 bottom-2 flex'
>
<
div
className=
'absolute top-14 right-0 bottom-2 flex'
>
{
{
showNodePanel
&&
(
showNodePanel
&&
(
<
NodePanel
node=
{
selectedNode
!
}
/>
<
NodePanel
node=
{
selectedNode
as
any
}
/>
)
)
}
}
{
{
...
...
web/app/components/workflow/store.ts
0 → 100644
View file @
94cda3e8
import
{
create
}
from
'zustand'
import
type
{
EdgeMouseHandler
}
from
'reactflow'
type
State
=
{
selectedNodeId
:
string
hoveringEdgeId
:
string
}
type
Action
=
{
handleSelectedNodeId
:
(
selectedNodeId
:
State
[
'selectedNodeId'
])
=>
void
handleEnterEdge
:
EdgeMouseHandler
handleLeaveEdge
:
EdgeMouseHandler
}
export
const
useStore
=
create
<
State
&
Action
>
(
set
=>
({
selectedNodeId
:
''
,
handleSelectedNodeId
:
selectedNodeId
=>
set
(()
=>
({
selectedNodeId
})),
hoveringEdgeId
:
''
,
handleEnterEdge
:
(
_
,
edge
)
=>
set
(()
=>
({
hoveringEdgeId
:
edge
.
id
})),
handleLeaveEdge
:
()
=>
set
(()
=>
({
hoveringEdgeId
:
''
})),
}))
web/app/components/workflow/zoom-in-out.tsx
View file @
94cda3e8
...
@@ -4,7 +4,7 @@ import {
...
@@ -4,7 +4,7 @@ import {
memo
,
memo
,
useState
,
useState
,
}
from
'react'
}
from
'react'
import
{
use
WorkflowContext
}
from
'./context
'
import
{
use
ReactFlow
}
from
'reactflow
'
import
{
import
{
PortalToFollowElem
,
PortalToFollowElem
,
PortalToFollowElemContent
,
PortalToFollowElemContent
,
...
@@ -43,7 +43,7 @@ const ZOOM_IN_OUT_OPTIONS = [
...
@@ -43,7 +43,7 @@ const ZOOM_IN_OUT_OPTIONS = [
]
]
const
ZoomInOut
:
FC
=
()
=>
{
const
ZoomInOut
:
FC
=
()
=>
{
const
{
reactFlow
}
=
useWorkflowContext
()
const
reactFlow
=
useReactFlow
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
const
handleZoom
=
(
type
:
string
)
=>
{
const
handleZoom
=
(
type
:
string
)
=>
{
...
...
web/package.json
View file @
94cda3e8
...
@@ -79,7 +79,8 @@
...
@@ -79,7 +79,8 @@
"sharp"
:
"^0.33.2"
,
"sharp"
:
"^0.33.2"
,
"sortablejs"
:
"^1.15.0"
,
"sortablejs"
:
"^1.15.0"
,
"swr"
:
"^2.1.0"
,
"swr"
:
"^2.1.0"
,
"use-context-selector"
:
"^1.4.1"
"use-context-selector"
:
"^1.4.1"
,
"zustand"
:
"^4.5.1"
},
},
"devDependencies"
:
{
"devDependencies"
:
{
"@antfu/eslint-config"
:
"^0.36.0"
,
"@antfu/eslint-config"
:
"^0.36.0"
,
...
...
web/yarn.lock
View file @
94cda3e8
This diff is collapsed.
Click to expand it.
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