@@ -1108,6 +1108,19 @@ const internalCharts = {
11081108 deviceHistory : null ,
11091109} ;
11101110
1111+ // Helper function to check if a metric value is missing (null or undefined)
1112+ function isValueMissing ( value ) {
1113+ return value === null || value === undefined ;
1114+ }
1115+
1116+ // Helper function to destroy a chart if it exists
1117+ function destroyChartIfExists ( chartRef ) {
1118+ if ( chartRef ) {
1119+ chartRef . destroy ( ) ;
1120+ }
1121+ return null ;
1122+ }
1123+
11111124// ============================================================================
11121125// Internal Network - API Functions
11131126// ============================================================================
@@ -1221,13 +1234,13 @@ function updateInternalHistoryCharts() {
12211234 const pingData = sorted . map ( m => m . ping_idle_ms || null ) ; // Use null for missing to skip points
12221235 const jitterData = sorted . map ( m => m . jitter_ms || 0 ) ;
12231236 const gatewayPingData = sorted . map ( m => m . gateway_ping_ms || null ) ; // Use null for missing
1224- const localLatencyData = sorted . map ( m => m . local_latency_ms || 0 ) ;
1237+ const localLatencyData = sorted . map ( m => m . local_latency_ms || null ) ; // Use null for missing
12251238 // Loaded ping: maximum of ping during download or upload (shows bufferbloat)
12261239 const loadedPingData = sorted . map ( m => {
12271240 const dlPing = m . ping_during_download_ms ;
12281241 const ulPing = m . ping_during_upload_ms ;
12291242 // Return null if both are missing, otherwise max of available values
1230- if ( ! dlPing && ! ulPing ) return null ;
1243+ if ( isValueMissing ( dlPing ) && isValueMissing ( ulPing ) ) return null ;
12311244 return Math . max ( dlPing || 0 , ulPing || 0 ) ;
12321245 } ) ;
12331246
@@ -1289,7 +1302,7 @@ function updateInternalHistoryCharts() {
12891302 } ,
12901303 elements : {
12911304 point : { radius : 3 , hoverRadius : 6 , borderWidth : 2 } ,
1292- line : { tension : 0.4 , borderWidth : 2 } ,
1305+ line : { tension : 0.4 , borderWidth : 2 , spanGaps : false } ,
12931306 } ,
12941307 } ;
12951308
@@ -1340,13 +1353,15 @@ function updateInternalHistoryCharts() {
13401353 }
13411354 }
13421355
1343- // Internal Latency History Chart (Ping & Jitter)
1356+ // Internal Latency History Chart (Ping, Jitter, Gateway, Local Latency )
13441357 const latencyCtx = document . getElementById ( 'internal-latency-chart' ) ;
13451358 if ( latencyCtx ) {
13461359 if ( internalCharts . latency ) {
13471360 internalCharts . latency . data . labels = labels ;
13481361 internalCharts . latency . data . datasets [ 0 ] . data = pingData ;
13491362 internalCharts . latency . data . datasets [ 1 ] . data = jitterData ;
1363+ internalCharts . latency . data . datasets [ 2 ] . data = gatewayPingData ;
1364+ internalCharts . latency . data . datasets [ 3 ] . data = localLatencyData ;
13501365 internalCharts . latency . update ( ) ;
13511366 } else {
13521367 internalCharts . latency = new Chart ( latencyCtx . getContext ( '2d' ) , {
@@ -1368,6 +1383,22 @@ function updateInternalHistoryCharts() {
13681383 backgroundColor : 'rgba(168, 85, 247, 0.1)' ,
13691384 fill : true ,
13701385 } ,
1386+ {
1387+ label : 'Gateway Ping (ms)' ,
1388+ data : gatewayPingData ,
1389+ borderColor : '#06b6d4' ,
1390+ backgroundColor : 'rgba(6, 182, 212, 0.1)' ,
1391+ fill : false ,
1392+ borderDash : [ 5 , 5 ] ,
1393+ } ,
1394+ {
1395+ label : 'Local Latency (ms)' ,
1396+ data : localLatencyData ,
1397+ borderColor : '#84cc16' ,
1398+ backgroundColor : 'rgba(132, 204, 22, 0.1)' ,
1399+ fill : false ,
1400+ borderDash : [ 2 , 8 ] , // More distinct dash pattern
1401+ } ,
13711402 ] ,
13721403 } ,
13731404 options : {
@@ -2091,7 +2122,8 @@ function updateDeviceCharts() {
20912122 const lanCtx = document . getElementById ( 'lan-devices-chart' ) ;
20922123 if ( lanCtx ) {
20932124 if ( lanDevices . length === 0 ) {
2094- // No LAN devices found
2125+ // No LAN devices found - destroy chart and show placeholder
2126+ internalCharts . lanDevices = destroyChartIfExists ( internalCharts . lanDevices ) ;
20952127 showChartPlaceholder ( lanCtx , 'No LAN devices found' ) ;
20962128 } else {
20972129 const labels = lanDevices . map ( d => d . friendly_name || d . hostname || d . ip_address ) ;
@@ -2103,7 +2135,8 @@ function updateDeviceCharts() {
21032135 uploadData . some ( v => v !== null && v !== undefined ) ;
21042136
21052137 if ( ! hasData ) {
2106- // Devices exist but no tests run - show placeholder with device names
2138+ // Devices exist but no tests run - destroy chart and show placeholder with device names
2139+ internalCharts . lanDevices = destroyChartIfExists ( internalCharts . lanDevices ) ;
21072140 showChartPlaceholder ( lanCtx , `${ lanDevices . length } device(s) - Run tests to see speeds` ) ;
21082141 } else {
21092142 if ( internalCharts . lanDevices ) {
@@ -2144,6 +2177,8 @@ function updateDeviceCharts() {
21442177 const wifiCtx = document . getElementById ( 'wifi-devices-chart' ) ;
21452178 if ( wifiCtx ) {
21462179 if ( wifiDevices . length === 0 ) {
2180+ // No WiFi devices found - destroy chart and show placeholder
2181+ internalCharts . wifiDevices = destroyChartIfExists ( internalCharts . wifiDevices ) ;
21472182 showChartPlaceholder ( wifiCtx , 'No WiFi devices found' ) ;
21482183 } else {
21492184 const labels = wifiDevices . map ( d => d . friendly_name || d . hostname || d . ip_address ) ;
@@ -2154,6 +2189,8 @@ function updateDeviceCharts() {
21542189 uploadData . some ( v => v !== null && v !== undefined ) ;
21552190
21562191 if ( ! hasData ) {
2192+ // Devices exist but no tests run - destroy chart and show placeholder with device names
2193+ internalCharts . wifiDevices = destroyChartIfExists ( internalCharts . wifiDevices ) ;
21572194 showChartPlaceholder ( wifiCtx , `${ wifiDevices . length } device(s) - Run tests to see speeds` ) ;
21582195 } else {
21592196 if ( internalCharts . wifiDevices ) {
0 commit comments