@@ -69,6 +69,7 @@ interface Message {
6969 type : MessageTypes ;
7070 text ?: string ;
7171 paths ?: { nodes : any [ ] , edges : any [ ] } [ ] ;
72+ graphName ?: string ;
7273}
7374
7475interface Props {
@@ -92,47 +93,52 @@ const SUGGESTIONS = [
9293
9394const RemoveLastPath = ( messages : Message [ ] ) => {
9495 const index = messages . findIndex ( ( m ) => m . type === MessageTypes . Path )
95-
96+
9697 if ( index !== - 1 ) {
9798 messages = [ ...messages . slice ( 0 , index - 2 ) , ...messages . slice ( index + 1 ) ] ;
9899 messages = RemoveLastPath ( messages )
99100 }
100-
101+
101102 return messages
102103}
103104
104105export function Chat ( { repo, path, setPath, graph, chartRef, selectedPathId, isPath, setIsPath } : Props ) {
105-
106+
106107 // Holds the messages in the chat
107108 const [ messages , setMessages ] = useState < Message [ ] > ( [ ] ) ;
108-
109+
109110 // Holds the messages in the chat
110111 const [ paths , setPaths ] = useState < { nodes : any [ ] , edges : any [ ] } [ ] > ( [ ] ) ;
111-
112+
112113 const [ selectedPath , setSelectedPath ] = useState < { nodes : any [ ] , edges : any [ ] } > ( ) ;
113-
114+
114115 // Holds the user input while typing
115116 const [ query , setQuery ] = useState ( '' ) ;
116-
117+
117118 const [ isPathResponse , setIsPathResponse ] = useState ( false ) ;
118-
119+
119120 const [ tipOpen , setTipOpen ] = useState ( false ) ;
120-
121+
121122 const [ sugOpen , setSugOpen ] = useState ( false ) ;
122-
123+
123124 // A reference to the chat container to allow scrolling to the bottom
124125 const containerRef : React . RefObject < HTMLDivElement > = useRef ( null ) ;
125-
126+
126127 const isSendMessage = messages . some ( m => m . type === MessageTypes . Pending ) || ( messages . some ( m => m . text === "Please select a starting point and the end point. Select or press relevant item on the graph" ) && ! messages . some ( m => m . type === MessageTypes . Path ) )
127-
128+
129+ useEffect ( ( ) => {
130+ setSelectedPath ( undefined )
131+ setIsPathResponse ( false )
132+ } , [ graph . Id ] )
133+
128134 useEffect ( ( ) => {
129135 const p = paths . find ( ( path ) => [ ...path . edges , ...path . nodes ] . some ( ( e : any ) => e . id === selectedPathId ) )
130-
136+
131137 if ( ! p ) return
132-
138+
133139 handleSetSelectedPath ( p )
134140 } , [ selectedPathId ] )
135-
141+
136142 // Scroll to the bottom of the chat on new message
137143 useEffect ( ( ) => {
138144 setTimeout ( ( ) => {
@@ -202,14 +208,28 @@ export function Chat({ repo, path, setPath, graph, chartRef, selectedPathId, isP
202208 } )
203209 chart . elements ( ) . filter ( el => [ ...p . nodes , ...p . edges ] . some ( e => e . id == el . id ( ) ) ) . layout ( LAYOUT ) . run ( ) ;
204210 } else {
205- chart . elements ( ) . filter ( el => [ ...p . nodes , ...p . edges ] . some ( e => e . id == el . id ( ) ) ) . forEach ( el => {
206- if ( el . id ( ) == p . nodes [ 0 ] . id || el . id ( ) == p . nodes [ p . nodes . length - 1 ] . id ) {
207- el . removeStyle ( ) . style ( SELECTED_PATH_NODE_STYLE ) ;
208- } else if ( el . isNode ( ) ) {
209- el . removeStyle ( ) . style ( PATH_NODE_STYLE ) ;
211+ const elements : any = { nodes : [ ] , edges : [ ] } ;
212+
213+ [ ...p . nodes , ...p . edges ] . forEach ( e => {
214+ let element = chart . elements ( `#${ e . id } ` )
215+ if ( element . length === 0 ) {
216+ const type = "src_node" in e
217+ e = type ? { ...e , id : e . id . slice ( 1 ) } : e
218+ type
219+ ? elements . edges . push ( e )
220+ : elements . nodes . push ( e )
210221 }
211- if ( el . isEdge ( ) ) {
212- el . removeStyle ( ) . style ( SELECTED_PATH_EDGE_STYLE ) ;
222+ } )
223+
224+ chart . add ( graph . extend ( elements ) )
225+ chart . elements ( ) . filter ( ( e ) => [ ...p . nodes , ...p . edges ] . some ( ( el ) => el . id == e . id ( ) ) ) . forEach ( ( e ) => {
226+ if ( e . id ( ) == p . nodes [ 0 ] . id || e . id ( ) == p . nodes [ p . nodes . length - 1 ] . id ) {
227+ e . removeStyle ( ) . style ( SELECTED_PATH_NODE_STYLE ) ;
228+ } else if ( e . isNode ( ) ) {
229+ e . removeStyle ( ) . style ( PATH_NODE_STYLE ) ;
230+ }
231+ if ( e . isEdge ( ) ) {
232+ e . removeStyle ( ) . style ( SELECTED_PATH_EDGE_STYLE ) ;
213233 }
214234 } ) . layout ( LAYOUT ) . run ( ) ;
215235 }
@@ -329,7 +349,7 @@ export function Chat({ repo, path, setPath, graph, chartRef, selectedPathId, isP
329349 } ) ;
330350 elements . layout ( LAYOUT ) . run ( )
331351 setPaths ( formattedPaths )
332- setMessages ( ( prev ) => [ ...RemoveLastPath ( prev ) , { type : MessageTypes . PathResponse , paths : formattedPaths } ] ) ;
352+ setMessages ( ( prev ) => [ ...RemoveLastPath ( prev ) , { type : MessageTypes . PathResponse , paths : formattedPaths , graphName : graph . Id } ] ) ;
333353 setPath ( undefined )
334354 setIsPathResponse ( true )
335355 }
@@ -341,7 +361,6 @@ export function Chat({ repo, path, setPath, graph, chartRef, selectedPathId, isP
341361 className = "Tip"
342362 onClick = { ( ) => {
343363 setTipOpen ( false )
344- setPath ( { } )
345364 setMessages ( prev => [
346365 ...RemoveLastPath ( prev ) ,
347366 { type : MessageTypes . Query , text : "Create a path" } ,
@@ -356,7 +375,10 @@ export function Chat({ repo, path, setPath, graph, chartRef, selectedPathId, isP
356375 type : MessageTypes . Response ,
357376 text : "Please select a starting point and the end point. Select or press relevant item on the graph"
358377 } ] ) , 300 )
359- setTimeout ( ( ) => setMessages ( prev => [ ...prev , { type : MessageTypes . Path } ] ) , 4000 )
378+ setTimeout ( ( ) => {
379+ setPath ( { } )
380+ setMessages ( prev => [ ...prev , { type : MessageTypes . Path } ] )
381+ } , 4000 )
360382 } }
361383 >
362384 < Lightbulb />
@@ -431,14 +453,22 @@ export function Chat({ repo, path, setPath, graph, chartRef, selectedPathId, isP
431453 message . paths . map ( ( p , i : number ) => (
432454 < button
433455 key = { i }
434- className = { cn ( "flex text-wrap border p-2 gap-2 rounded-md" , p . nodes . length === selectedPath ?. nodes . length && selectedPath ?. nodes . every ( node => p ?. nodes . some ( ( n ) => n . id === node . id ) ) && "border-[#FF66B3] bg-[#FFF0F7]" ) }
456+ className = { cn (
457+ "flex text-wrap border p-2 gap-2 rounded-md" ,
458+ p . nodes . length === selectedPath ?. nodes . length &&
459+ selectedPath ?. nodes . every ( node => p ?. nodes . some ( ( n ) => n . id === node . id ) ) && selectedPath . nodes . length === p . nodes . length && "border-[#FF66B3] bg-[#FFF0F7]" ,
460+ message . graphName !== graph . Id && "opacity-50 bg-gray-200"
461+ ) }
462+ title = { message . graphName !== graph . Id ? `Move to graph ${ message . graphName } to use this path` : undefined }
463+ disabled = { message . graphName !== graph . Id }
435464 onClick = { ( ) => {
436- if ( p . nodes . length === selectedPath ?. nodes . length && selectedPath ?. nodes . every ( node => p ?. nodes . some ( ( n ) => n . id === node . id ) ) ) return
437- handleSetSelectedPath ( p )
438- setIsPath ( true )
465+ if ( p . nodes . length === selectedPath ?. nodes . length &&
466+ selectedPath ?. nodes . every ( node => p ?. nodes . some ( ( n ) => n . id === node . id ) ) ) return ;
467+ handleSetSelectedPath ( p ) ;
468+ setIsPath ( true ) ;
439469 } }
440470 >
441- < p className = "font-bold" > #{ i } </ p >
471+ < p className = "font-bold" > #{ i + 1 } </ p >
442472 < div className = "flex flex-wrap" >
443473 {
444474 p . nodes . map ( ( node : any , j : number ) => (
0 commit comments