@@ -2,6 +2,7 @@ import { compact, uniq } from 'lodash';
2
2
3
3
import {
4
4
osrdEditoastApi ,
5
+ type MacroNodeResponse ,
5
6
type SearchResultItemOperationalPoint ,
6
7
type TrainScheduleBase ,
7
8
type TrainScheduleResult ,
@@ -10,7 +11,7 @@ import type { AppDispatch } from 'store';
10
11
import { formatToIsoDate } from 'utils/date' ;
11
12
import { calculateTimeDifferenceInSeconds , formatDurationAsISO8601 } from 'utils/timeManipulation' ;
12
13
13
- import nodeStore from './nodeStore ' ;
14
+ import type MacroEditorState from './MacroEditorState ' ;
14
15
import { DEFAULT_TRAINRUN_FREQUENCIES , DEFAULT_TRAINRUN_FREQUENCY } from './osrdToNge' ;
15
16
import type {
16
17
NetzgrafikDto ,
@@ -375,28 +376,152 @@ const handleTrainrunOperation = async ({
375
376
}
376
377
} ;
377
378
378
- const handleUpdateNode = ( timeTableId : number , node : NodeDto ) => {
379
- const { betriebspunktName : trigram , positionX, positionY } = node ;
380
- nodeStore . set ( timeTableId , { trigram, positionX, positionY } ) ;
379
+ const apiCreateNode = async (
380
+ state : MacroEditorState ,
381
+ dispatch : AppDispatch ,
382
+ node : Omit < MacroNodeResponse , 'id' >
383
+ ) => {
384
+ try {
385
+ const createPromise = dispatch (
386
+ osrdEditoastApi . endpoints . postProjectsByProjectIdStudiesAndStudyIdScenariosScenarioIdMacroNodes . initiate (
387
+ {
388
+ projectId : state . scenario . project . id ,
389
+ studyId : state . scenario . study_id ,
390
+ scenarioId : state . scenario . id ,
391
+ macroNodeForm : node ,
392
+ }
393
+ )
394
+ ) ;
395
+ const newNode = await createPromise . unwrap ( ) ;
396
+ state . indexNode ( newNode , true ) ;
397
+ } catch ( e ) {
398
+ console . error ( e ) ;
399
+ }
400
+ } ;
401
+
402
+ const apiUpdateNode = async (
403
+ state : MacroEditorState ,
404
+ dispatch : AppDispatch ,
405
+ node : MacroNodeResponse
406
+ ) => {
407
+ try {
408
+ await dispatch (
409
+ osrdEditoastApi . endpoints . putProjectsByProjectIdStudiesAndStudyIdScenariosScenarioIdMacroNodesNodeId . initiate (
410
+ {
411
+ projectId : state . scenario . project . id ,
412
+ studyId : state . scenario . study_id ,
413
+ scenarioId : state . scenario . id ,
414
+ nodeId : node . id ,
415
+ macroNodeForm : node ,
416
+ }
417
+ )
418
+ ) ;
419
+ state . indexNode ( node , true ) ;
420
+ } catch ( e ) {
421
+ console . error ( e ) ;
422
+ }
423
+ } ;
424
+
425
+ const apiDeleteNode = async (
426
+ state : MacroEditorState ,
427
+ dispatch : AppDispatch ,
428
+ node : MacroNodeResponse
429
+ ) => {
430
+ try {
431
+ await dispatch (
432
+ osrdEditoastApi . endpoints . deleteProjectsByProjectIdStudiesAndStudyIdScenariosScenarioIdMacroNodesNodeId . initiate (
433
+ {
434
+ projectId : state . scenario . project . id ,
435
+ studyId : state . scenario . study_id ,
436
+ scenarioId : state . scenario . id ,
437
+ nodeId : node . id ,
438
+ }
439
+ )
440
+ ) ;
441
+ state . deleteNodeByKey ( node . path_item_key ) ;
442
+ } catch ( e ) {
443
+ console . error ( e ) ;
444
+ }
381
445
} ;
382
446
383
- const handleNodeOperation = ( {
447
+ /**
448
+ * Cast a NGE node to a node.
449
+ */
450
+ const castNgeNode = (
451
+ node : NetzgrafikDto [ 'nodes' ] [ 0 ] ,
452
+ labels : NetzgrafikDto [ 'labels' ]
453
+ ) : Omit < MacroNodeResponse , 'path_item_key' > => ( {
454
+ id : node . id ,
455
+ trigram : node . betriebspunktName ,
456
+ full_name : node . fullName ,
457
+ connection_time : node . connectionTime ,
458
+ position_x : node . positionX ,
459
+ position_y : node . positionY ,
460
+ labels : node . labelIds
461
+ . map ( ( id ) => {
462
+ const ngeLabel = labels . find ( ( e ) => e . id === id ) ;
463
+ if ( ngeLabel ) return ngeLabel . label ;
464
+ return null ;
465
+ } )
466
+ . filter ( ( n ) => n !== null ) as string [ ] ,
467
+ } ) ;
468
+
469
+ const handleNodeOperation = async ( {
470
+ state,
384
471
type,
385
472
node,
386
- timeTableId,
473
+ netzgrafikDto,
474
+ dispatch,
387
475
} : {
476
+ state : MacroEditorState ;
388
477
type : NGEEvent [ 'type' ] ;
389
478
node : NodeDto ;
390
- timeTableId : number ;
479
+ netzgrafikDto : NetzgrafikDto ;
480
+ dispatch : AppDispatch ;
391
481
} ) => {
482
+ const indexNode = state . getNodeById ( node . id ) ;
392
483
switch ( type ) {
393
484
case 'create' :
394
485
case 'update' : {
395
- handleUpdateNode ( timeTableId , node ) ;
486
+ if ( indexNode ) {
487
+ if ( indexNode . saved ) {
488
+ // Update the key if trigram has changed and key is based on it
489
+ let nodeKey = indexNode . node . path_item_key ;
490
+ if ( nodeKey . startsWith ( 'trigram:' ) && indexNode . node . trigram !== node . betriebspunktName ) {
491
+ nodeKey = `trigram:${ node . betriebspunktName } ` ;
492
+ }
493
+ await apiUpdateNode ( state , dispatch , {
494
+ ...indexNode . node ,
495
+ ...castNgeNode ( node , netzgrafikDto . labels ) ,
496
+ id : indexNode . node . id ,
497
+ path_item_key : nodeKey ,
498
+ } ) ;
499
+ } else {
500
+ const newNode = {
501
+ ...indexNode . node ,
502
+ ...castNgeNode ( node , netzgrafikDto . labels ) ,
503
+ } ;
504
+ // Create the node
505
+ await apiCreateNode ( state , dispatch , newNode ) ;
506
+ // keep track of the ID given by NGE
507
+ state . nodesIdToKey [ node . id ] = newNode . path_item_key ;
508
+ }
509
+ } else {
510
+ // It's an unknown node, we need to create it in the db
511
+ // We assume that `betriebspunktName` is a trigram
512
+ const key = `trigram:${ node . betriebspunktName } ` ;
513
+ // Create the node
514
+ await apiCreateNode ( state , dispatch , {
515
+ ...castNgeNode ( node , netzgrafikDto . labels ) ,
516
+ path_item_key : key ,
517
+ } ) ;
518
+ // keep track of the ID given by NGE
519
+ state . nodesIdToKey [ node . id ] = key ;
520
+ }
396
521
break ;
397
522
}
398
523
case 'delete' : {
399
- nodeStore . delete ( timeTableId , node . betriebspunktName ) ;
524
+ if ( indexNode ) await apiDeleteNode ( state , dispatch , indexNode . node ) ;
400
525
break ;
401
526
}
402
527
default :
@@ -445,6 +570,7 @@ const handleLabelOperation = async ({
445
570
const handleOperation = async ( {
446
571
event,
447
572
dispatch,
573
+ state,
448
574
infraId,
449
575
timeTableId,
450
576
netzgrafikDto,
@@ -453,6 +579,7 @@ const handleOperation = async ({
453
579
} : {
454
580
event : NGEEvent ;
455
581
dispatch : AppDispatch ;
582
+ state : MacroEditorState ;
456
583
infraId : number ;
457
584
timeTableId : number ;
458
585
netzgrafikDto : NetzgrafikDto ;
@@ -462,7 +589,7 @@ const handleOperation = async ({
462
589
const { type } = event ;
463
590
switch ( event . objectType ) {
464
591
case 'node' :
465
- handleNodeOperation ( { type, node : event . node , timeTableId } ) ;
592
+ await handleNodeOperation ( { state , dispatch , netzgrafikDto , type, node : event . node } ) ;
466
593
break ;
467
594
case 'trainrun' : {
468
595
await handleTrainrunOperation ( {
0 commit comments