@@ -2,6 +2,7 @@ PulseApp.ui = PulseApp.ui || {};
2
2
3
3
PulseApp . ui . dashboard = ( ( ) => {
4
4
let searchInput = null ;
5
+ let guestMetricDragSnapshot = { } ; // To store metrics during slider drag
5
6
6
7
function init ( ) {
7
8
searchInput = document . getElementById ( 'dashboard-search' ) ;
@@ -30,18 +31,26 @@ PulseApp.ui.dashboard = (() => {
30
31
) ;
31
32
32
33
if ( validHistory . length < 2 ) return null ;
34
+
33
35
const oldest = validHistory [ 0 ] ;
34
36
const newest = validHistory [ validHistory . length - 1 ] ;
35
37
const valueDiff = newest [ key ] - oldest [ key ] ;
36
- const timeDiff = ( newest . timestamp - oldest . timestamp ) / 1000 ;
38
+ const timeDiffSeconds = ( newest . timestamp - oldest . timestamp ) / 1000 ;
39
+
40
+ if ( timeDiffSeconds <= 0 ) {
41
+ return null ;
42
+ }
37
43
38
- if ( timeDiff <= 0 ) return 0 ;
39
- return valueDiff / timeDiff ;
44
+ if ( valueDiff < 0 ) {
45
+ return null ;
46
+ }
47
+
48
+ return valueDiff / timeDiffSeconds ;
40
49
}
41
50
42
51
const processGuest = ( guest , type ) => {
43
52
let avgCpu = 0 , avgMem = 0 , avgDisk = 0 ;
44
- let avgDiskReadRate = 0 , avgDiskWriteRate = 0 , avgNetInRate = 0 , avgNetOutRate = 0 ;
53
+ let avgDiskReadRate = null , avgDiskWriteRate = null , avgNetInRate = null , avgNetOutRate = null ;
45
54
let avgMemoryPercent = 'N/A' , avgDiskPercent = 'N/A' ;
46
55
47
56
const metricsData = PulseApp . state . get ( 'metricsData' ) || [ ] ;
@@ -54,27 +63,60 @@ PulseApp.ui.dashboard = (() => {
54
63
55
64
const guestUniqueId = guest . id ;
56
65
57
- if ( guest . status === 'running' && metrics && metrics . current ) {
58
- const currentDataPoint = {
59
- timestamp : Date . now ( ) ,
60
- ...metrics . current
61
- } ;
62
- PulseApp . state . updateDashboardHistory ( guestUniqueId , currentDataPoint ) ;
63
- const history = PulseApp . state . getDashboardHistory ( ) [ guestUniqueId ] || [ ] ;
64
-
65
- avgCpu = calculateAverage ( history , 'cpu' ) ?? 0 ;
66
- avgMem = calculateAverage ( history , 'mem' ) ?? 0 ;
67
- avgDisk = calculateAverage ( history , 'disk' ) ?? 0 ;
68
- avgDiskReadRate = calculateAverageRate ( history , 'diskread' ) ?? 0 ;
69
- avgDiskWriteRate = calculateAverageRate ( history , 'diskwrite' ) ?? 0 ;
70
- avgNetInRate = calculateAverageRate ( history , 'netin' ) ?? 0 ;
71
- avgNetOutRate = calculateAverageRate ( history , 'netout' ) ?? 0 ;
72
- avgMemoryPercent = ( guest . maxmem > 0 ) ? Math . round ( avgMem / guest . maxmem * 100 ) : 'N/A' ;
73
- avgDiskPercent = ( guest . maxdisk > 0 ) ? Math . round ( avgDisk / guest . maxdisk * 100 ) : 'N/A' ;
66
+ // Check for drag state and apply snapshot if active
67
+ const isDragging = PulseApp . ui . thresholds && PulseApp . ui . thresholds . isThresholdDragInProgress && PulseApp . ui . thresholds . isThresholdDragInProgress ( ) ;
68
+ const snapshot = guestMetricDragSnapshot [ guestUniqueId ] ;
69
+
70
+ if ( isDragging && snapshot ) {
71
+ avgDiskReadRate = snapshot . diskread ;
72
+ avgDiskWriteRate = snapshot . diskwrite ;
73
+ avgNetInRate = snapshot . netin ;
74
+ avgNetOutRate = snapshot . netout ;
75
+
76
+ // For other metrics, continue with live data or defaults if snapshot doesn't cover them
77
+ // or if we decide to only snapshot I/O rates.
78
+ // For now, let other metrics be calculated as usual even during drag.
79
+ if ( guest . status === 'running' && metrics && metrics . current ) {
80
+ const currentDataPoint = {
81
+ timestamp : Date . now ( ) ,
82
+ ...metrics . current
83
+ } ;
84
+ PulseApp . state . updateDashboardHistory ( guestUniqueId , currentDataPoint ) ;
85
+ const history = PulseApp . state . getDashboardHistory ( ) [ guestUniqueId ] || [ ] ;
86
+ avgCpu = calculateAverage ( history , 'cpu' ) ?? 0 ;
87
+ avgMem = calculateAverage ( history , 'mem' ) ?? 0 ;
88
+ avgDisk = calculateAverage ( history , 'disk' ) ?? 0 ;
89
+ // I/O rates are already set from snapshot if dragging
90
+ } else {
91
+ PulseApp . state . clearDashboardHistoryEntry ( guestUniqueId ) ;
92
+ // If not running, CPU/Mem/Disk also go to their defaults (0 or N/A)
93
+ }
74
94
75
95
} else {
76
- PulseApp . state . clearDashboardHistoryEntry ( guestUniqueId ) ;
96
+ // Original logic if not dragging or no snapshot
97
+ if ( guest . status === 'running' && metrics && metrics . current ) {
98
+ const currentDataPoint = {
99
+ timestamp : Date . now ( ) ,
100
+ ...metrics . current
101
+ } ;
102
+ PulseApp . state . updateDashboardHistory ( guestUniqueId , currentDataPoint ) ;
103
+ const history = PulseApp . state . getDashboardHistory ( ) [ guestUniqueId ] || [ ] ;
104
+
105
+ avgCpu = calculateAverage ( history , 'cpu' ) ?? 0 ;
106
+ avgMem = calculateAverage ( history , 'mem' ) ?? 0 ;
107
+ avgDisk = calculateAverage ( history , 'disk' ) ?? 0 ;
108
+ avgDiskReadRate = calculateAverageRate ( history , 'diskread' ) ;
109
+ avgDiskWriteRate = calculateAverageRate ( history , 'diskwrite' ) ;
110
+ avgNetInRate = calculateAverageRate ( history , 'netin' ) ;
111
+ avgNetOutRate = calculateAverageRate ( history , 'netout' ) ;
112
+ } else {
113
+ PulseApp . state . clearDashboardHistoryEntry ( guestUniqueId ) ;
114
+ // Rates remain null (will be N/A), others default
115
+ }
77
116
}
117
+
118
+ avgMemoryPercent = ( guest . maxmem > 0 && typeof avgMem === 'number' ) ? Math . round ( avgMem / guest . maxmem * 100 ) : 'N/A' ;
119
+ avgDiskPercent = ( guest . maxdisk > 0 && typeof avgDisk === 'number' ) ? Math . round ( avgDisk / guest . maxdisk * 100 ) : 'N/A' ;
78
120
79
121
const name = guest . name || `${ guest . type === 'qemu' ? 'VM' : 'CT' } ${ guest . vmid } ` ;
80
122
const uptimeFormatted = PulseApp . utils . formatUptime ( guest . uptime ) ;
@@ -341,10 +383,32 @@ PulseApp.ui.dashboard = (() => {
341
383
return row ;
342
384
}
343
385
386
+ function snapshotGuestMetricsForDrag ( ) {
387
+ guestMetricDragSnapshot = { } ; // Clear previous snapshot
388
+ const currentDashboardData = PulseApp . state . get ( 'dashboardData' ) || [ ] ;
389
+ currentDashboardData . forEach ( guest => {
390
+ if ( guest && guest . uniqueId ) {
391
+ guestMetricDragSnapshot [ guest . uniqueId ] = {
392
+ diskread : guest . diskread ,
393
+ diskwrite : guest . diskwrite ,
394
+ netin : guest . netin ,
395
+ netout : guest . netout
396
+ // Optionally snapshot other metrics if they also show issues
397
+ } ;
398
+ }
399
+ } ) ;
400
+ }
401
+
402
+ function clearGuestMetricSnapshots ( ) {
403
+ guestMetricDragSnapshot = { } ;
404
+ }
405
+
344
406
return {
345
407
init,
346
408
refreshDashboardData,
347
409
updateDashboardTable,
348
- createGuestRow
410
+ createGuestRow,
411
+ snapshotGuestMetricsForDrag, // Export snapshot function
412
+ clearGuestMetricSnapshots // Export clear function
349
413
} ;
350
414
} ) ( ) ;
0 commit comments