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
c42deab6
authored
Feb 12, 2025
by
heheer
Committed by
GitHub
Feb 12, 2025
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
global variable & interactive node dnd (#3764)
parent
58f715e8
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
407 additions
and
162 deletions
+407
-162
packages/web/components/common/DndDrag/index.tsx
+26
-9
projects/app/src/components/core/app/VariableEdit.tsx
+105
-45
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeFormInput/index.tsx
+120
-37
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeIfElse/index.tsx
+3
-1
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeUserSelect.tsx
+153
-70
No files found.
packages/web/components/common/DndDrag/index.tsx
View file @
c42deab6
import
{
Box
}
from
'@chakra-ui/react'
;
import
React
,
{
useState
}
from
'react'
;
import
{
Box
,
Tbody
}
from
'@chakra-ui/react'
;
import
React
,
{
ReactNode
,
useState
}
from
'react'
;
import
{
DragDropContext
,
DroppableProps
,
Droppable
,
DraggableChildrenFn
,
DragStart
,
DropResult
DropResult
,
DroppableProvided
,
DroppableStateSnapshot
}
from
'react-beautiful-dnd'
;
export
*
from
'react-beautiful-dnd'
;
type
Props
<
T
=
any
>
=
{
onDragEndCb
:
(
result
:
T
[])
=>
void
;
renderClone
?:
DraggableChildrenFn
;
children
:
DroppableProps
[
'children'
];
children
:
|
((
provided
:
DroppableProvided
,
snapshot
:
DroppableStateSnapshot
)
=>
ReactNode
)
|
ReactNode
;
dataList
:
T
[];
isTable
?:
boolean
;
zoom
?:
number
;
};
function
DndDrag
<
T
>
({
children
,
renderClone
,
onDragEndCb
,
dataList
}:
Props
<
T
>
)
{
function
DndDrag
<
T
>
({
children
,
renderClone
,
onDragEndCb
,
dataList
,
isTable
=
false
,
zoom
=
1
}:
Props
<
T
>
)
{
const
[
draggingItemHeight
,
setDraggingItemHeight
]
=
useState
(
0
);
const
onDragStart
=
(
start
:
DragStart
)
=>
{
...
...
@@ -45,10 +57,15 @@ function DndDrag<T>({ children, renderClone, onDragEndCb, dataList }: Props<T>)
<
DragDropContext
onDragStart=
{
onDragStart
}
onDragEnd=
{
onDragEnd
}
>
<
Droppable
droppableId=
"droppable"
renderClone=
{
renderClone
}
>
{
(
provided
,
snapshot
)
=>
{
return
(
return
isTable
?
(
<
Tbody
{
...
provided
.
droppableProps
}
ref=
{
provided
.
innerRef
}
>
{
typeof
children
!==
'function'
&&
children
}
{
snapshot
.
isDraggingOver
&&
<
Box
height=
{
`${draggingItemHeight / zoom}px`
}
/>
}
</
Tbody
>
)
:
(
<
Box
{
...
provided
.
droppableProps
}
ref=
{
provided
.
innerRef
}
>
{
children
(
provided
,
snapshot
)
}
{
snapshot
.
isDraggingOver
&&
<
Box
height=
{
`${draggingItemHeight}px`
}
/>
}
{
typeof
children
===
'function'
&&
children
(
provided
,
snapshot
)
}
{
snapshot
.
isDraggingOver
&&
<
Box
height=
{
`${draggingItemHeight
/ zoom
}px`
}
/>
}
</
Box
>
);
}
}
...
...
projects/app/src/components/core/app/VariableEdit.tsx
View file @
c42deab6
import
React
,
{
useCallback
,
useMemo
,
useState
}
from
'react'
;
import
React
,
{
useCallback
,
useMemo
}
from
'react'
;
import
{
Box
,
Button
,
Flex
,
Table
,
Thead
,
Tbody
,
Tr
,
Th
,
Td
,
...
...
@@ -20,9 +19,8 @@ import {
}
from
'@fastgpt/global/core/workflow/constants'
;
import
type
{
VariableItemType
}
from
'@fastgpt/global/core/app/type.d'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
import
{
useForm
}
from
'react-hook-form'
;
import
{
useForm
,
UseFormReset
}
from
'react-hook-form'
;
import
{
customAlphabet
}
from
'nanoid'
;
const
nanoid
=
customAlphabet
(
'abcdefghijklmnopqrstuvwxyz1234567890'
,
6
);
import
MyModal
from
'@fastgpt/web/components/common/MyModal'
;
import
{
useTranslation
}
from
'next-i18next'
;
import
{
useToast
}
from
'@fastgpt/web/hooks/useToast'
;
...
...
@@ -32,6 +30,14 @@ import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
import
QuestionTip
from
'@fastgpt/web/components/common/MyTooltip/QuestionTip'
;
import
InputTypeConfig
from
'@/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig'
;
import
MyIconButton
from
'@fastgpt/web/components/common/Icon/button'
;
import
{
useReactFlow
,
useViewport
}
from
'reactflow'
;
import
DndDrag
,
{
Draggable
,
DraggableProvided
,
DraggableStateSnapshot
}
from
'@fastgpt/web/components/common/DndDrag'
;
const
nanoid
=
customAlphabet
(
'abcdefghijklmnopqrstuvwxyz1234567890'
,
6
);
export
const
defaultVariable
:
VariableItemType
=
{
id
:
nanoid
(),
...
...
@@ -61,6 +67,7 @@ const VariableEdit = ({
})
=>
{
const
{
t
}
=
useTranslation
();
const
{
toast
}
=
useToast
();
const
{
zoom
}
=
useViewport
();
const
form
=
useForm
<
VariableItemType
>
();
const
{
setValue
,
reset
,
watch
,
getValues
}
=
form
;
...
...
@@ -166,7 +173,7 @@ const VariableEdit = ({
);
return
(
<
Box
>
<
Box
className=
"nodrag"
>
{
/* Row box */
}
<
Flex
alignItems=
{
'center'
}
>
<
MyIcon
name=
{
'core/app/simpleMode/variable'
}
w=
{
'20px'
}
/>
...
...
@@ -200,48 +207,40 @@ const VariableEdit = ({
<
Th
>
{
t
(
'common:common.Operation'
)
}
</
Th
>
</
Tr
>
</
Thead
>
<
Tbody
>
<
DndDrag
<
VariableItemType
>
onDragEndCb=
{
(
list
)
=>
{
onChange
(
list
);
}
}
dataList=
{
formatVariables
}
renderClone=
{
(
provided
,
snapshot
,
rubric
)
=>
(
<
TableItem
provided=
{
provided
}
snapshot=
{
snapshot
}
item=
{
formatVariables
[
rubric
.
source
.
index
]
}
reset=
{
reset
}
onChange=
{
onChange
}
variables=
{
variables
}
/>
)
}
isTable
zoom=
{
zoom
}
>
{
formatVariables
.
map
((
item
,
index
)
=>
(
<
Tr
key=
{
item
.
id
}
>
<
Td
fontWeight=
{
'medium'
}
>
<
Flex
alignItems=
{
'center'
}
>
<
MyIcon
name=
{
item
.
icon
as
any
}
w=
{
'16px'
}
color=
{
'myGray.400'
}
mr=
{
2
}
/>
{
item
.
key
}
</
Flex
>
</
Td
>
<
Td
>
<
Flex
alignItems=
{
'center'
}
>
{
item
.
required
?
(
<
MyIcon
name=
{
'check'
}
w=
{
'16px'
}
color=
{
'myGray.900'
}
mr=
{
2
}
/>
)
:
(
''
)
}
</
Flex
>
</
Td
>
<
Td
>
<
Flex
>
<
MyIconButton
icon=
{
'common/settingLight'
}
onClick=
{
()
=>
{
const
formattedItem
=
{
...
item
,
list
:
item
.
enums
||
[]
};
reset
(
formattedItem
);
}
}
/>
<
MyIconButton
icon=
{
'delete'
}
hoverColor=
{
'red.500'
}
onClick=
{
()
=>
onChange
(
variables
.
filter
((
variable
)
=>
variable
.
id
!==
item
.
id
))
}
/>
</
Flex
>
</
Td
>
</
Tr
>
<
Draggable
key=
{
item
.
id
}
draggableId=
{
item
.
id
}
index=
{
index
}
>
{
(
provided
,
snapshot
)
=>
(
<
TableItem
provided=
{
provided
}
snapshot=
{
snapshot
}
item=
{
item
}
reset=
{
reset
}
onChange=
{
onChange
}
variables=
{
variables
}
key=
{
item
.
id
}
/>
)
}
</
Draggable
>
))
}
</
Tbody
>
</
DndDrag
>
</
Table
>
</
TableContainer
>
)
}
...
...
@@ -339,4 +338,65 @@ const VariableEdit = ({
);
};
const
TableItem
=
({
provided
,
snapshot
,
item
,
reset
,
onChange
,
variables
}:
{
provided
:
DraggableProvided
;
snapshot
:
DraggableStateSnapshot
;
item
:
VariableItemType
&
{
icon
?:
string
;
};
reset
:
UseFormReset
<
VariableItemType
>
;
onChange
:
(
data
:
VariableItemType
[])
=>
void
;
variables
:
VariableItemType
[];
})
=>
{
return
(
<
Tr
ref=
{
provided
.
innerRef
}
{
...
provided
.
draggableProps
}
{
...
provided
.
dragHandleProps
}
style=
{
{
...
provided
.
draggableProps
.
style
,
opacity
:
snapshot
.
isDragging
?
0.8
:
1
}
}
>
<
Td
fontWeight=
{
'medium'
}
>
<
Flex
alignItems=
{
'center'
}
>
<
MyIcon
name=
{
item
.
icon
as
any
}
w=
{
'16px'
}
color=
{
'myGray.400'
}
mr=
{
1
}
/>
{
item
.
key
}
</
Flex
>
</
Td
>
<
Td
>
<
Flex
alignItems=
{
'center'
}
>
{
item
.
required
?
<
MyIcon
name=
{
'check'
}
w=
{
'16px'
}
color=
{
'myGray.900'
}
mr=
{
2
}
/>
:
''
}
</
Flex
>
</
Td
>
<
Td
>
<
Flex
>
<
MyIconButton
icon=
{
'common/settingLight'
}
onClick=
{
()
=>
{
const
formattedItem
=
{
...
item
,
list
:
item
.
enums
||
[]
};
reset
(
formattedItem
);
}
}
/>
<
MyIconButton
icon=
{
'delete'
}
hoverColor=
{
'red.500'
}
onClick=
{
()
=>
onChange
(
variables
.
filter
((
variable
)
=>
variable
.
id
!==
item
.
id
))
}
/>
</
Flex
>
</
Td
>
</
Tr
>
);
};
export
default
React
.
memo
(
VariableEdit
);
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeFormInput/index.tsx
View file @
c42deab6
import
{
FlowNodeItemType
}
from
'@fastgpt/global/core/workflow/type/node'
;
import
React
,
{
useMemo
,
useState
}
from
'react'
;
import
{
NodeProps
}
from
'reactflow'
;
import
{
NodeProps
,
useViewport
}
from
'reactflow'
;
import
NodeCard
from
'../render/NodeCard'
;
import
Container
from
'../../components/Container'
;
import
RenderInput
from
'../render/RenderInput'
;
...
...
@@ -38,11 +38,17 @@ import InputFormEditModal, { defaultFormInput } from './InputFormEditModal';
import
RenderOutput
from
'../render/RenderOutput'
;
import
FormLabel
from
'@fastgpt/web/components/common/MyBox/FormLabel'
;
import
MyIconButton
from
'@fastgpt/web/components/common/Icon/button'
;
import
DndDrag
,
{
Draggable
,
DraggableProvided
,
DraggableStateSnapshot
}
from
'@fastgpt/web/components/common/DndDrag'
;
const
NodeFormInput
=
({
data
,
selected
}:
NodeProps
<
FlowNodeItemType
>
)
=>
{
const
{
nodeId
,
inputs
,
outputs
}
=
data
;
const
{
t
}
=
useTranslation
();
const
onChangeNode
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
.
onChangeNode
);
const
{
zoom
}
=
useViewport
();
const
[
editField
,
setEditField
]
=
useState
<
UserInputFormItemType
>
();
...
...
@@ -159,53 +165,79 @@ const NodeFormInput = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
<
Th
>
{
t
(
'user:operations'
)
}
</
Th
>
</
Tr
>
</
Thead
>
<
Tbody
>
<
DndDrag
<
UserInputFormItemType
>
onDragEndCb=
{
(
list
)
=>
{
const
sortedOutputs
=
[
outputs
[
0
],
...
outputs
.
slice
(
1
).
sort
((
a
,
b
)
=>
{
const
aIndex
=
list
.
findIndex
((
item
)
=>
item
.
key
===
a
.
key
);
const
bIndex
=
list
.
findIndex
((
item
)
=>
item
.
key
===
b
.
key
);
return
aIndex
-
bIndex
;
})
];
onChangeNode
({
nodeId
,
type
:
'updateInput'
,
key
,
value
:
{
...
props
,
key
,
value
:
list
}
});
onChangeNode
({
nodeId
,
type
:
'attr'
,
key
:
'outputs'
,
value
:
sortedOutputs
});
}
}
dataList=
{
inputs
}
renderClone=
{
(
provided
,
snapshot
,
rubric
)
=>
{
const
item
=
inputs
[
rubric
.
source
.
index
];
const
icon
=
FlowNodeInputMap
[
item
.
type
as
FlowNodeInputTypeEnum
]?.
icon
;
return
(
<
TableItem
provided=
{
provided
}
snapshot=
{
snapshot
}
item=
{
item
}
icon=
{
icon
}
setEditField=
{
setEditField
}
onDelete=
{
onDelete
}
/>
);
}
}
isTable
zoom=
{
zoom
}
>
{
inputs
.
map
((
item
,
index
)
=>
{
const
icon
=
FlowNodeInputMap
[
item
.
type
as
FlowNodeInputTypeEnum
]?.
icon
;
return
(
<
Tr
key=
{
index
}
>
<
Td
>
<
Flex
alignItems=
{
'center'
}
fontSize=
{
'mini'
}
fontWeight=
{
'medium'
}
>
{
!!
icon
&&
(
<
MyIcon
name=
{
icon
as
any
}
w=
{
'14px'
}
mr=
{
1
}
color=
{
'myGray.400'
}
/>
)
}
{
item
.
label
}
</
Flex
>
</
Td
>
<
Td
>
{
item
.
description
||
'-'
}
</
Td
>
<
Td
>
{
item
.
required
?
(
<
Flex
alignItems=
{
'center'
}
>
<
MyIcon
name=
{
'check'
}
w=
{
'16px'
}
color=
{
'myGray.900'
}
mr=
{
2
}
/>
</
Flex
>
)
:
(
'-'
)
}
</
Td
>
<
Td
>
<
Flex
>
<
MyIconButton
icon=
{
'common/settingLight'
}
onClick=
{
()
=>
setEditField
(
item
)
}
/>
<
MyIconButton
icon=
{
'delete'
}
hoverColor=
{
'red.500'
}
onClick=
{
()
=>
onDelete
(
item
.
key
)
}
/>
</
Flex
>
</
Td
>
</
Tr
>
<
Draggable
key=
{
item
.
key
}
draggableId=
{
item
.
key
}
index=
{
index
}
>
{
(
provided
,
snapshot
)
=>
(
<
TableItem
provided=
{
provided
}
snapshot=
{
snapshot
}
key=
{
item
.
key
}
item=
{
item
}
icon=
{
icon
}
setEditField=
{
setEditField
}
onDelete=
{
onDelete
}
/>
)
}
</
Draggable
>
);
})
}
</
Tbody
>
</
DndDrag
>
</
Table
>
</
TableContainer
>
</
Box
>
);
}
}),
[
t
,
editField
,
onChangeNode
,
nodeId
,
outputs
]
[
t
,
editField
,
zoom
,
onChangeNode
,
nodeId
,
outputs
]
);
return
(
...
...
@@ -223,3 +255,54 @@ const NodeFormInput = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
};
export
default
React
.
memo
(
NodeFormInput
);
const
TableItem
=
({
provided
,
snapshot
,
item
,
icon
,
setEditField
,
onDelete
}:
{
provided
:
DraggableProvided
;
snapshot
:
DraggableStateSnapshot
;
item
:
UserInputFormItemType
;
icon
:
string
;
setEditField
:
(
item
:
UserInputFormItemType
)
=>
void
;
onDelete
:
(
valueKey
:
string
)
=>
void
;
})
=>
{
return
(
<
Tr
ref=
{
provided
.
innerRef
}
{
...
provided
.
draggableProps
}
{
...
provided
.
dragHandleProps
}
style=
{
{
...
provided
.
draggableProps
.
style
,
opacity
:
snapshot
.
isDragging
?
0.8
:
1
}
}
>
<
Td
>
<
Flex
alignItems=
{
'center'
}
fontSize=
{
'mini'
}
fontWeight=
{
'medium'
}
whiteSpace=
{
'nowrap'
}
>
{
!!
icon
&&
<
MyIcon
name=
{
icon
as
any
}
w=
{
'14px'
}
mr=
{
1
}
color=
{
'myGray.400'
}
/>
}
{
item
.
label
}
</
Flex
>
</
Td
>
<
Td
>
{
item
.
description
||
'-'
}
</
Td
>
<
Td
>
{
item
.
required
?
(
<
Flex
alignItems=
{
'center'
}
>
<
MyIcon
name=
{
'check'
}
w=
{
'16px'
}
color=
{
'myGray.900'
}
mr=
{
2
}
/>
</
Flex
>
)
:
(
'-'
)
}
</
Td
>
<
Td
>
<
Flex
>
<
MyIconButton
icon=
{
'common/settingLight'
}
onClick=
{
()
=>
setEditField
(
item
)
}
/>
<
MyIconButton
icon=
{
'delete'
}
hoverColor=
{
'red.500'
}
onClick=
{
()
=>
onDelete
(
item
.
key
)
}
/>
</
Flex
>
</
Td
>
</
Tr
>
);
};
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeIfElse/index.tsx
View file @
c42deab6
...
...
@@ -3,7 +3,7 @@ import NodeCard from '../render/NodeCard';
import
{
useTranslation
}
from
'next-i18next'
;
import
{
Box
,
Button
,
Flex
}
from
'@chakra-ui/react'
;
import
{
NodeInputKeyEnum
}
from
'@fastgpt/global/core/workflow/constants'
;
import
{
NodeProps
,
Position
}
from
'reactflow'
;
import
{
NodeProps
,
Position
,
useViewport
}
from
'reactflow'
;
import
{
FlowNodeItemType
}
from
'@fastgpt/global/core/workflow/type/node'
;
import
{
IfElseListItemType
}
from
'@fastgpt/global/core/workflow/template/system/ifElse/type'
;
import
{
useContextSelector
}
from
'use-context-selector'
;
...
...
@@ -18,6 +18,7 @@ import { IfElseResultEnum } from '@fastgpt/global/core/workflow/template/system/
const
NodeIfElse
=
({
data
,
selected
}:
NodeProps
<
FlowNodeItemType
>
)
=>
{
const
{
t
}
=
useTranslation
();
const
{
nodeId
,
inputs
=
[]
}
=
data
;
const
{
zoom
}
=
useViewport
();
const
onChangeNode
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
.
onChangeNode
);
const
elseHandleId
=
getHandleId
(
nodeId
,
'source'
,
IfElseResultEnum
.
ELSE
);
...
...
@@ -63,6 +64,7 @@ const NodeIfElse = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
nodeId=
{
nodeId
}
/>
)
}
zoom=
{
zoom
}
>
{
(
provided
)
=>
(
<
Box
{
...
provided
.
droppableProps
}
ref=
{
provided
.
innerRef
}
>
...
...
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeUserSelect.tsx
View file @
c42deab6
import
React
,
{
useMemo
}
from
'react'
;
import
{
NodeProps
,
Position
}
from
'reactflow'
;
import
{
NodeProps
,
Position
,
useViewport
}
from
'reactflow'
;
import
{
Box
,
Button
,
HStack
,
Input
}
from
'@chakra-ui/react'
;
import
NodeCard
from
'./render/NodeCard'
;
import
{
FlowNodeItemType
}
from
'@fastgpt/global/core/workflow/type/node.d'
;
...
...
@@ -18,86 +18,72 @@ import { WorkflowContext } from '../../context';
import
{
UserSelectOptionItemType
}
from
'@fastgpt/global/core/workflow/template/system/interactive/type'
;
import
IOTitle
from
'../components/IOTitle'
;
import
RenderOutput
from
'./render/RenderOutput'
;
import
DndDrag
,
{
Draggable
,
DraggableProvided
,
DraggableStateSnapshot
}
from
'@fastgpt/web/components/common/DndDrag'
;
const
NodeUserSelect
=
({
data
,
selected
}:
NodeProps
<
FlowNodeItemType
>
)
=>
{
const
{
t
}
=
useTranslation
();
const
{
nodeId
,
inputs
,
outputs
}
=
data
;
const
onChangeNode
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
.
onChangeNode
);
const
{
zoom
}
=
useViewport
();
const
CustomComponent
=
useMemo
(
()
=>
({
[
NodeInputKeyEnum
.
userSelectOptions
]:
({
key
:
optionKey
,
value
=
[],
...
props
}:
FlowNodeInputItemType
)
=>
{
[
NodeInputKeyEnum
.
userSelectOptions
]:
(
v
:
FlowNodeInputItemType
)
=>
{
const
{
key
:
optionKey
,
value
,
...
props
}
=
v
;
const
options
=
value
as
UserSelectOptionItemType
[];
return
(
<
Box
>
{
options
.
map
((
item
,
i
)
=>
(
<
Box
key=
{
item
.
key
}
mb=
{
4
}
>
<
HStack
spacing=
{
1
}
>
<
MyTooltip
label=
{
t
(
'common:common.Delete'
)
}
>
<
MyIcon
mt=
{
0.5
}
name=
{
'minus'
}
w=
{
'0.8rem'
}
cursor=
{
'pointer'
}
color=
{
'myGray.600'
}
_hover=
{
{
color
:
'red.600'
}
}
onClick=
{
()
=>
{
onChangeNode
({
nodeId
,
type
:
'updateInput'
,
key
:
optionKey
,
value
:
{
...
props
,
key
:
optionKey
,
value
:
options
.
filter
((
input
)
=>
input
.
key
!==
item
.
key
)
}
});
}
}
/>
</
MyTooltip
>
<
Box
color=
{
'myGray.600'
}
fontWeight=
{
'medium'
}
fontSize=
{
'sm'
}
>
{
t
(
'common:option'
)
+
(
i
+
1
)
}
</
Box
>
</
HStack
>
<
Box
position=
{
'relative'
}
mt=
{
1
}
>
<
Input
defaultValue=
{
item
.
value
}
bg=
{
'white'
}
fontSize=
{
'sm'
}
onChange=
{
(
e
)
=>
{
const
newVal
=
options
.
map
((
val
)
=>
val
.
key
===
item
.
key
?
{
...
val
,
value
:
e
.
target
.
value
}
:
val
);
onChangeNode
({
nodeId
,
type
:
'updateInput'
,
key
:
optionKey
,
value
:
{
...
props
,
key
:
optionKey
,
value
:
newVal
}
});
}
}
/>
<
SourceHandle
nodeId=
{
nodeId
}
handleId=
{
getHandleId
(
nodeId
,
'source'
,
item
.
key
)
}
position=
{
Position
.
Right
}
translate=
{
[
34
,
0
]
}
/>
<
DndDrag
<
UserSelectOptionItemType
>
onDragEndCb=
{
(
list
)
=>
{
onChangeNode
({
nodeId
,
type
:
'updateInput'
,
key
:
optionKey
,
value
:
{
...
props
,
key
:
optionKey
,
value
:
list
}
});
}
}
dataList=
{
options
}
renderClone=
{
(
provided
,
snapshot
,
rubric
)
=>
(
<
OptionItem
provided=
{
provided
}
snapshot=
{
snapshot
}
item=
{
options
[
rubric
.
source
.
index
]
}
nodeId=
{
nodeId
}
itemValue=
{
v
}
index=
{
rubric
.
source
.
index
}
/>
)
}
zoom=
{
zoom
}
>
{
(
provided
)
=>
(
<
Box
ref=
{
provided
.
innerRef
}
{
...
provided
.
droppableProps
}
>
{
options
.
map
((
item
,
i
)
=>
(
<
Draggable
key=
{
item
.
key
}
index=
{
i
}
draggableId=
{
item
.
key
}
>
{
(
provided
,
snapshot
)
=>
(
<
OptionItem
provided=
{
provided
}
snapshot=
{
snapshot
}
item=
{
item
}
nodeId=
{
nodeId
}
itemValue=
{
v
}
index=
{
i
}
key=
{
item
.
key
}
/>
)
}
</
Draggable
>
))
}
</
Box
>
</
Box
>
))
}
)
}
</
DndDrag
>
<
Button
fontSize=
{
'sm'
}
leftIcon=
{
<
MyIcon
name=
{
'common/addLight'
}
w=
{
4
}
/>
}
...
...
@@ -120,7 +106,7 @@ const NodeUserSelect = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
);
}
}),
[
nodeId
,
onChangeNode
,
t
]
[
nodeId
,
onChangeNode
,
t
,
zoom
]
);
return
(
...
...
@@ -136,3 +122,100 @@ const NodeUserSelect = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
);
};
export
default
React
.
memo
(
NodeUserSelect
);
const
OptionItem
=
({
provided
,
snapshot
,
item
,
nodeId
,
itemValue
,
index
}:
{
provided
:
DraggableProvided
;
snapshot
:
DraggableStateSnapshot
;
item
:
UserSelectOptionItemType
;
nodeId
:
string
;
itemValue
:
FlowNodeInputItemType
;
index
:
number
;
})
=>
{
const
{
t
}
=
useTranslation
();
const
onChangeNode
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
.
onChangeNode
);
const
{
key
:
optionKey
,
value
,
...
props
}
=
itemValue
;
const
options
=
value
as
UserSelectOptionItemType
[];
return
(
<
Box
mb=
{
4
}
ref=
{
provided
.
innerRef
}
{
...
provided
.
draggableProps
}
{
...
provided
.
dragHandleProps
}
style=
{
{
...
provided
.
draggableProps
.
style
,
opacity
:
snapshot
.
isDragging
?
0.8
:
1
}
}
>
<
HStack
spacing=
{
1
}
>
<
MyTooltip
label=
{
t
(
'common:common.Delete'
)
}
>
<
MyIcon
mt=
{
0.5
}
name=
{
'minus'
}
w=
{
'0.8rem'
}
cursor=
{
'pointer'
}
color=
{
'myGray.600'
}
_hover=
{
{
color
:
'red.600'
}
}
onClick=
{
()
=>
{
onChangeNode
({
nodeId
,
type
:
'updateInput'
,
key
:
optionKey
,
value
:
{
...
props
,
key
:
optionKey
,
value
:
options
.
filter
((
input
)
=>
input
.
key
!==
item
.
key
)
}
});
}
}
/>
</
MyTooltip
>
<
Box
color=
{
'myGray.600'
}
fontWeight=
{
'medium'
}
fontSize=
{
'sm'
}
>
{
t
(
'common:option'
)
+
(
index
+
1
)
}
</
Box
>
</
HStack
>
<
Box
position=
{
'relative'
}
mt=
{
1
}
>
<
Input
defaultValue=
{
item
.
value
}
bg=
{
'white'
}
fontSize=
{
'sm'
}
onChange=
{
(
e
)
=>
{
const
newVal
=
options
.
map
((
val
)
=>
val
.
key
===
item
.
key
?
{
...
val
,
value
:
e
.
target
.
value
}
:
val
);
onChangeNode
({
nodeId
,
type
:
'updateInput'
,
key
:
optionKey
,
value
:
{
...
props
,
key
:
optionKey
,
value
:
newVal
}
});
}
}
/>
{
!
snapshot
.
isDragging
&&
(
<
SourceHandle
nodeId=
{
nodeId
}
handleId=
{
getHandleId
(
nodeId
,
'source'
,
item
.
key
)
}
position=
{
Position
.
Right
}
translate=
{
[
34
,
0
]
}
/>
)
}
</
Box
>
</
Box
>
);
};
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