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