11import { Badge , Title } from '@patternfly/react-core' ;
22import {
33 action ,
4- BadgeLocation ,
5- BreadthFirstLayout ,
64 ComponentFactory ,
75 ContextMenuItem ,
86 createTopologyControlButtons ,
7+ DagreLayout ,
98 defaultControlButtonsOptions ,
109 DefaultEdge ,
1110 DefaultGroup ,
@@ -20,13 +19,16 @@ import {
2019 Node ,
2120 NodeShape ,
2221 SELECTION_EVENT ,
22+ TOP_TO_BOTTOM ,
2323 TopologyControlBar ,
2424 TopologyView ,
2525 Visualization ,
2626 VisualizationProvider ,
2727 VisualizationSurface ,
2828 withContextMenu ,
2929 WithContextMenuProps ,
30+ withDragNode ,
31+ WithDragNodeProps ,
3032 withPanZoom ,
3133 withSelection ,
3234 WithSelectionProps ,
@@ -38,6 +40,13 @@ import * as korrel8r from '../../korrel8r/types';
3840import { getIcon } from '../icons' ;
3941import './korrel8rtopology.css' ;
4042
43+ // DagreLayout with straight edges (no angular bendpoints).
44+ class StraightEdgeDagreLayout extends DagreLayout {
45+ protected updateEdgeBendpoints ( ) : void {
46+ // no-op: skip bendpoints for straight edges between nodes.
47+ }
48+ }
49+
4150const capitalize = ( s : string ) => ( s ? s [ 0 ] . toUpperCase ( ) + s . slice ( 1 ) : '' ) ;
4251
4352const nodeLabel = ( node : korrel8r . Node ) : string => {
@@ -47,20 +56,13 @@ const nodeLabel = (node: korrel8r.Node): string => {
4756 return capitalize ( c . name ) ;
4857} ;
4958
50- const nodeBadge = ( node : korrel8r . Node ) : string => {
51- const queries = nodeQueries ( node ) ;
52- return `${ queries . length > 1 ? `${ queries [ 0 ] ?. count } /` : '' } ${ node ?. count ?? '?' } ` ;
53- } ;
54-
55- const nodeQueries = ( node : korrel8r . Node ) => node ?. queries ?? [ ] ;
56-
5759interface Korrel8rTopologyNodeProps {
5860 element : Node ;
5961}
6062
6163const Korrel8rTopologyNode : React . FC <
62- Korrel8rTopologyNodeProps & WithContextMenuProps & WithSelectionProps
63- > = ( { element, onSelect, selected, onContextMenu, contextMenuOpen } ) => {
64+ Korrel8rTopologyNodeProps & WithContextMenuProps & WithSelectionProps & WithDragNodeProps
65+ > = ( { element, onSelect, selected, onContextMenu, contextMenuOpen, dragNodeRef } ) => {
6466 const node = element . getData ( ) ;
6567 const topologyNode = (
6668 < DefaultNode
@@ -69,10 +71,12 @@ const Korrel8rTopologyNode: React.FC<
6971 selected = { selected }
7072 onContextMenu = { onContextMenu }
7173 contextMenuOpen = { contextMenuOpen }
74+ dragNodeRef = { dragNodeRef }
7275 hover = { false }
7376 label = { nodeLabel ( node ) }
74- badge = { nodeBadge ( node ) }
75- badgeLocation = { BadgeLocation . below }
77+ badge = { node ?. count ?. toString ( ) ?? '?' }
78+ badgeClassName = "tp-plugin__topology_node_badge"
79+ hideContextMenuKebab = { node ?. queries ?. length === 1 }
7680 >
7781 < g transform = { `translate(25, 25)` } > { getIcon ( node . class ) } </ g >
7882 </ DefaultNode >
@@ -159,7 +163,7 @@ export const Korrel8rTopology: React.FC<{
159163 < Title headingLevel = "h4" > { node . class . toString ( ) } </ Title >
160164 </ ContextMenuItem > ,
161165 ] ;
162- nodeQueries ( node ) . forEach ( ( qc ) =>
166+ node ?. queries ? .forEach ( ( qc ) =>
163167 menu . push (
164168 < ContextMenuItem
165169 key = { qc . query . toString ( ) }
@@ -186,7 +190,7 @@ export const Korrel8rTopology: React.FC<{
186190 case ModelKind . graph :
187191 return withPanZoom ( ) ( GraphComponent ) ;
188192 case ModelKind . node :
189- return withContextMenu ( nodeMenu ) ( withSelection ( ) ( Korrel8rTopologyNode ) ) ;
193+ return withDragNode ( ) ( withContextMenu ( nodeMenu ) ( withSelection ( ) ( Korrel8rTopologyNode ) ) ) ;
190194 case ModelKind . edge :
191195 return DefaultEdge ;
192196 default :
@@ -203,12 +207,19 @@ export const Korrel8rTopology: React.FC<{
203207 graph : {
204208 id : 'korrel8r_graph' ,
205209 type : 'graph' ,
206- layout : 'BreadthFirst ' ,
210+ layout : 'Dagre ' ,
207211 } ,
208212 } ;
209213
210214 const controller = new Visualization ( ) ;
211- controller . registerLayoutFactory ( ( _ , graph : Graph ) => new BreadthFirstLayout ( graph ) ) ;
215+ controller . registerLayoutFactory (
216+ ( _ , graph : Graph ) =>
217+ new StraightEdgeDagreLayout ( graph , {
218+ rankdir : TOP_TO_BOTTOM ,
219+ ranksep : 10 ,
220+ nodeDistance : 15 ,
221+ } ) ,
222+ ) ;
212223 controller . fromModel ( model , false ) ;
213224 return controller ;
214225 } , [ nodes , edges ] ) ;
@@ -252,7 +263,9 @@ export const Korrel8rTopology: React.FC<{
252263 zoomOutCallback : action ( ( ) => {
253264 controller . getGraph ( ) . scaleBy ( 0.75 ) ;
254265 } ) ,
255- fitToScreen : false , // Same thing as resetView
266+ fitToScreenCallback : action ( ( ) => {
267+ controller . getGraph ( ) . fit ( PADDING ) ;
268+ } ) ,
256269 resetViewCallback : action ( ( ) => {
257270 controller . getGraph ( ) . reset ( ) ;
258271 controller . getGraph ( ) . layout ( ) ;
0 commit comments