1
- import { createElement , DragEventHandler , Fragment , memo , ReactNode , useCallback , useContext , useEffect , useMemo , useRef , useState } from 'react'
2
- import { useNavigate } from 'react-router-dom'
1
+ import { createElement , DragEventHandler , Fragment , memo , ReactNode , SetStateAction , useCallback , useContext , useEffect , useMemo , useRef , useState } from 'react'
2
+ import { useBlocker , useNavigate } from 'react-router-dom'
3
3
import ReactFlow , {
4
4
addEdge ,
5
5
Background ,
@@ -493,25 +493,42 @@ export default function JourneyEditor() {
493
493
const journeyId = journey . id
494
494
495
495
const loadSteps = useCallback ( async ( ) => {
496
-
497
496
const steps = await api . journeys . steps . get ( project . id , journeyId )
498
497
499
498
const { edges, nodes } = stepsToNodes ( steps )
500
499
501
500
setNodes ( nodes )
502
501
setEdges ( edges )
503
-
504
502
} , [ project , journeyId ] )
505
503
506
504
useEffect ( ( ) => {
507
505
void loadSteps ( )
508
506
} , [ loadSteps ] )
509
507
510
508
const [ saving , setSaving ] = useState ( false )
509
+ const [ hasUnsavedChanges , setHasUnsavedChanges ] = useState ( false )
510
+
511
+ const blocker = useBlocker (
512
+ ( { currentLocation, nextLocation } ) => hasUnsavedChanges && currentLocation . pathname !== nextLocation . pathname ,
513
+ )
514
+
515
+ useEffect ( ( ) => {
516
+ if ( blocker . state !== 'blocked' ) return
517
+ if ( confirm ( t ( 'confirm_unsaved_changes' ) ) ) {
518
+ blocker . proceed ( )
519
+ } else {
520
+ blocker . reset ( )
521
+ }
522
+ } , [ blocker . state ] )
523
+
524
+ const handleSetNodes = ( nodes : SetStateAction < Array < Node < any , string | undefined > > > ) => {
525
+ setHasUnsavedChanges ( true )
526
+ setNodes ( nodes )
527
+ }
528
+
511
529
const saveSteps = useCallback ( async ( ) => {
512
530
513
531
setSaving ( true )
514
-
515
532
try {
516
533
const stepMap = await api . journeys . steps . set ( project . id , journey . id , nodesToSteps ( nodes , edges ) )
517
534
@@ -524,6 +541,7 @@ export default function JourneyEditor() {
524
541
} catch ( error : any ) {
525
542
toast . error ( `Unable to save: ${ error } ` )
526
543
} finally {
544
+ setHasUnsavedChanges ( false )
527
545
setSaving ( false )
528
546
}
529
547
} , [ project , journey , nodes , edges ] )
@@ -580,7 +598,7 @@ export default function JourneyEditor() {
580
598
} ,
581
599
}
582
600
583
- setNodes ( nds => nds . concat ( newStep ) )
601
+ handleSetNodes ( nds => nds . concat ( newStep ) )
584
602
585
603
} , [ setNodes , flowInstance , project , journey ] )
586
604
@@ -658,7 +676,7 @@ export default function JourneyEditor() {
658
676
label = { t ( 'name' ) }
659
677
name = "name"
660
678
value = { editNode . data . name ?? '' }
661
- onChange = { name => setNodes ( nds => nds . map ( n => n . id === editNode . id ? { ...n , data : { ...n . data , name } } : n ) ) }
679
+ onChange = { name => handleSetNodes ( nds => nds . map ( n => n . id === editNode . id ? { ...n , data : { ...n . data , name } } : n ) ) }
662
680
/>
663
681
{
664
682
type . hasDataKey && (
@@ -667,14 +685,14 @@ export default function JourneyEditor() {
667
685
subtitle = { t ( 'data_key_description' ) }
668
686
name = "data_key"
669
687
value = { editNode . data . data_key }
670
- onChange = { data_key => setNodes ( nds => nds . map ( n => n . id === editNode . id ? { ...n , data : { ...n . data , data_key } } : n ) ) }
688
+ onChange = { data_key => handleSetNodes ( nds => nds . map ( n => n . id === editNode . id ? { ...n , data : { ...n . data , data_key } } : n ) ) }
671
689
/>
672
690
)
673
691
}
674
692
{
675
693
type . Edit && createElement ( type . Edit , {
676
694
value : editNode . data . data ?? { } ,
677
- onChange : data => setNodes ( nds => nds . map ( n => n . id === editNode . id
695
+ onChange : data => handleSetNodes ( nds => nds . map ( n => n . id === editNode . id
678
696
? {
679
697
...editNode ,
680
698
data : {
0 commit comments