Skip to content

Commit 2e3ad77

Browse files
committed
fix: connected propmt
1 parent 57a17a5 commit 2e3ad77

File tree

5 files changed

+121
-48
lines changed

5 files changed

+121
-48
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
type Props = {}
2+
3+
const ConditionDialog = (props: Props) => {
4+
return <div>ConditionDialog</div>
5+
}
6+
7+
export default ConditionDialog

client/src/components/pages/flow-detail/constant.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,16 @@ export const MAP_MESSAGE_TYPE: Record<
123123
label: i18n.t('flowDetail:message_dialog.message_types.list_card'),
124124
},
125125
}
126+
127+
export const CONDITIONAL_OPERATOR = [
128+
'==',
129+
'!=',
130+
'>',
131+
'>=',
132+
'<',
133+
'<=',
134+
'contains',
135+
'not_contains',
136+
'in',
137+
'not_in',
138+
]

client/src/components/pages/flow-detail/flow-inside.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const FlowInside = () => {
1818
handleDrop,
1919
handleInit,
2020
handleDoubleClickNode,
21+
handleDoubleClickEdge,
2122
} = useFlowCtx()
2223

2324
return (
@@ -34,6 +35,7 @@ export const FlowInside = () => {
3435
onDrop={handleDrop}
3536
onInit={handleInit}
3637
onNodeDoubleClick={handleDoubleClickNode}
38+
onEdgeDoubleClick={handleDoubleClickEdge}
3739
>
3840
<Background
3941
gap={24}

client/src/components/pages/flow-detail/flow-provider.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import {
1515
Edge,
1616
EdgeChange,
17+
EdgeMouseHandler,
1718
Node,
1819
NodeChange,
1920
NodeMouseHandler,
@@ -43,6 +44,9 @@ type FlowCtx = {
4344
handleDoubleClickNode: NodeMouseHandler
4445
handleChangeSelectedNode: (node: Node<any> | null) => void
4546
handleChangeLang: (lang: string) => void
47+
handleDoubleClickEdge: EdgeMouseHandler
48+
getNode: (id: string) => Node<any> | undefined
49+
getEdge: (id: string) => Edge<any> | undefined
4650
}
4751

4852
const FlowContext = createContext<FlowCtx | undefined>(undefined)
@@ -95,6 +99,7 @@ export const FlowProvider = ({ children, flow }: Props) => {
9599
},
96100
])
97101
const [selectedNode, setSelectedNode] = useState<Node<any> | null>(null)
102+
const [selectedEdge, setSelectedEdge] = useState<Edge<any> | null>(null)
98103
const [currentLang, setCurrentLang] = useState(
99104
flow.settings?.find((setting) => setting.type === 'language')?.value ||
100105
'en',
@@ -312,6 +317,26 @@ export const FlowProvider = ({ children, flow }: Props) => {
312317
[],
313318
)
314319

320+
const handleDoubleClickEdge: EdgeMouseHandler = useCallback(
321+
(_e, edge: Edge<any>) => {
322+
const sourceNode = _getNode(edge.source)
323+
324+
if (!sourceNode) {
325+
return
326+
}
327+
328+
if (
329+
sourceNode.data.action !== EActionTypes.PROMPT_AND_COLLECT &&
330+
sourceNode.data.action !== EActionTypes.CHECK_VARIABLES
331+
) {
332+
return
333+
}
334+
335+
setSelectedEdge(edge)
336+
},
337+
[_getNode],
338+
)
339+
315340
/**
316341
* Handles the change of the selected node.
317342
*
@@ -385,6 +410,9 @@ export const FlowProvider = ({ children, flow }: Props) => {
385410
handleChangeSelectedNode,
386411
currentLang,
387412
handleChangeLang,
413+
handleDoubleClickEdge,
414+
getNode: _getNode,
415+
getEdge,
388416
}}
389417
>
390418
{children}

client/src/components/pages/flow-detail/nodes.tsx

Lines changed: 71 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { cn } from '@/lib/utils'
2-
import { TNode } from '@/types/flow'
2+
import { EActionTypes, TNode } from '@/types/flow'
33
import {
44
Bolt,
55
Check,
@@ -10,16 +10,8 @@ import {
1010
Webhook,
1111
X,
1212
} from 'lucide-react'
13-
import { useMemo } from 'react'
14-
import {
15-
Handle,
16-
HandleProps,
17-
NodeProps,
18-
Position,
19-
getConnectedEdges,
20-
useNodeId,
21-
useStore,
22-
} from 'reactflow'
13+
import { Handle, HandleProps, NodeProps, Position } from 'reactflow'
14+
import { useFlowCtx } from '.'
2315
import { SOURCE_HANDLE_PROMPT_NO, SOURCE_HANDLE_PROMPT_YES } from './constant'
2416

2517
type CustomNodeProps = NodeProps<
@@ -38,36 +30,75 @@ const HandleCustom = ({
3830
style?: React.CSSProperties
3931
children?: React.ReactNode
4032
}) => {
41-
const { nodeInternals, edges } = useStore((s) => ({
42-
nodeInternals: s.nodeInternals,
43-
edges: s.edges,
44-
}))
45-
46-
const nodeId = useNodeId()
47-
48-
const isHandleConnectable = useMemo(() => {
49-
if (typeof props.isConnectable === 'function') {
50-
const node = nodeInternals.get(nodeId as string) as any
51-
const connectedEdges = getConnectedEdges([node], edges)
52-
53-
return props.isConnectable({ node, connectedEdges })
54-
}
55-
56-
if (typeof props.isConnectable === 'number') {
57-
const node = nodeInternals.get(nodeId as string) as any
58-
const connectedEdges = getConnectedEdges([node], edges)
59-
60-
return connectedEdges.length <= props.isConnectable
61-
}
62-
63-
return props.isConnectable
64-
}, [props, nodeInternals, nodeId, edges])
33+
const { nodes, edges } = useFlowCtx()
6534

6635
return (
6736
<Handle
6837
{...props}
6938
className={cn(' !bg-stone-600 !w-2 !h-2', className)}
70-
isConnectable={isHandleConnectable}
39+
isValidConnection={(connection) => {
40+
const sourcesFromHandleInState = edges.filter(
41+
(edge) => edge.source === connection.source,
42+
).length
43+
const sourceNode = nodes.find((node) => node.id === connection.source)
44+
45+
const targetFromHandleInState = edges.filter(
46+
(edge) => edge.target === connection.target,
47+
).length
48+
49+
if (
50+
sourceNode?.data.action === EActionTypes.START &&
51+
sourcesFromHandleInState < 2
52+
)
53+
return true
54+
55+
if (sourceNode?.data.action === EActionTypes.PROMPT_AND_COLLECT) {
56+
const numberOfYes = edges.filter((edge) => {
57+
return (
58+
edge.source === connection.source &&
59+
edge.sourceHandle === SOURCE_HANDLE_PROMPT_YES
60+
)
61+
}).length
62+
const numberOfNo = edges.filter(
63+
(edge) =>
64+
edge.source === connection.source &&
65+
edge.sourceHandle === SOURCE_HANDLE_PROMPT_NO,
66+
).length
67+
68+
if (
69+
numberOfYes === 1 &&
70+
connection.sourceHandle === SOURCE_HANDLE_PROMPT_YES
71+
)
72+
return false
73+
74+
if (
75+
numberOfNo === 1 &&
76+
connection.sourceHandle === SOURCE_HANDLE_PROMPT_NO
77+
)
78+
return false
79+
80+
const targetEdge = edges.find(
81+
(edge) =>
82+
edge.target === connection.target &&
83+
edge.source === connection.source &&
84+
edge.sourceHandle !== null,
85+
)
86+
87+
if (targetEdge) return false
88+
89+
return true
90+
}
91+
92+
if (
93+
sourceNode?.data.action === EActionTypes.CHECK_VARIABLES &&
94+
sourcesFromHandleInState < 2
95+
)
96+
return true
97+
98+
if (targetFromHandleInState === 1) return false
99+
if (sourcesFromHandleInState < 1) return true
100+
return false
101+
}}
71102
>
72103
{children ? children : null}
73104
</Handle>
@@ -82,7 +113,7 @@ export const StartNode = (props?: CustomNodeProps) => {
82113
<Bolt className='w-4 h-4' />
83114
<span className='leading-none'>{data?.label}</span>
84115
</div>
85-
<HandleCustom type='source' position={Position.Right} isConnectable={2} />
116+
<HandleCustom type='source' position={Position.Right} />
86117
</div>
87118
)
88119
}
@@ -95,7 +126,7 @@ export const FallBackNode = (props?: CustomNodeProps) => {
95126
<Webhook className='w-4 h-4' />
96127
<span className='leading-none'>{data?.label}</span>
97128
</div>
98-
<HandleCustom type='target' position={Position.Left} isConnectable={1} />
129+
<HandleCustom type='target' position={Position.Left} />
99130
</div>
100131
)
101132
}
@@ -109,11 +140,7 @@ export const NodeWrapper = (props?: {
109140
<div className={cn('bg-card shadow rounded-md p-2 border-card', className)}>
110141
{children}
111142
<HandleCustom type='target' position={Position.Top} isConnectable={1} />
112-
<HandleCustom
113-
type='source'
114-
position={Position.Bottom}
115-
isConnectable={1}
116-
/>
143+
<HandleCustom type='source' position={Position.Bottom} />
117144
</div>
118145
)
119146
}
@@ -138,11 +165,10 @@ export const PromptAndCollectNode = (props?: CustomNodeProps) => {
138165
<HelpCircle className='w-4 h-4' />
139166
<span className='leading-none'>{data?.name || data?.label}</span>
140167
</div>
141-
<HandleCustom type='target' position={Position.Top} isConnectable={1} />
168+
<HandleCustom type='target' position={Position.Top} />
142169
<HandleCustom
143170
type='source'
144171
position={Position.Bottom}
145-
isConnectable={2}
146172
id={SOURCE_HANDLE_PROMPT_NO}
147173
className='!w-4 !h-4 flex items-center justify-center !bg-red-500 !-bottom-2 text-white'
148174
style={{
@@ -154,7 +180,6 @@ export const PromptAndCollectNode = (props?: CustomNodeProps) => {
154180
<HandleCustom
155181
type='source'
156182
position={Position.Bottom}
157-
isConnectable={2}
158183
id={SOURCE_HANDLE_PROMPT_YES}
159184
style={{
160185
left: '20%',
@@ -184,7 +209,6 @@ export const CheckVariablesNode = (props?: CustomNodeProps) => {
184209
style={{
185210
left: '80%',
186211
}}
187-
isConnectable={2}
188212
>
189213
<X className='w-2 h-2 pointer-events-none' />
190214
</HandleCustom>
@@ -196,7 +220,6 @@ export const CheckVariablesNode = (props?: CustomNodeProps) => {
196220
left: '20%',
197221
}}
198222
className='!w-4 !h-4 flex items-center justify-center !bg-green-500 !-bottom-2 text-white'
199-
isConnectable={2}
200223
>
201224
<Check className='w-2 h-2 pointer-events-none' />
202225
</HandleCustom>

0 commit comments

Comments
 (0)