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
7c829feb
authored
Sep 29, 2024
by
heheer
Committed by
GitHub
Sep 29, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add context menu & comment node (#2834)
* feat: add comment node * useMemo
parent
7bdff9ce
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
345 additions
and
17 deletions
+345
-17
packages/global/core/workflow/constants.ts
+5
-1
packages/global/core/workflow/node/constant.ts
+2
-1
packages/global/core/workflow/template/system/comment.ts
+40
-0
packages/service/core/workflow/dispatch/index.ts
+1
-0
packages/web/components/common/Icon/constants.ts
+1
-0
packages/web/components/common/Icon/icons/comment.svg
+4
-0
packages/web/i18n/en/workflow.json
+2
-0
packages/web/i18n/zh/workflow.json
+3
-0
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/ContextMenu.tsx
+83
-0
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx
+24
-3
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx
+10
-3
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeComment.tsx
+128
-0
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx
+27
-8
projects/app/src/pages/app/detail/components/WorkflowComponents/context.tsx
+15
-1
No files found.
packages/global/core/workflow/constants.ts
View file @
7c829feb
...
@@ -151,7 +151,11 @@ export enum NodeInputKeyEnum {
...
@@ -151,7 +151,11 @@ export enum NodeInputKeyEnum {
loopEndInput
=
'loopEndInput'
,
loopEndInput
=
'loopEndInput'
,
// form input
// form input
userInputForms
=
'userInputForms'
userInputForms
=
'userInputForms'
,
// comment
commentText
=
'commentText'
,
commentSize
=
'commentSize'
}
}
export
enum
NodeOutputKeyEnum
{
export
enum
NodeOutputKeyEnum
{
...
...
packages/global/core/workflow/node/constant.ts
View file @
7c829feb
...
@@ -130,7 +130,8 @@ export enum FlowNodeTypeEnum {
...
@@ -130,7 +130,8 @@ export enum FlowNodeTypeEnum {
loop
=
'loop'
,
loop
=
'loop'
,
loopStart
=
'loopStart'
,
loopStart
=
'loopStart'
,
loopEnd
=
'loopEnd'
,
loopEnd
=
'loopEnd'
,
formInput
=
'formInput'
formInput
=
'formInput'
,
comment
=
'comment'
}
}
// node IO value type
// node IO value type
...
...
packages/global/core/workflow/template/system/comment.ts
0 → 100644
View file @
7c829feb
import
{
FlowNodeTypeEnum
}
from
'../../node/constant'
;
import
{
FlowNodeTemplateType
}
from
'../../type/node.d'
;
import
{
FlowNodeTemplateTypeEnum
,
NodeInputKeyEnum
,
WorkflowIOValueTypeEnum
}
from
'../../constants'
;
import
{
getHandleConfig
}
from
'../utils'
;
export
const
CommentNode
:
FlowNodeTemplateType
=
{
id
:
FlowNodeTypeEnum
.
comment
,
templateType
:
FlowNodeTemplateTypeEnum
.
systemInput
,
flowNodeType
:
FlowNodeTypeEnum
.
comment
,
sourceHandle
:
getHandleConfig
(
false
,
false
,
false
,
false
),
targetHandle
:
getHandleConfig
(
false
,
false
,
false
,
false
),
avatar
:
''
,
name
:
''
,
intro
:
''
,
version
:
'4811'
,
inputs
:
[
{
key
:
NodeInputKeyEnum
.
commentText
,
renderTypeList
:
[],
valueType
:
WorkflowIOValueTypeEnum
.
string
,
label
:
''
,
value
:
''
},
{
key
:
NodeInputKeyEnum
.
commentSize
,
renderTypeList
:
[],
valueType
:
WorkflowIOValueTypeEnum
.
object
,
label
:
''
,
value
:
{
width
:
240
,
height
:
140
}
}
],
outputs
:
[]
};
packages/service/core/workflow/dispatch/index.ts
View file @
7c829feb
...
@@ -107,6 +107,7 @@ const callbackMap: Record<FlowNodeTypeEnum, Function> = {
...
@@ -107,6 +107,7 @@ const callbackMap: Record<FlowNodeTypeEnum, Function> = {
[
FlowNodeTypeEnum
.
pluginConfig
]:
()
=>
Promise
.
resolve
(),
[
FlowNodeTypeEnum
.
pluginConfig
]:
()
=>
Promise
.
resolve
(),
[
FlowNodeTypeEnum
.
emptyNode
]:
()
=>
Promise
.
resolve
(),
[
FlowNodeTypeEnum
.
emptyNode
]:
()
=>
Promise
.
resolve
(),
[
FlowNodeTypeEnum
.
globalVariable
]:
()
=>
Promise
.
resolve
(),
[
FlowNodeTypeEnum
.
globalVariable
]:
()
=>
Promise
.
resolve
(),
[
FlowNodeTypeEnum
.
comment
]:
()
=>
Promise
.
resolve
(),
[
FlowNodeTypeEnum
.
runApp
]:
dispatchAppRequest
// abandoned
[
FlowNodeTypeEnum
.
runApp
]:
dispatchAppRequest
// abandoned
};
};
...
...
packages/web/components/common/Icon/constants.ts
View file @
7c829feb
...
@@ -7,6 +7,7 @@ export const iconPaths = {
...
@@ -7,6 +7,7 @@ export const iconPaths = {
closeSolid
:
()
=>
import
(
'./icons/closeSolid.svg'
),
closeSolid
:
()
=>
import
(
'./icons/closeSolid.svg'
),
collectionLight
:
()
=>
import
(
'./icons/collectionLight.svg'
),
collectionLight
:
()
=>
import
(
'./icons/collectionLight.svg'
),
collectionSolid
:
()
=>
import
(
'./icons/collectionSolid.svg'
),
collectionSolid
:
()
=>
import
(
'./icons/collectionSolid.svg'
),
comment
:
()
=>
import
(
'./icons/comment.svg'
),
'common/add2'
:
()
=>
import
(
'./icons/common/add2.svg'
),
'common/add2'
:
()
=>
import
(
'./icons/common/add2.svg'
),
'common/addCircleLight'
:
()
=>
import
(
'./icons/common/addCircleLight.svg'
),
'common/addCircleLight'
:
()
=>
import
(
'./icons/common/addCircleLight.svg'
),
'common/addLight'
:
()
=>
import
(
'./icons/common/addLight.svg'
),
'common/addLight'
:
()
=>
import
(
'./icons/common/addLight.svg'
),
...
...
packages/web/components/common/Icon/icons/comment.svg
0 → 100644
View file @
7c829feb
<svg
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 16 17"
>
<path
fill-rule=
"evenodd"
clip-rule=
"evenodd"
d=
"M10.7746 2.90224H5.22543C4.67152 2.90224 4.33762 2.90331 4.08927 2.92394C3.91796 2.93817 3.85352 2.95783 3.83939 2.96308C3.74318 3.01345 3.66463 3.09199 3.61426 3.18821C3.60902 3.20234 3.58935 3.26677 3.57512 3.43809C3.5545 3.68644 3.55343 4.02034 3.55343 4.57424V12.4544C3.55343 13.1464 3.55481 13.5712 3.58283 13.8723C3.58462 13.8915 3.58646 13.9093 3.58832 13.9258C3.60297 13.9181 3.61873 13.9096 3.63562 13.9002C3.90035 13.754 4.2523 13.5161 4.82438 13.1268L6.49832 11.9875C6.51469 11.9764 6.53278 11.9638 6.55248 11.9502C6.7415 11.8192 7.07919 11.5851 7.47593 11.4903C7.79844 11.4133 8.13446 11.4124 8.45734 11.4879C8.85455 11.5808 9.19338 11.8131 9.38304 11.9432C9.40281 11.9568 9.42096 11.9692 9.43739 11.9803L11.1789 13.153C11.7501 13.5377 12.1011 13.7724 12.365 13.9165C12.3817 13.9256 12.3974 13.934 12.4119 13.9415C12.4137 13.9252 12.4156 13.9076 12.4173 13.8886C12.4452 13.5892 12.4466 13.167 12.4466 12.4784V4.57424C12.4466 4.02034 12.4455 3.68644 12.4249 3.43809C12.4107 3.26677 12.391 3.20233 12.3857 3.18821C12.3354 3.09199 12.2568 3.01345 12.1606 2.96308C12.1465 2.95783 12.082 2.93816 11.9107 2.92394C11.6624 2.90331 11.3285 2.90224 10.7746 2.90224ZM2.43025 2.57509C2.22009 2.97967 2.22009 3.51119 2.22009 4.57424V12.4544C2.22009 13.7844 2.22009 14.4495 2.50121 14.8107C2.73556 15.1118 3.08767 15.2981 3.46845 15.3224C3.92523 15.3516 4.47501 14.9774 5.57457 14.229L7.24851 13.0898C7.51151 12.9108 7.64301 12.8213 7.78582 12.7871C7.90675 12.7582 8.03276 12.7579 8.15384 12.7862C8.29681 12.8197 8.42875 12.9085 8.69263 13.0862L10.4342 14.259C11.5318 14.9981 12.0805 15.3677 12.5361 15.337C12.9159 15.3115 13.2667 15.1248 13.5 14.824C13.7799 14.4633 13.7799 13.8017 13.7799 12.4784V4.57424C13.7799 3.51119 13.7799 2.97967 13.5697 2.57509C13.3926 2.23416 13.1147 1.95617 12.7737 1.77907C12.3691 1.56891 11.8376 1.56891 10.7746 1.56891H5.22543C4.16238 1.56891 3.63085 1.56891 3.22627 1.77907C2.88534 1.95617 2.60736 2.23416 2.43025 2.57509Z"
/>
</svg>
\ No newline at end of file
packages/web/i18n/en/workflow.json
View file @
7c829feb
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
"contains"
:
"Contains"
,
"contains"
:
"Contains"
,
"content_to_retrieve"
:
"Content to Retrieve"
,
"content_to_retrieve"
:
"Content to Retrieve"
,
"content_to_search"
:
"Content to Search"
,
"content_to_search"
:
"Content to Search"
,
"context_menu.add_comment"
:
"Add comment"
,
"create_link_error"
:
"Error creating link"
,
"create_link_error"
:
"Error creating link"
,
"custom_feedback"
:
"Custom Feedback"
,
"custom_feedback"
:
"Custom Feedback"
,
"custom_input"
:
"Custom Input"
,
"custom_input"
:
"Custom Input"
,
...
@@ -38,6 +39,7 @@
...
@@ -38,6 +39,7 @@
"edit_input"
:
"Edit Input"
,
"edit_input"
:
"Edit Input"
,
"edit_output"
:
"Edit output"
,
"edit_output"
:
"Edit output"
,
"end_with"
:
"Ends With"
,
"end_with"
:
"Ends With"
,
"enter_comment"
:
"Enter comment"
,
"error_info_returns_empty_on_success"
:
"Error information of code execution, returns empty on success"
,
"error_info_returns_empty_on_success"
:
"Error information of code execution, returns empty on success"
,
"execute_a_simple_script_code_usually_for_complex_data_processing"
:
"Execute a simple script code, usually for complex data processing."
,
"execute_a_simple_script_code_usually_for_complex_data_processing"
:
"Execute a simple script code, usually for complex data processing."
,
"execute_different_branches_based_on_conditions"
:
"Execute different branches based on conditions."
,
"execute_different_branches_based_on_conditions"
:
"Execute different branches based on conditions."
,
...
...
packages/web/i18n/zh/workflow.json
View file @
7c829feb
...
@@ -24,6 +24,8 @@
...
@@ -24,6 +24,8 @@
"contains"
:
"包含"
,
"contains"
:
"包含"
,
"content_to_retrieve"
:
"需要检索的内容"
,
"content_to_retrieve"
:
"需要检索的内容"
,
"content_to_search"
:
"需要检索的内容"
,
"content_to_search"
:
"需要检索的内容"
,
"contextMenu.addComment"
:
"添加注释"
,
"context_menu.add_comment"
:
"添加注释"
,
"create_link_error"
:
"创建链接异常"
,
"create_link_error"
:
"创建链接异常"
,
"custom_feedback"
:
"自定义反馈"
,
"custom_feedback"
:
"自定义反馈"
,
"custom_input"
:
"自定义输入"
,
"custom_input"
:
"自定义输入"
,
...
@@ -38,6 +40,7 @@
...
@@ -38,6 +40,7 @@
"edit_input"
:
"编辑输入"
,
"edit_input"
:
"编辑输入"
,
"edit_output"
:
"编辑输出"
,
"edit_output"
:
"编辑输出"
,
"end_with"
:
"结束为"
,
"end_with"
:
"结束为"
,
"enter_comment"
:
"输入注释"
,
"error_info_returns_empty_on_success"
:
"代码运行错误信息,成功时返回空"
,
"error_info_returns_empty_on_success"
:
"代码运行错误信息,成功时返回空"
,
"execute_a_simple_script_code_usually_for_complex_data_processing"
:
"执行一段简单的脚本代码,通常用于进行复杂的数据处理。"
,
"execute_a_simple_script_code_usually_for_complex_data_processing"
:
"执行一段简单的脚本代码,通常用于进行复杂的数据处理。"
,
"execute_different_branches_based_on_conditions"
:
"根据一定的条件,执行不同的分支。"
,
"execute_different_branches_based_on_conditions"
:
"根据一定的条件,执行不同的分支。"
,
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/ContextMenu.tsx
0 → 100644
View file @
7c829feb
import
{
Box
,
Flex
}
from
'@chakra-ui/react'
;
import
React
from
'react'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
import
{
useTranslation
}
from
'react-i18next'
;
import
{
nodeTemplate2FlowNode
}
from
'@/web/core/workflow/utils'
;
import
{
CommentNode
}
from
'@fastgpt/global/core/workflow/template/system/comment'
;
import
{
useContextSelector
}
from
'use-context-selector'
;
import
{
WorkflowContext
}
from
'../../context'
;
import
{
useReactFlow
}
from
'reactflow'
;
type
ContextMenuProps
=
{
top
:
number
;
left
:
number
;
};
const
ContextMenu
=
({
top
,
left
}:
ContextMenuProps
)
=>
{
const
{
t
}
=
useTranslation
();
const
setNodes
=
useContextSelector
(
WorkflowContext
,
(
ctx
)
=>
ctx
.
setNodes
);
const
setMenu
=
useContextSelector
(
WorkflowContext
,
(
ctx
)
=>
ctx
.
setMenu
);
const
{
screenToFlowPosition
}
=
useReactFlow
();
const
newNode
=
nodeTemplate2FlowNode
({
template
:
CommentNode
,
position
:
screenToFlowPosition
({
x
:
left
,
y
:
top
}),
t
});
return
(
<
Box
position=
"relative"
>
<
Box
position=
"absolute"
top=
{
`${top - 6}px`
}
left=
{
`${left + 10}px`
}
width=
{
0
}
height=
{
0
}
borderLeft=
"6px solid transparent"
borderRight=
"6px solid transparent"
borderBottom=
"6px solid white"
zIndex=
{
2
}
filter=
"drop-shadow(0px -1px 2px rgba(0, 0, 0, 0.1))"
/>
<
Flex
position=
{
'absolute'
}
top=
{
top
}
left=
{
left
}
bg=
{
'white'
}
w=
{
'120px'
}
height=
{
9
}
p=
{
1
}
rounded=
{
'md'
}
boxShadow=
{
'0px 2px 4px 0px #A1A7B340'
}
className=
"context-menu"
alignItems=
{
'center'
}
color=
{
'myGray.600'
}
cursor=
{
'pointer'
}
_hover=
{
{
color
:
'primary.500'
}
}
onClick=
{
()
=>
{
setMenu
(
null
);
setNodes
((
state
)
=>
{
const
newState
=
state
.
map
((
node
)
=>
({
...
node
,
selected
:
false
}))
// @ts-ignore
.
concat
(
newNode
);
return
newState
;
});
}
}
zIndex=
{
1
}
>
<
MyIcon
name=
"comment"
w=
{
'16px'
}
h=
{
'16px'
}
ml=
{
1
}
/>
<
Box
fontSize=
{
'12px'
}
fontWeight=
{
'500'
}
ml=
{
1.5
}
>
{
t
(
'workflow:context_menu.add_comment'
)
}
</
Box
>
</
Flex
>
</
Box
>
);
};
export
default
React
.
memo
(
ContextMenu
);
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx
View file @
7c829feb
...
@@ -282,7 +282,8 @@ export const useWorkflow = () => {
...
@@ -282,7 +282,8 @@ export const useWorkflow = () => {
setEdges
,
setEdges
,
onChangeNode
,
onChangeNode
,
onEdgesChange
,
onEdgesChange
,
setHoverEdgeId
setHoverEdgeId
,
setMenu
}
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
);
}
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
);
const
{
getIntersectingNodes
}
=
useReactFlow
();
const
{
getIntersectingNodes
}
=
useReactFlow
();
...
@@ -599,7 +600,7 @@ export const useWorkflow = () => {
...
@@ -599,7 +600,7 @@ export const useWorkflow = () => {
connect
connect
});
});
},
},
[
onConnect
,
t
,
toast
,
nodes
]
[
onConnect
,
t
,
toast
]
);
);
/* edge */
/* edge */
...
@@ -613,6 +614,24 @@ export const useWorkflow = () => {
...
@@ -613,6 +614,24 @@ export const useWorkflow = () => {
setHoverEdgeId
(
undefined
);
setHoverEdgeId
(
undefined
);
},
[
setHoverEdgeId
]);
},
[
setHoverEdgeId
]);
// context menu
const
onPaneContextMenu
=
useCallback
(
(
e
:
any
)
=>
{
// Prevent native context menu from showing
e
.
preventDefault
();
setMenu
({
top
:
e
.
clientY
-
64
,
left
:
e
.
clientX
-
12
});
},
[
setMenu
]
);
const
onPaneClick
=
useCallback
(()
=>
{
setMenu
(
null
);
},
[
setMenu
]);
return
{
return
{
handleNodesChange
,
handleNodesChange
,
handleEdgeChange
,
handleEdgeChange
,
...
@@ -624,7 +643,9 @@ export const useWorkflow = () => {
...
@@ -624,7 +643,9 @@ export const useWorkflow = () => {
onEdgeMouseLeave
,
onEdgeMouseLeave
,
helperLineHorizontal
,
helperLineHorizontal
,
helperLineVertical
,
helperLineVertical
,
onNodeDragStop
onNodeDragStop
,
onPaneContextMenu
,
onPaneClick
};
};
};
};
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx
View file @
7c829feb
...
@@ -17,6 +17,7 @@ import { WorkflowContext } from '../context';
...
@@ -17,6 +17,7 @@ import { WorkflowContext } from '../context';
import
{
useWorkflow
}
from
'./hooks/useWorkflow'
;
import
{
useWorkflow
}
from
'./hooks/useWorkflow'
;
import
HelperLines
from
'./components/HelperLines'
;
import
HelperLines
from
'./components/HelperLines'
;
import
FlowController
from
'./components/FlowController'
;
import
FlowController
from
'./components/FlowController'
;
import
ContextMenu
from
'./components/ContextMenu'
;
export
const
minZoom
=
0.1
;
export
const
minZoom
=
0.1
;
export
const
maxZoom
=
1.5
;
export
const
maxZoom
=
1.5
;
...
@@ -57,14 +58,15 @@ const nodeTypes: Record<FlowNodeTypeEnum, any> = {
...
@@ -57,14 +58,15 @@ const nodeTypes: Record<FlowNodeTypeEnum, any> = {
[
FlowNodeTypeEnum
.
loop
]:
dynamic
(()
=>
import
(
'./nodes/Loop/NodeLoop'
)),
[
FlowNodeTypeEnum
.
loop
]:
dynamic
(()
=>
import
(
'./nodes/Loop/NodeLoop'
)),
[
FlowNodeTypeEnum
.
loopStart
]:
dynamic
(()
=>
import
(
'./nodes/Loop/NodeLoopStart'
)),
[
FlowNodeTypeEnum
.
loopStart
]:
dynamic
(()
=>
import
(
'./nodes/Loop/NodeLoopStart'
)),
[
FlowNodeTypeEnum
.
loopEnd
]:
dynamic
(()
=>
import
(
'./nodes/Loop/NodeLoopEnd'
)),
[
FlowNodeTypeEnum
.
loopEnd
]:
dynamic
(()
=>
import
(
'./nodes/Loop/NodeLoopEnd'
)),
[
FlowNodeTypeEnum
.
formInput
]:
dynamic
(()
=>
import
(
'./nodes/NodeFormInput'
))
[
FlowNodeTypeEnum
.
formInput
]:
dynamic
(()
=>
import
(
'./nodes/NodeFormInput'
)),
[
FlowNodeTypeEnum
.
comment
]:
dynamic
(()
=>
import
(
'./nodes/NodeComment'
))
};
};
const
edgeTypes
=
{
const
edgeTypes
=
{
[
EDGE_TYPE
]:
ButtonEdge
[
EDGE_TYPE
]:
ButtonEdge
};
};
const
Workflow
=
()
=>
{
const
Workflow
=
()
=>
{
const
{
nodes
,
edges
,
reactFlowWrapper
,
workflowControlMode
}
=
useContextSelector
(
const
{
nodes
,
edges
,
menu
,
reactFlowWrapper
,
workflowControlMode
}
=
useContextSelector
(
WorkflowContext
,
WorkflowContext
,
(
v
)
=>
v
(
v
)
=>
v
);
);
...
@@ -79,7 +81,9 @@ const Workflow = () => {
...
@@ -79,7 +81,9 @@ const Workflow = () => {
onEdgeMouseLeave
,
onEdgeMouseLeave
,
helperLineHorizontal
,
helperLineHorizontal
,
helperLineVertical
,
helperLineVertical
,
onNodeDragStop
onNodeDragStop
,
onPaneContextMenu
,
onPaneClick
}
=
useWorkflow
();
}
=
useWorkflow
();
const
{
const
{
...
@@ -121,6 +125,7 @@ const Workflow = () => {
...
@@ -121,6 +125,7 @@ const Workflow = () => {
<
NodeTemplatesModal
isOpen=
{
isOpenTemplate
}
onClose=
{
onCloseTemplate
}
/>
<
NodeTemplatesModal
isOpen=
{
isOpenTemplate
}
onClose=
{
onCloseTemplate
}
/>
</>
</>
{
menu
&&
<
ContextMenu
{
...
menu
}
/>
}
<
ReactFlow
<
ReactFlow
ref=
{
reactFlowWrapper
}
ref=
{
reactFlowWrapper
}
fitView
fitView
...
@@ -142,6 +147,8 @@ const Workflow = () => {
...
@@ -142,6 +147,8 @@ const Workflow = () => {
onEdgeMouseEnter=
{
onEdgeMouseEnter
}
onEdgeMouseEnter=
{
onEdgeMouseEnter
}
onEdgeMouseLeave=
{
onEdgeMouseLeave
}
onEdgeMouseLeave=
{
onEdgeMouseLeave
}
panOnScrollSpeed=
{
2
}
panOnScrollSpeed=
{
2
}
onPaneContextMenu=
{
onPaneContextMenu
}
onPaneClick=
{
onPaneClick
}
{
...
(
workflowControlMode
===
'
select
'
{
...
(
workflowControlMode
===
'
select
'
?
{
?
{
selectionMode
:
SelectionMode
.
Full
,
selectionMode
:
SelectionMode
.
Full
,
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeComment.tsx
0 → 100644
View file @
7c829feb
import
React
,
{
useCallback
,
useMemo
,
useRef
,
useState
}
from
'react'
;
import
NodeCard
from
'./render/NodeCard'
;
import
{
NodeProps
}
from
'reactflow'
;
import
{
FlowNodeItemType
}
from
'@fastgpt/global/core/workflow/type/node'
;
import
{
Box
,
Textarea
}
from
'@chakra-ui/react'
;
import
{
useContextSelector
}
from
'use-context-selector'
;
import
{
WorkflowContext
}
from
'../../context'
;
import
{
NodeInputKeyEnum
}
from
'@fastgpt/global/core/workflow/constants'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
import
{
useTranslation
}
from
'react-i18next'
;
const
NodeComment
=
({
data
,
selected
}:
NodeProps
<
FlowNodeItemType
>
)
=>
{
const
{
nodeId
,
inputs
}
=
data
;
const
{
commentText
,
commentSize
}
=
useMemo
(
()
=>
({
commentText
:
inputs
.
find
((
item
)
=>
item
.
key
===
NodeInputKeyEnum
.
commentText
),
commentSize
:
inputs
.
find
((
item
)
=>
item
.
key
===
NodeInputKeyEnum
.
commentSize
)
}),
[
inputs
]
);
const
onChangeNode
=
useContextSelector
(
WorkflowContext
,
(
ctx
)
=>
ctx
.
onChangeNode
);
const
{
t
}
=
useTranslation
();
const
[
size
,
setSize
]
=
useState
<
{
width
:
number
;
height
:
number
;
}
>
(
commentSize
?.
value
);
const
initialY
=
useRef
(
0
);
const
initialX
=
useRef
(
0
);
const
handleMouseDown
=
useCallback
(
(
e
:
React
.
MouseEvent
)
=>
{
initialY
.
current
=
e
.
clientY
;
initialX
.
current
=
e
.
clientX
;
const
handleMouseMove
=
(
e
:
MouseEvent
)
=>
{
const
deltaY
=
e
.
clientY
-
initialY
.
current
;
const
deltaX
=
e
.
clientX
-
initialX
.
current
;
setSize
((
prevSize
)
=>
({
width
:
prevSize
.
width
+
deltaX
<
240
?
240
:
prevSize
.
width
+
deltaX
,
height
:
prevSize
.
height
+
deltaY
<
140
?
140
:
prevSize
.
height
+
deltaY
}));
initialY
.
current
=
e
.
clientY
;
initialX
.
current
=
e
.
clientX
;
commentSize
&&
onChangeNode
({
nodeId
:
nodeId
,
type
:
'updateInput'
,
key
:
NodeInputKeyEnum
.
commentSize
,
value
:
{
...
commentSize
,
value
:
{
width
:
size
.
width
+
deltaX
,
height
:
size
.
height
+
deltaY
}
}
});
};
const
handleMouseUp
=
()
=>
{
document
.
removeEventListener
(
'mousemove'
,
handleMouseMove
);
document
.
removeEventListener
(
'mouseup'
,
handleMouseUp
);
};
document
.
addEventListener
(
'mousemove'
,
handleMouseMove
);
document
.
addEventListener
(
'mouseup'
,
handleMouseUp
);
},
[
commentSize
,
nodeId
,
onChangeNode
,
size
.
height
,
size
.
width
]
);
return
(
<
NodeCard
selected=
{
false
}
{
...
data
}
minW=
{
`${size.width}px`
}
minH=
{
`${size.height}px`
}
menuForbid=
{
{
debug
:
true
}
}
border=
{
'none'
}
rounded=
{
'none'
}
bg=
{
'#D8E9FF'
}
boxShadow=
{
'0px 4px 10px 0px rgba(19, 51, 107, 0.10), 0px 0px 1px 0px rgba(19, 51, 107, 0.10)'
}
>
<
Box
w=
{
'full'
}
h=
{
'full'
}
position=
{
'relative'
}
>
<
Box
position=
{
'absolute'
}
right=
{
'0'
}
bottom=
{
'-2'
}
zIndex=
{
9
}
cursor=
{
'nwse-resize'
}
px=
{
'2px'
}
className=
"nodrag"
onMouseDown=
{
handleMouseDown
}
>
<
MyIcon
name=
{
'common/editor/resizer'
}
width=
{
'14px'
}
height=
{
'14px'
}
/>
</
Box
>
<
Textarea
value=
{
commentText
?.
value
}
border=
{
'none'
}
rounded=
{
'none'
}
minH=
{
`${size.height}px`
}
minW=
{
`${size.width}px`
}
resize=
{
'none'
}
placeholder=
{
t
(
'workflow:enter_comment'
)
}
onChange=
{
(
e
)
=>
{
commentText
&&
onChangeNode
({
nodeId
:
nodeId
,
type
:
'updateInput'
,
key
:
NodeInputKeyEnum
.
commentText
,
value
:
{
...
commentText
,
value
:
e
.
target
.
value
}
});
}
}
/>
</
Box
>
</
NodeCard
>
);
};
export
default
React
.
memo
(
NodeComment
);
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx
View file @
7c829feb
import
React
,
{
useCallback
,
useMemo
}
from
'react'
;
import
React
,
{
useCallback
,
useMemo
}
from
'react'
;
import
{
Box
,
Button
,
Card
,
Flex
,
Image
}
from
'@chakra-ui/react'
;
import
{
Box
,
Button
,
Card
,
Flex
,
FlexProps
,
Image
}
from
'@chakra-ui/react'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
import
Avatar
from
'@fastgpt/web/components/common/Avatar'
;
import
Avatar
from
'@fastgpt/web/components/common/Avatar'
;
import
type
{
FlowNodeItemType
}
from
'@fastgpt/global/core/workflow/type/node.d'
;
import
type
{
FlowNodeItemType
}
from
'@fastgpt/global/core/workflow/type/node.d'
;
...
@@ -39,7 +39,7 @@ type Props = FlowNodeItemType & {
...
@@ -39,7 +39,7 @@ type Props = FlowNodeItemType & {
copy
?:
boolean
;
copy
?:
boolean
;
delete
?:
boolean
;
delete
?:
boolean
;
};
};
};
}
&
Omit
<
FlexProps
,
'children'
>
;
const
NodeCard
=
(
props
:
Props
)
=>
{
const
NodeCard
=
(
props
:
Props
)
=>
{
const
{
t
}
=
useTranslation
();
const
{
t
}
=
useTranslation
();
...
@@ -62,7 +62,8 @@ const NodeCard = (props: Props) => {
...
@@ -62,7 +62,8 @@ const NodeCard = (props: Props) => {
isTool
=
false
,
isTool
=
false
,
isError
=
false
,
isError
=
false
,
debugResult
,
debugResult
,
isFolded
isFolded
,
...
customStyle
}
=
props
;
}
=
props
;
const
nodeList
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
.
nodeList
);
const
nodeList
=
useContextSelector
(
WorkflowContext
,
(
v
)
=>
v
.
nodeList
);
...
@@ -156,9 +157,12 @@ const NodeCard = (props: Props) => {
...
@@ -156,9 +157,12 @@ const NodeCard = (props: Props) => {
/* Node header */
/* Node header */
const
Header
=
useMemo
(()
=>
{
const
Header
=
useMemo
(()
=>
{
const
showHeader
=
node
?.
flowNodeType
!==
FlowNodeTypeEnum
.
comment
;
return
(
return
(
<
Box
position=
{
'relative'
}
>
<
Box
position=
{
'relative'
}
>
{
/* debug */
}
{
/* debug */
}
{
showHeader
&&
(
<
Box
px=
{
4
}
py=
{
3
}
>
<
Box
px=
{
4
}
py=
{
3
}
>
{
/* tool target handle */
}
{
/* tool target handle */
}
<
ToolTargetHandle
show=
{
showToolHandle
}
nodeId=
{
nodeId
}
/>
<
ToolTargetHandle
show=
{
showToolHandle
}
nodeId=
{
nodeId
}
/>
...
@@ -188,7 +192,13 @@ const NodeCard = (props: Props) => {
...
@@ -188,7 +192,13 @@ const NodeCard = (props: Props) => {
/>
/>
</
Box
>
</
Box
>
)
}
)
}
<
Avatar
src=
{
avatar
}
borderRadius=
{
'sm'
}
objectFit=
{
'contain'
}
w=
{
'30px'
}
h=
{
'30px'
}
/>
<
Avatar
src=
{
avatar
}
borderRadius=
{
'sm'
}
objectFit=
{
'contain'
}
w=
{
'30px'
}
h=
{
'30px'
}
/>
<
Box
ml=
{
3
}
fontSize=
{
'md'
}
fontWeight=
{
'medium'
}
>
<
Box
ml=
{
3
}
fontSize=
{
'md'
}
fontWeight=
{
'medium'
}
>
{
t
(
name
as
any
)
}
{
t
(
name
as
any
)
}
</
Box
>
</
Box
>
...
@@ -245,7 +255,12 @@ const NodeCard = (props: Props) => {
...
@@ -245,7 +255,12 @@ const NodeCard = (props: Props) => {
{
!!
nodeTemplate
?.
diagram
&&
!
hasNewVersion
&&
(
{
!!
nodeTemplate
?.
diagram
&&
!
hasNewVersion
&&
(
<
MyTooltip
<
MyTooltip
label=
{
label=
{
<
Image
src=
{
nodeTemplate
?.
diagram
}
w=
{
'100%'
}
minH=
{
[
'auto'
,
'200px'
]
}
alt=
{
''
}
/>
<
Image
src=
{
nodeTemplate
?.
diagram
}
w=
{
'100%'
}
minH=
{
[
'auto'
,
'200px'
]
}
alt=
{
''
}
/>
}
}
>
>
<
Box
<
Box
...
@@ -261,15 +276,17 @@ const NodeCard = (props: Props) => {
...
@@ -261,15 +276,17 @@ const NodeCard = (props: Props) => {
</
MyTooltip
>
</
MyTooltip
>
)
}
)
}
</
Flex
>
</
Flex
>
<
MenuRender
nodeId=
{
nodeId
}
menuForbid=
{
menuForbid
}
nodeList=
{
nodeList
}
/>
<
NodeIntro
nodeId=
{
nodeId
}
intro=
{
intro
}
/>
<
NodeIntro
nodeId=
{
nodeId
}
intro=
{
intro
}
/>
</
Box
>
</
Box
>
)
}
<
MenuRender
nodeId=
{
nodeId
}
menuForbid=
{
menuForbid
}
nodeList=
{
nodeList
}
/>
<
ConfirmSyncModal
/>
</
Box
>
</
Box
>
);
);
},
[
},
[
node
?.
flowNodeType
,
showToolHandle
,
showToolHandle
,
nodeId
,
nodeId
,
node
?.
flowNodeType
,
isFolded
,
isFolded
,
avatar
,
avatar
,
t
,
t
,
...
@@ -278,9 +295,10 @@ const NodeCard = (props: Props) => {
...
@@ -278,9 +295,10 @@ const NodeCard = (props: Props) => {
onOpenConfirmSync
,
onOpenConfirmSync
,
onClickSyncVersion
,
onClickSyncVersion
,
nodeTemplate
?.
diagram
,
nodeTemplate
?.
diagram
,
intro
,
menuForbid
,
menuForbid
,
nodeList
,
nodeList
,
intro
,
ConfirmSyncModal
,
onChangeNode
,
onChangeNode
,
onOpenCustomTitleModal
,
onOpenCustomTitleModal
,
toast
toast
...
@@ -334,6 +352,7 @@ const NodeCard = (props: Props) => {
...
@@ -334,6 +352,7 @@ const NodeCard = (props: Props) => {
:
{
:
{
borderColor
:
selected
?
'primary.600'
:
'borderColor.base'
borderColor
:
selected
?
'primary.600'
:
'borderColor.base'
}
)}
}
)}
{
...
customStyle
}
>
>
<
NodeDebugResponse
nodeId=
{
nodeId
}
debugResult=
{
debugResult
}
/>
<
NodeDebugResponse
nodeId=
{
nodeId
}
debugResult=
{
debugResult
}
/>
{
Header
}
{
Header
}
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/context.tsx
View file @
7c829feb
...
@@ -174,6 +174,11 @@ type WorkflowContextType = {
...
@@ -174,6 +174,11 @@ type WorkflowContextType = {
//
//
workflowControlMode
?:
'drag'
|
'select'
;
workflowControlMode
?:
'drag'
|
'select'
;
setWorkflowControlMode
:
(
value
?:
SetState
<
'drag'
|
'select'
>
|
undefined
)
=>
void
;
setWorkflowControlMode
:
(
value
?:
SetState
<
'drag'
|
'select'
>
|
undefined
)
=>
void
;
menu
:
{
top
:
number
;
left
:
number
;
}
|
null
;
setMenu
:
(
value
:
React
.
SetStateAction
<
{
top
:
number
;
left
:
number
}
|
null
>
)
=>
void
;
};
};
type
DebugDataType
=
{
type
DebugDataType
=
{
...
@@ -313,6 +318,10 @@ export const WorkflowContext = createContext<WorkflowContextType>({
...
@@ -313,6 +318,10 @@ export const WorkflowContext = createContext<WorkflowContextType>({
},
},
onSwitchCloudVersion
:
function
(
appVersion
:
AppVersionSchemaType
):
boolean
{
onSwitchCloudVersion
:
function
(
appVersion
:
AppVersionSchemaType
):
boolean
{
throw
new
Error
(
'Function not implemented.'
);
throw
new
Error
(
'Function not implemented.'
);
},
menu
:
null
,
setMenu
:
function
(
value
:
React
.
SetStateAction
<
{
top
:
number
;
left
:
number
}
|
null
>
):
void
{
throw
new
Error
(
'Function not implemented.'
);
}
}
});
});
...
@@ -973,6 +982,8 @@ const WorkflowContextProvider = ({
...
@@ -973,6 +982,8 @@ const WorkflowContextProvider = ({
};
};
},
[
edges
,
nodes
]);
},
[
edges
,
nodes
]);
const
[
menu
,
setMenu
]
=
useState
<
{
top
:
number
;
left
:
number
}
|
null
>
(
null
);
const
value
=
{
const
value
=
{
appId
,
appId
,
reactFlowWrapper
,
reactFlowWrapper
,
...
@@ -1032,7 +1043,10 @@ const WorkflowContextProvider = ({
...
@@ -1032,7 +1043,10 @@ const WorkflowContextProvider = ({
setShowHistoryModal
,
setShowHistoryModal
,
// chat test
// chat test
setWorkflowTestData
setWorkflowTestData
,
menu
,
setMenu
};
};
return
(
return
(
...
...
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