mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-04-05 20:03:48 +00:00
update latency modal
This commit is contained in:
@@ -63,21 +63,46 @@ interface LatencyDetailModalProps {
|
||||
const CustomTooltip = ({ active, payload, label }: any) => {
|
||||
if (active && payload && payload.length) {
|
||||
const entry = payload[0]
|
||||
const packetLoss = entry?.payload?.packet_loss
|
||||
const data = entry?.payload
|
||||
const packetLoss = data?.packet_loss
|
||||
const hasMinMax = data?.min !== undefined && data?.max !== undefined && data?.min !== data?.max
|
||||
|
||||
return (
|
||||
<div className="bg-gray-900/95 backdrop-blur-sm border border-gray-700 rounded-lg p-3 shadow-xl">
|
||||
<p className="text-sm font-semibold text-white mb-2">{label}</p>
|
||||
<div className="space-y-1.5">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0 bg-blue-500" />
|
||||
<span className="text-xs text-gray-300 min-w-[60px]">Latency:</span>
|
||||
<span className="text-sm font-semibold text-white">{entry.value} ms</span>
|
||||
</div>
|
||||
{hasMinMax ? (
|
||||
// Show min/avg/max when downsampled data is available
|
||||
<>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0 bg-green-500" />
|
||||
<span className="text-xs text-gray-300 min-w-[60px]">Min:</span>
|
||||
<span className="text-sm font-semibold text-green-400">{data.min} ms</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0 bg-blue-500" />
|
||||
<span className="text-xs text-gray-300 min-w-[60px]">Avg:</span>
|
||||
<span className="text-sm font-semibold text-white">{data.value} ms</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0 bg-red-500" />
|
||||
<span className="text-xs text-gray-300 min-w-[60px]">Max:</span>
|
||||
<span className="text-sm font-semibold text-red-400">{data.max} ms</span>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
// Simple latency display for single data points
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0 bg-blue-500" />
|
||||
<span className="text-xs text-gray-300 min-w-[60px]">Latency:</span>
|
||||
<span className="text-sm font-semibold text-white">{entry.value} ms</span>
|
||||
</div>
|
||||
)}
|
||||
{packetLoss !== undefined && packetLoss > 0 && (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0 bg-red-500" />
|
||||
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0 bg-orange-500" />
|
||||
<span className="text-xs text-gray-300 min-w-[60px]">Pkt Loss:</span>
|
||||
<span className="text-sm font-semibold text-red-400">{packetLoss}%</span>
|
||||
<span className="text-sm font-semibold text-orange-400">{packetLoss}%</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -1083,9 +1108,11 @@ export function LatencyDetailModal({ open, onOpenChange, currentLatency }: Laten
|
||||
tickFormatter={(v) => `${Number(v).toFixed(1)}ms`}
|
||||
/>
|
||||
<Tooltip content={<CustomTooltip />} />
|
||||
{/* For longer timeframes (6h+), show max values to preserve spikes.
|
||||
For 1 hour view, show avg values since there's no downsampling */}
|
||||
<Area
|
||||
type="monotone"
|
||||
dataKey="value"
|
||||
dataKey={timeframe === "hour" ? "value" : "max"}
|
||||
stroke="#3b82f6"
|
||||
strokeWidth={2}
|
||||
fill="url(#latencyGradient)"
|
||||
|
||||
@@ -746,28 +746,21 @@ def get_latency_history(target='gateway', timeframe='hour'):
|
||||
|
||||
conn.close()
|
||||
|
||||
# Compute stats
|
||||
# Compute stats - always use actual min/max values to preserve spikes
|
||||
if data:
|
||||
values = [d["value"] for d in data if d["value"] is not None]
|
||||
mins = [d["min"] for d in data if d.get("min") is not None]
|
||||
maxs = [d["max"] for d in data if d.get("max") is not None]
|
||||
|
||||
if values:
|
||||
# For gateway, use min/max of the averages (values) so stats match the graph
|
||||
# For other targets (realtime), use actual min/max from individual pings
|
||||
if target == 'gateway':
|
||||
stats = {
|
||||
"min": round(min(values), 1),
|
||||
"max": round(max(values), 1),
|
||||
"avg": round(sum(values) / len(values), 1),
|
||||
"current": values[-1] if values else 0
|
||||
}
|
||||
else:
|
||||
mins = [d["min"] for d in data if d.get("min") is not None]
|
||||
maxs = [d["max"] for d in data if d.get("max") is not None]
|
||||
stats = {
|
||||
"min": round(min(mins) if mins else min(values), 1),
|
||||
"max": round(max(maxs) if maxs else max(values), 1),
|
||||
"avg": round(sum(values) / len(values), 1),
|
||||
"current": values[-1] if values else 0
|
||||
}
|
||||
stats = {
|
||||
# Use actual min from all samples (preserves lowest value)
|
||||
"min": round(min(mins) if mins else min(values), 1),
|
||||
# Use actual max from all samples (preserves spikes)
|
||||
"max": round(max(maxs) if maxs else max(values), 1),
|
||||
"avg": round(sum(values) / len(values), 1),
|
||||
"current": values[-1] if values else 0
|
||||
}
|
||||
else:
|
||||
stats = {"min": 0, "max": 0, "avg": 0, "current": 0}
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user