1+ import { fetchGlances , drawGraph , HISTORY_SIZE , formatBytes } from "./gCore.js" ;
2+
3+ export function initNetwork ( el , config ) {
4+ const { url, apiVer, dataPoints } = config ;
5+ const bodyEl = el . querySelector ( '.glances-body' ) ;
6+ let lastNet = null ;
7+
8+ // 1. Setup DOM
9+ bodyEl . innerHTML = `
10+ <div class="canvas-wrapper">
11+ <canvas class="glances-graph"></canvas>
12+ <div class="net-overlay">
13+ <div class="net-row"><i class="fa-solid fa-arrow-down"></i> <span id="net-rx">--</span></div>
14+ <div class="net-row"><i class="fa-solid fa-arrow-up"></i> <span id="net-tx">--</span></div>
15+ </div>
16+ </div>
17+ <div class="graph-meta"><span id="net-meta">RX: -- | TX: --</span></div>` ;
18+
19+ const canvas = el . querySelector ( 'canvas' ) ;
20+ const ctx = canvas . getContext ( '2d' ) ;
21+ const titleEl = el . querySelector ( '.metric-title' ) ;
22+ const valEl = el . querySelector ( '.metric-value' ) ;
23+
24+ // Redraw Helper (Calculates dynamic scale for network)
25+ const redraw = ( ) => {
26+ const peak = Math . max ( ...dataPoints ) ;
27+ // Add 20% headroom, default 1KB minimum
28+ const maxVal = peak > 0 ? peak * 1.2 : 1024 ;
29+ drawGraph ( canvas , ctx , dataPoints , '--yellow' , maxVal ) ;
30+ } ;
31+
32+ // 2. Setup Resize Observer
33+ const wrapper = el . querySelector ( '.canvas-wrapper' ) ;
34+ if ( wrapper ) {
35+ new ResizeObserver ( ( ) => {
36+ canvas . width = wrapper . clientWidth ;
37+ canvas . height = wrapper . clientHeight ;
38+ redraw ( ) ;
39+ } ) . observe ( wrapper ) ;
40+ }
41+
42+ // 3. Return Update Function
43+ return async ( ) => {
44+ const rawData = await fetchGlances ( url , apiVer , 'network' ) ;
45+ const interfaces = Array . isArray ( rawData ) ? rawData : Object . values ( rawData ) ;
46+
47+ let totalRx = 0 ;
48+ let totalTx = 0 ;
49+
50+ interfaces . forEach ( iface => {
51+ const rx = iface . rx !== undefined ? iface . rx : ( iface . bytes_recv || 0 ) ;
52+ const tx = iface . tx !== undefined ? iface . tx : ( iface . bytes_sent || 0 ) ;
53+ totalRx += rx ;
54+ totalTx += tx ;
55+ } ) ;
56+
57+ const now = Date . now ( ) ;
58+
59+ if ( lastNet ) {
60+ const timeDiff = ( now - lastNet . time ) / 1000 ;
61+ if ( timeDiff > 0 ) {
62+ const rxDiff = totalRx - lastNet . rx ;
63+ const txDiff = totalTx - lastNet . tx ;
64+
65+ const rxSpeed = Math . max ( 0 , rxDiff / timeDiff ) ;
66+ const txSpeed = Math . max ( 0 , txDiff / timeDiff ) ;
67+ const totalSpeed = rxSpeed + txSpeed ;
68+
69+ titleEl . innerText = "NETWORK" ;
70+ valEl . innerText = formatBytes ( totalSpeed ) + '/s' ;
71+
72+ // Update Overlay & Footer
73+ const rxEl = el . querySelector ( '#net-rx' ) ;
74+ const txEl = el . querySelector ( '#net-tx' ) ;
75+ if ( rxEl ) rxEl . innerText = formatBytes ( rxSpeed ) + '/s' ;
76+ if ( txEl ) txEl . innerText = formatBytes ( txSpeed ) + '/s' ;
77+ el . querySelector ( '#net-meta' ) . innerText = `⬇ ${ formatBytes ( rxSpeed ) } | ⬆ ${ formatBytes ( txSpeed ) } ` ;
78+
79+ // Update Graph
80+ dataPoints . push ( totalSpeed ) ;
81+ if ( dataPoints . length > HISTORY_SIZE ) dataPoints . shift ( ) ;
82+ redraw ( ) ;
83+ }
84+ } else {
85+ titleEl . innerText = "NETWORK" ;
86+ valEl . innerText = "Calc..." ;
87+ }
88+
89+ lastNet = { rx : totalRx , tx : totalTx , time : now } ;
90+ } ;
91+ }
0 commit comments