@@ -6,6 +6,10 @@ import "react-leaflet-markercluster/dist/styles.min.css";
6
6
import L from "leaflet" ;
7
7
import "./WorldMap.css" ;
8
8
import TimeAgo from 'react-timeago' ;
9
+ import { FaBroadcastTower , FaServer } from 'react-icons/fa' ;
10
+ import ReactDOMServer from 'react-dom/server' ;
11
+ const broadcastTowerIconHTML = ReactDOMServer . renderToString ( < FaBroadcastTower /> ) ;
12
+ const serverIconHTML = ReactDOMServer . renderToString ( < FaServer /> ) ;
9
13
10
14
// Hardcoded probe region pins
11
15
const probeRegions = [
@@ -31,7 +35,7 @@ const AccordionItem = ({ instanceScore, orchObj, instanceObj, startExpanded }) =
31
35
{ isExpanded && (
32
36
< div className = "accordion-item-details" >
33
37
< strong > { orchObj . id } </ strong >
34
- < div > < strong > KPI score:</ strong > { instanceScore . toFixed ( 4 ) * 100 } %</ div >
38
+ < div > < strong > KPI score:</ strong > { ( instanceScore * 100 ) . toFixed ( 1 ) } %</ div >
35
39
< hr />
36
40
< strong > Global Stats:</ strong >
37
41
< p > Discovery Time: { orchObj . avgDiscoveryTime . toPrecision ( 3 ) } ms</ p >
@@ -59,25 +63,49 @@ const AccordionItem = ({ instanceScore, orchObj, instanceObj, startExpanded }) =
59
63
) ;
60
64
} ;
61
65
66
+ // Helper function to group instances by instance.id
67
+ const groupInstancesById = ( markers ) => {
68
+ return markers . reduce ( ( acc , marker ) => {
69
+ const instanceId = marker . options . options . instanceObj . id ;
70
+
71
+ if ( ! acc [ instanceId ] ) {
72
+ acc [ instanceId ] = [ ] ;
73
+ }
74
+ acc [ instanceId ] . push ( marker ) ;
75
+
76
+ return acc ;
77
+ } , { } ) ;
78
+ } ;
79
+
62
80
// Side panel to show selected cluster or marker details
63
81
const SidePanel = ( { selectedData, onClose } ) => {
64
82
if ( ! selectedData ) return null ;
65
83
84
+ // Group the markers by instance ID if a cluster is selected
85
+ const groupedData = Array . isArray ( selectedData ) ? groupInstancesById ( selectedData ) : null ;
86
+
66
87
return (
67
88
< div className = "side-panel" >
68
89
< button onClick = { onClose } className = "close-button" >
69
90
Close
70
91
</ button >
71
92
{ Array . isArray ( selectedData ) ? (
72
- // Cluster is selected
93
+ // Cluster is selected, group by instance ID
73
94
< div className = "accordion" >
74
- { selectedData . map ( ( marker , index ) => (
75
- < AccordionItem
76
- key = { index }
77
- instanceScore = { marker . options . options . instanceScore }
78
- orchObj = { marker . options . options . orchObj }
79
- instanceObj = { marker . options . options . instanceObj }
80
- />
95
+ { Object . keys ( groupedData ) . map ( ( instanceId ) => (
96
+ < div key = { instanceId } className = "accordion-item-wrapper" >
97
+ < strong > { instanceId } </ strong >
98
+ < div className = "accordion-item-details" >
99
+ { groupedData [ instanceId ] . map ( ( marker , index ) => (
100
+ < AccordionItem
101
+ key = { index }
102
+ instanceScore = { marker . options . options . instanceScore }
103
+ orchObj = { marker . options . options . orchObj }
104
+ instanceObj = { marker . options . options . instanceObj }
105
+ />
106
+ ) ) }
107
+ </ div >
108
+ </ div >
81
109
) ) }
82
110
</ div >
83
111
) : (
@@ -129,7 +157,7 @@ const WorldMap = ({ orchestrators, selectedKPI }) => {
129
157
. reduce ( ( sum , score ) => sum + score , 0 ) / childCount
130
158
) . toFixed ( 2 ) ;
131
159
132
- let size = Math . min ( 20 + childCount * 2 , 80 ) ;
160
+ let size = Math . min ( 36 + childCount * 2 , 96 ) ;
133
161
const color = getPinColor ( avgScore ) ;
134
162
135
163
return L . divIcon ( {
@@ -210,11 +238,9 @@ const WorldMap = ({ orchestrators, selectedKPI }) => {
210
238
className : "dummy" ,
211
239
html : `<div class="custom-pin" style="background-color: ${ selectedData ?. instanceObj ?. id === instance . id ? "var(--magenta)" :
212
240
getPinColor ( instance [ selectedKPI ] )
213
- } ; width: ${ selectedData ?. instanceObj ?. id === instance . id ? "36px" :
214
- "24px"
215
- } ; height: ${ selectedData ?. instanceObj ?. id === instance . id ? "36px" :
216
- "24px"
217
- } ; border-radius: 50%;"></div>`,
241
+ } ; width: ${ selectedData ?. instanceObj ?. id === instance . id ? "48px" : "36px"
242
+ } ; height: ${ selectedData ?. instanceObj ?. id === instance . id ? "48px" : "36px"
243
+ } ; border-radius: 50%;">${ serverIconHTML } </div>`,
218
244
} ) }
219
245
eventHandlers = { {
220
246
click : ( ) => {
@@ -247,7 +273,7 @@ const WorldMap = ({ orchestrators, selectedKPI }) => {
247
273
position = { [ region . latitude , region . longitude ] }
248
274
icon = { L . divIcon ( {
249
275
className : 'dummy' ,
250
- html : `<div class="probe-pin""> </div>` ,
276
+ html : `<div class="probe-pin"> ${ broadcastTowerIconHTML } </div>` ,
251
277
} ) }
252
278
>
253
279
< Tooltip >
0 commit comments