11import { getAgglomeratesForSegmentsFromTracingstore , getUpdateActionLog } from "admin/rest_api" ;
22import ErrorHandling from "libs/error_handling" ;
33import Toast from "libs/toast" ;
4- import { isNumberMap , sleep } from "libs/utils" ;
4+ import { getAdaptToTypeFunction , sleep } from "libs/utils" ;
55import _ from "lodash" ;
66import { buffers , type Channel } from "redux-saga" ;
77import { actionChannel , call , delay , flush , fork , put , race , takeEvery } from "typed-redux-saga" ;
@@ -404,8 +404,7 @@ export function* tryToIncorporateActions(
404404 case "updateUserBoundingBoxVisibilityInVolumeTracing" :
405405 case "updateSegmentGroupsExpandedState" : {
406406 if ( areUnsavedChangesOfUser ) {
407- // TODOM: Missing actions still need support in applyVolumeUpdateActionsFromServerAction
408- // TODOM: --------------------- User specific actions must be reapplied if local actions!!!!!! ------------------------------------------
407+ // Maybe write tests for these? Maybe part of M4
409408 yield * put ( applyVolumeUpdateActionsFromServerAction ( [ action ] ) ) ;
410409 }
411410 break ;
@@ -603,53 +602,61 @@ export function* tryToIncorporateActions(
603602 return { success : true } ;
604603}
605604
605+ type IdsToReloadPerMapping = Record < string , number [ ] > ;
606+
607+ // Gathers mapped agglomerate ids for unknown but relevant segments to apply the passed save queue entries correctly.
608+ // This is needed in case proofreading was done via mesh interactions whose mapping info is present in the meshes
609+ // but not in the activeMappingByLayer.mapping. Due to incorporating backend updates the agglomerate ids of the
610+ // meshes might be outdated, thus we reload this info and store it in the local mapping to perform the correct merge.
611+ // Returns a list of segment ids to reload for each needed volume / editable tracing id.
606612function * getAllUnknownSegmentIdsInPendingUpdates (
607613 saveQueue : SaveQueueEntry [ ] ,
608- ) : Saga < Record < string , number [ ] > > {
614+ ) : Saga < IdsToReloadPerMapping > {
609615 const activeMappingByLayer = yield * select (
610616 ( store ) => store . temporaryConfiguration . activeMappingByLayer ,
611617 ) ;
612- const idsToRequest = { } as Record < string , number [ ] > ;
618+ const idsToRequestByLayerId = { } as IdsToReloadPerMapping ;
613619 for ( const saveQueueEntry of saveQueue ) {
614620 for ( const action of saveQueueEntry . actions ) {
615621 switch ( action . name ) {
616622 case "mergeAgglomerate" :
617623 case "splitAgglomerate" : {
618624 const { segmentId1, segmentId2, actionTracingId } = action . value ;
619- const upToDateMapping = activeMappingByLayer [ actionTracingId ] ?. mapping ;
620- if ( ! upToDateMapping || segmentId1 == null || segmentId2 == null ) {
625+ const mappingSyncedWithBackend = activeMappingByLayer [ actionTracingId ] ?. mapping ;
626+ if ( ! mappingSyncedWithBackend || segmentId1 == null || segmentId2 == null ) {
621627 continue ;
622628 }
623- const adaptToType =
624- upToDateMapping && isNumberMap ( upToDateMapping )
625- ? ( el : number ) => el
626- : ( el : number ) => BigInt ( el ) ;
627- const upToDateAgglomerateId1 = ( upToDateMapping as NumberLikeMap ) . get (
629+
630+ const adaptToType = getAdaptToTypeFunction ( mappingSyncedWithBackend ) ;
631+ const updatedAgglomerateId1 = ( mappingSyncedWithBackend as NumberLikeMap ) . get (
628632 adaptToType ( segmentId1 ) ,
629633 ) ;
630- const upToDateAgglomerateId2 = ( upToDateMapping as NumberLikeMap ) . get (
634+ const updatedAgglomerateId2 = ( mappingSyncedWithBackend as NumberLikeMap ) . get (
631635 adaptToType ( segmentId2 ) ,
632636 ) ;
633- if ( ! upToDateAgglomerateId1 ) {
634- if ( ! ( actionTracingId in idsToRequest ) ) {
635- idsToRequest [ actionTracingId ] = [ ] ;
637+ if ( ! updatedAgglomerateId1 ) {
638+ if ( ! ( actionTracingId in idsToRequestByLayerId ) ) {
639+ idsToRequestByLayerId [ actionTracingId ] = [ ] ;
636640 }
637- idsToRequest [ actionTracingId ] . push ( segmentId1 ) ;
641+ idsToRequestByLayerId [ actionTracingId ] . push ( segmentId1 ) ;
638642 }
639- if ( ! upToDateAgglomerateId2 ) {
640- if ( ! ( actionTracingId in idsToRequest ) ) {
641- idsToRequest [ actionTracingId ] = [ ] ;
643+ if ( ! updatedAgglomerateId2 ) {
644+ if ( ! ( actionTracingId in idsToRequestByLayerId ) ) {
645+ idsToRequestByLayerId [ actionTracingId ] = [ ] ;
642646 }
643- idsToRequest [ actionTracingId ] . push ( segmentId2 ) ;
647+ idsToRequestByLayerId [ actionTracingId ] . push ( segmentId2 ) ;
644648 }
645649 }
646650 }
647651 }
648652 }
649- return idsToRequest ;
653+ return idsToRequestByLayerId ;
650654}
651655
652- function * addMissingSegmentsToLoadedMappings ( idsToRequest : Record < string , number [ ] > ) : Saga < void > {
656+ // For each passed mapping reload the segment ids' mapping information and store it in the local mapping.
657+ // Needed after getAllUnknownSegmentIdsInPendingUpdates to load updated mapping info for segment ids of
658+ // mesh interaction proofreading actions to ensure reapplying these actions is done with up-to-date mapping info.
659+ function * addMissingSegmentsToLoadedMappings ( idsToRequest : IdsToReloadPerMapping ) : Saga < void > {
653660 const annotationId = yield * select ( ( state ) => state . annotation . annotationId ) ;
654661 const version = yield * select ( ( state ) => state . annotation . version ) ;
655662 const tracingStoreUrl = yield * select ( ( state ) => state . annotation . tracingStore . url ) ;
@@ -661,7 +668,7 @@ function* addMissingSegmentsToLoadedMappings(idsToRequest: Record<string, number
661668 continue ;
662669 }
663670 const activeMapping = activeMappingByLayer [ volumeTracingId ] ;
664- // Ask the server to map the (split) segment ids. This creates a partial mapping
671+ // Ask the server to map the segment ids needing reloading . This creates a partial mapping
665672 // that only contains these ids.
666673 const mappingWithMissingIds = yield * call (
667674 getAgglomeratesForSegmentsFromTracingstore ,
@@ -684,6 +691,11 @@ function* addMissingSegmentsToLoadedMappings(idsToRequest: Record<string, number
684691 }
685692}
686693
694+ // Gathers info mapped info for segment ids from proofreading actions where the mapping is unknown.
695+ // This happens in case of mesh proofreading actions. To re-apply the user's changes in the rebasing
696+ // up-to-date mapping info is needed for all segments in all proofreading actions. Thus, the missing info
697+ // is first loaded and then the save queue update actions are remapped to update their agglomerate id infos
698+ // to apply them correctly during rebasing. Last the save queue is replaced with the updated save queue entries.
687699function * updateSaveQueueEntriesToStateAfterRebase ( ) : Saga <
688700 | {
689701 success : false ;
@@ -710,8 +722,8 @@ function* updateSaveQueueEntriesToStateAfterRebase(): Saga<
710722 case "mergeAgglomerate" :
711723 case "splitAgglomerate" : {
712724 const { segmentId1, segmentId2, actionTracingId } = action . value ;
713- const upToDateMapping = activeMappingByLayer [ actionTracingId ] ?. mapping ;
714- if ( ! upToDateMapping ) {
725+ const mappingSyncedWithBackend = activeMappingByLayer [ actionTracingId ] ?. mapping ;
726+ if ( ! mappingSyncedWithBackend ) {
715727 console . error (
716728 "Found proofreading action without matching mapping in save queue. This should never happen." ,
717729 action ,
@@ -728,14 +740,11 @@ function* updateSaveQueueEntriesToStateAfterRebase(): Saga<
728740 return null ;
729741 }
730742
731- const adaptToType =
732- upToDateMapping && isNumberMap ( upToDateMapping )
733- ? ( el : number ) => el
734- : ( el : number ) => BigInt ( el ) ;
735- let upToDateAgglomerateId1 = ( upToDateMapping as NumberLikeMap ) . get (
743+ const adaptToType = getAdaptToTypeFunction ( mappingSyncedWithBackend ) ;
744+ let upToDateAgglomerateId1 = ( mappingSyncedWithBackend as NumberLikeMap ) . get (
736745 adaptToType ( segmentId1 ) ,
737746 ) ;
738- let upToDateAgglomerateId2 = ( upToDateMapping as NumberLikeMap ) . get (
747+ let upToDateAgglomerateId2 = ( mappingSyncedWithBackend as NumberLikeMap ) . get (
739748 adaptToType ( segmentId2 ) ,
740749 ) ;
741750 if ( ! upToDateAgglomerateId1 || ! upToDateAgglomerateId2 ) {
0 commit comments