1
1
import React , { useState } from "react" ;
2
- import { MapContainer , TileLayer , Marker , Popup } from "react-leaflet" ;
2
+ import { MapContainer , TileLayer , Marker , Tooltip } from "react-leaflet" ;
3
3
import MarkerClusterGroup from "react-leaflet-markercluster" ;
4
4
import "leaflet/dist/leaflet.css" ;
5
5
import "react-leaflet-markercluster/dist/styles.min.css" ;
6
6
import L from "leaflet" ;
7
7
import "./WorldMap.css" ;
8
+ import TimeAgo from 'react-timeago' ;
8
9
9
10
// Hardcoded probe region pins
10
11
const probeRegions = [
@@ -29,26 +30,30 @@ const AccordionItem = ({ instanceScore, orchObj, instanceObj, startExpanded }) =
29
30
</ div >
30
31
{ isExpanded && (
31
32
< div className = "accordion-item-details" >
32
- < p > Instance KPI: { instanceScore ?. toFixed ( 2 ) || "N/A" } </ p >
33
- < p > Orchestrator Name: { orchObj . name } </ p >
34
- < p > Orchestrator ID: { orchObj . id } </ p >
35
- < p > Average Discovery Time: { orchObj . avgDiscoveryTime } </ p >
36
- < p > Average Price: { orchObj . avgPrice } </ p >
37
- < p > Average RTR: { orchObj . avgRTR } </ p >
38
- < p > Average SR: { orchObj . avgSR } </ p >
39
- < p > Normalized Discovery Time: { orchObj . normalizedDiscoveryTime } </ p >
40
- < p > Normalized Price: { orchObj . normalizedPrice } </ p >
41
- < p > Normalized RTR: { orchObj . normalizedRTR } </ p >
42
- < p > Instance Average RTR: { instanceObj . avgRTR } </ p >
43
- < p > Instance Average SR: { instanceObj . avgSR } </ p >
44
- < p > Instance ID: { instanceObj . id } </ p >
45
- < p > Instance Last Ping: { instanceObj . lastPing } </ p >
46
- < p > Instance Normalized Discovery Time: { instanceObj . normalizedDiscoveryTime } </ p >
47
- < p > Instance Normalized Price: { instanceObj . normalizedPrice } </ p >
48
- < p > Instance Normalized RTR: { instanceObj . normalizedRTR } </ p >
49
- < p > Instance Price: { instanceObj . price } </ p >
50
- < p > Instance Probed From: { instanceObj . probedFrom } </ p >
51
- < p > Instance Regions: { instanceObj . regions } </ p >
33
+ < p > Address: { orchObj . id } </ p >
34
+ { orchObj . name != orchObj . id && < p > ENS: { orchObj . name } </ p > }
35
+ < div > < strong > KPI score:</ strong > { instanceScore . toFixed ( 4 ) * 100 } %</ div >
36
+ < hr />
37
+ < strong > Global Stats:</ strong >
38
+ < p > Discovery Time: { orchObj . avgDiscoveryTime . toPrecision ( 3 ) } ms</ p >
39
+ < p > Price: { orchObj . avgPrice . toPrecision ( 3 ) } </ p >
40
+ < p > RTR: { orchObj . avgRTR . toFixed ( 1 ) } </ p >
41
+ < p > SR: { orchObj . avgSR . toFixed ( 1 ) } </ p >
42
+ < hr />
43
+ < strong > Instance Stats:</ strong >
44
+ < p > IP: { instanceObj . id } </ p >
45
+ < div > Last Ping: < TimeAgo
46
+ date = { instanceObj . lastPing }
47
+ component = { "p" }
48
+ minPeriod = { 60 }
49
+ style = { { } }
50
+ /> </ div >
51
+ < p > Discovery Time: { instanceObj . bestDiscoveryTime . toPrecision ( 3 ) } ms</ p >
52
+ < p > Price: { instanceObj . price . toPrecision ( 3 ) } </ p >
53
+ < p > RTR: { instanceObj . avgRTR . toFixed ( 1 ) } </ p >
54
+ < p > SR: { instanceObj . avgSR . toFixed ( 1 ) } </ p >
55
+ < hr />
56
+ < div > < strong > Probed From:</ strong > { instanceObj . probedFrom . map ( ( location ) => < p > { location } </ p > ) } </ div >
52
57
</ div >
53
58
) }
54
59
</ div >
@@ -187,7 +192,17 @@ const WorldMap = ({ orchestrators, selectedKPI }) => {
187
192
clusterclick : ( e ) => {
188
193
const cluster = e . layer ;
189
194
const markers = cluster . getAllChildMarkers ( ) ;
190
- setSelectedData ( markers ) ;
195
+ if ( ! selectedData || ! Array . isArray ( selectedData ) ) {
196
+ setSelectedData ( markers ) ;
197
+ return ;
198
+ }
199
+ const notChanged = Array . isArray ( selectedData ) && selectedData . length == markers . length &&
200
+ selectedData . every ( ( marker , index ) => marker . _leaflet_id === markers [ index ] . _leaflet_id ) || false ;
201
+ if ( ! notChanged ) {
202
+ setSelectedData ( markers ) ;
203
+ } else {
204
+ setSelectedData ( null ) ;
205
+ }
191
206
} ,
192
207
} }
193
208
>
@@ -204,7 +219,7 @@ const WorldMap = ({ orchestrators, selectedKPI }) => {
204
219
icon = { L . divIcon ( {
205
220
className : "dummy" ,
206
221
html : `<div class="custom-pin" style="background-color: ${ selectedData ?. instanceObj ?. id === instance . id ? "var(--magenta)" :
207
- getPinColor ( instance [ selectedKPI ] )
222
+ getPinColor ( instance [ selectedKPI ] )
208
223
} ; width: ${ selectedData ?. instanceObj ?. id === instance . id ? "36px" :
209
224
"24px"
210
225
} ; height: ${ selectedData ?. instanceObj ?. id === instance . id ? "36px" :
@@ -213,14 +228,24 @@ const WorldMap = ({ orchestrators, selectedKPI }) => {
213
228
} ) }
214
229
eventHandlers = { {
215
230
click : ( ) => {
216
- setSelectedData ( {
217
- instanceScore : instance [ selectedKPI ] ,
218
- orchObj : orch ,
219
- instanceObj : instance ,
220
- } ) ;
231
+ if ( ! selectedData || Array . isArray ( selectedData ) || selectedData . instanceObj . id != instance . id ) {
232
+ setSelectedData ( {
233
+ instanceScore : instance [ selectedKPI ] ,
234
+ orchObj : orch ,
235
+ instanceObj : instance ,
236
+ } ) ;
237
+ } else {
238
+ setSelectedData ( null ) ;
239
+ }
221
240
} ,
222
241
} }
223
- />
242
+ >
243
+ < Tooltip >
244
+ < strong > { instance . id } </ strong >
245
+ < br />
246
+ Orchestrator node
247
+ </ Tooltip >
248
+ </ Marker >
224
249
) )
225
250
) }
226
251
</ MarkerClusterGroup >
@@ -235,11 +260,11 @@ const WorldMap = ({ orchestrators, selectedKPI }) => {
235
260
html : `<div class="probe-pin""></div>` ,
236
261
} ) }
237
262
>
238
- < Popup >
263
+ < Tooltip >
239
264
< strong > { region . name } </ strong >
240
265
< br />
241
266
Stronk Origin
242
- </ Popup >
267
+ </ Tooltip >
243
268
</ Marker >
244
269
) ) }
245
270
</ MapContainer >
0 commit comments