@@ -3,7 +3,7 @@ import {Event} from "../model/graph/event/event.model";
33import { EventService , SelectableObject } from "../services/event.service" ;
44import { SpeciesService } from "../services/species.service" ;
55import { combineLatest , combineLatestWith , filter , fromEvent , map , Observable , of , switchMap , take , tap } from "rxjs" ;
6- import { MatTree , MatTreeNestedDataSource , MatTreeNodeDef } from "@angular/material/tree" ;
6+ import { MatTree , MatTreeNestedDataSource , MatTreeNodeDef , MatTreeNodeOutlet , MatTreeNodeToggle } from "@angular/material/tree" ;
77import { UrlStateService } from "../services/url-state.service" ;
88import { SplitComponent } from "angular-split" ;
99import { UntilDestroy , untilDestroyed } from "@ngneat/until-destroy" ;
@@ -35,6 +35,8 @@ import {PassiveDirective} from "../utils/passive.directive";
3535 MatTree ,
3636 MatNestedTreeNode ,
3737 MatTreeNodeDef ,
38+ MatTreeNodeToggle ,
39+ MatTreeNodeOutlet ,
3840 MatButton ,
3941 MatIconButton ,
4042 NgClass ,
@@ -168,11 +170,15 @@ export class EventHierarchyComponent implements AfterViewInit, OnDestroy {
168170 } , 100 ) ;
169171
170172 this . eventService . treeData$ . pipe ( untilDestroyed ( this ) ) . subscribe ( events => {
173+ // Save expanded node stIds before resetting the data source
174+ const expandedIds = this . collectExpandedIds ( this . treeDataSource . data ) ;
171175 // @ts -ignore
172176 // Mat tree has a bug causing children to not be rendered in the UI without first setting the data to null
173177 // This is a workaround to add child data to tree and update the view. see details: https://github.com/angular/components/issues/11381
174178 this . treeDataSource . data = [ ] ; //todo: check performance issue
175179 this . treeDataSource . data = events as Event [ ] ;
180+ // Restore expansion state
181+ this . restoreExpandedIds ( events as Event [ ] , expandedIds ) ;
176182 this . adjustWidths ( ) ;
177183 } ) ;
178184
@@ -393,20 +399,16 @@ export class EventHierarchyComponent implements AfterViewInit, OnDestroy {
393399 const selectedEventId = isPathway ( treeEvent ) && treeEvent . hasDiagram ? null : treeEvent . stId ;
394400 this . _ignore = true ;
395401 // this.speciesService.setIgnore(true);
396- this . router . navigate ( [ diagramId ] , {
402+ this . state . navigateTo ( diagramId ?? null , {
397403 queryParamsHandling : "preserve" // Keep existing query params
398404 } ) . then ( ( ) => {
399405 this . state . select . set ( selectedEventId ) ;
400406 this . eventService . setCurrentTreeEvent ( treeEvent ) ;
401- // Listen for NavigationEnd event to reset _ignore
402- this . router . events . pipe (
403- filter ( routerEvent => routerEvent instanceof NavigationEnd ) ,
404- take ( 1 ) // Take the first NavigationEnd event and unsubscribe automatically
405- ) . subscribe ( ( ) => {
406- this . _ignore = false ;
407- // this.speciesService.setIgnore(false);
408- } ) ;
409-
407+ // Reset _ignore after setting state. The .then() callback fires after
408+ // NavigationEnd has already been emitted, so waiting for a future
409+ // NavigationEnd would leave _ignore stuck at true if no further
410+ // navigation occurs.
411+ this . _ignore = false ;
410412 } ) . catch ( err => {
411413 throw new Error ( 'Navigation error:' , err ) ;
412414 } ) ;
@@ -530,4 +532,35 @@ export class EventHierarchyComponent implements AfterViewInit, OnDestroy {
530532 labelSpan . classList . remove ( 'add-overflowX' ) ;
531533 el . classList . remove ( 'no-transition' ) ;
532534 }
535+
536+ private collectExpandedIds ( nodes : Event [ ] ) : Set < string > {
537+ const expanded = new Set < string > ( ) ;
538+ const traverse = ( items : Event [ ] ) => {
539+ for ( const node of items ) {
540+ if ( this . tree ?. isExpanded ( node ) ) {
541+ expanded . add ( node . stId ) ;
542+ }
543+ if ( isPathway ( node ) && node . events ) {
544+ traverse ( node . events . map ( e => e . element ) ) ;
545+ }
546+ }
547+ } ;
548+ traverse ( nodes ) ;
549+ return expanded ;
550+ }
551+
552+ private restoreExpandedIds ( nodes : Event [ ] , expandedIds : Set < string > ) : void {
553+ if ( expandedIds . size === 0 ) return ;
554+ const traverse = ( items : Event [ ] ) => {
555+ for ( const node of items ) {
556+ if ( expandedIds . has ( node . stId ) ) {
557+ this . tree ?. expand ( node ) ;
558+ }
559+ if ( isPathway ( node ) && node . events ) {
560+ traverse ( node . events . map ( e => e . element ) ) ;
561+ }
562+ }
563+ } ;
564+ traverse ( nodes ) ;
565+ }
533566}
0 commit comments