@@ -14,8 +14,6 @@ import React, {
1414 useState
1515} from 'react' ;
1616import { debounce } from 'lodash' ;
17- import { isRumAgentName } from '../../../../../../../plugins/apm/common/agent_name' ;
18- import { AGENT_NAME } from '../../../../../../../plugins/apm/common/elasticsearch_fieldnames' ;
1917import {
2018 animationOptions ,
2119 cytoscapeOptions ,
@@ -96,10 +94,15 @@ function getLayoutOptions(
9694}
9795
9896function selectRoots ( cy : cytoscape . Core ) : string [ ] {
99- const nodes = cy . nodes ( ) ;
100- const roots = nodes . roots ( ) ;
101- const rumNodes = nodes . filter ( node => isRumAgentName ( node . data ( AGENT_NAME ) ) ) ;
102- return rumNodes . union ( roots ) . map ( node => node . id ( ) ) ;
97+ const bfs = cy . elements ( ) . bfs ( {
98+ roots : cy . elements ( ) . leaves ( )
99+ } ) ;
100+ const furthestNodeFromLeaves = bfs . path . last ( ) ;
101+ return cy
102+ . elements ( )
103+ . roots ( )
104+ . union ( furthestNodeFromLeaves )
105+ . map ( el => el . id ( ) ) ;
103106}
104107
105108export function Cytoscape ( {
@@ -168,15 +171,26 @@ export function Cytoscape({
168171 layout . run ( ) ;
169172 }
170173 } ;
174+ let layoutstopDelayTimeout : NodeJS . Timeout ;
171175 const layoutstopHandler : cytoscape . EventHandler = event => {
172- event . cy . animate ( {
173- ...animationOptions ,
174- center : {
175- eles : serviceName
176- ? event . cy . getElementById ( serviceName )
177- : event . cy . collection ( )
176+ // This 0ms timer is necessary to prevent a race condition
177+ // between the layout finishing rendering and viewport centering
178+ layoutstopDelayTimeout = setTimeout ( ( ) => {
179+ if ( serviceName ) {
180+ event . cy . animate ( {
181+ ...animationOptions ,
182+ fit : {
183+ eles : event . cy . elements ( ) ,
184+ padding : nodeHeight
185+ } ,
186+ center : {
187+ eles : event . cy . getElementById ( serviceName )
188+ }
189+ } ) ;
190+ } else {
191+ event . cy . fit ( undefined , nodeHeight ) ;
178192 }
179- } ) ;
193+ } , 0 ) ;
180194 } ;
181195 // debounce hover tracking so it doesn't spam telemetry with redundant events
182196 const trackNodeEdgeHover = debounce (
@@ -231,6 +245,7 @@ export function Cytoscape({
231245 cy . removeListener ( 'select' , 'node' , selectHandler ) ;
232246 cy . removeListener ( 'unselect' , 'node' , unselectHandler ) ;
233247 }
248+ clearTimeout ( layoutstopDelayTimeout ) ;
234249 } ;
235250 } , [ cy , height , serviceName , trackApmEvent , width ] ) ;
236251
0 commit comments