From 8383e381d114bc52844c850ff8887b78466b2707 Mon Sep 17 00:00:00 2001 From: MacRimi Date: Fri, 6 Mar 2026 20:02:49 +0100 Subject: [PATCH] Update latency-detail-modal.tsx --- AppImage/components/latency-detail-modal.tsx | 1151 +++++++++--------- 1 file changed, 608 insertions(+), 543 deletions(-) diff --git a/AppImage/components/latency-detail-modal.tsx b/AppImage/components/latency-detail-modal.tsx index f39c27b5..81fa6653 100644 --- a/AppImage/components/latency-detail-modal.tsx +++ b/AppImage/components/latency-detail-modal.tsx @@ -1,11 +1,11 @@ "use client" -import { useState, useEffect, useCallback } from "react" +import { useState, useEffect, useCallback, useRef } from "react" import { Dialog, DialogContent, DialogHeader, DialogTitle } from "./ui/dialog" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select" import { Button } from "./ui/button" import { Badge } from "./ui/badge" -import { Activity, TrendingDown, TrendingUp, Minus, RefreshCw, Wifi, FileText } from "lucide-react" +import { Activity, TrendingDown, TrendingUp, Minus, RefreshCw, Wifi, FileText, Square } from "lucide-react" import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, LineChart, Line } from "recharts" import { useIsMobile } from "../hooks/use-mobile" import { fetchApi } from "@/lib/api-config" @@ -24,6 +24,10 @@ const TARGET_OPTIONS = [ { value: "google", label: "Google DNS (8.8.8.8)", realtime: true }, ] +// Realtime test configuration +const REALTIME_TEST_DURATION = 120 // 2 minutes in seconds +const REALTIME_TEST_INTERVAL = 5 // 5 seconds between tests + interface LatencyHistoryPoint { timestamp: number value: number @@ -113,35 +117,48 @@ interface ReportData { realtimeResults: RealtimeResult[] data: LatencyHistoryPoint[] timeframe: string + testDuration?: number } const generateLatencyReport = (report: ReportData) => { const now = new Date().toLocaleString() + const logoUrl = `${window.location.origin}/images/proxmenux-logo.png` + + // Calculate stats for realtime results + const realtimeStats = report.realtimeResults.length > 0 ? { + min: Math.min(...report.realtimeResults.filter(r => r.latency_min !== null).map(r => r.latency_min!)), + max: Math.max(...report.realtimeResults.filter(r => r.latency_max !== null).map(r => r.latency_max!)), + avg: report.realtimeResults.reduce((acc, r) => acc + (r.latency_avg || 0), 0) / report.realtimeResults.length, + current: report.realtimeResults[report.realtimeResults.length - 1]?.latency_avg ?? null, + avgPacketLoss: report.realtimeResults.reduce((acc, r) => acc + (r.packet_loss || 0), 0) / report.realtimeResults.length, + } : null + const statusText = report.isRealtime - ? getStatusText(report.realtimeResults[report.realtimeResults.length - 1]?.latency_avg ?? null) + ? getStatusText(realtimeStats?.current ?? null) : getStatusText(report.stats.current) + // Colors matching Lynis report const statusColorMap: Record = { - "Excellent": "#22c55e", - "Good": "#22c55e", - "Fair": "#f59e0b", - "Poor": "#ef4444", - "N/A": "#888888" + "Excellent": "#16a34a", + "Good": "#16a34a", + "Fair": "#ca8a04", + "Poor": "#dc2626", + "N/A": "#64748b" } - const statusColor = statusColorMap[statusText] || "#888888" + const statusColor = statusColorMap[statusText] || "#64748b" const timeframeLabel = TIMEFRAME_OPTIONS.find(t => t.value === report.timeframe)?.label || report.timeframe // Build test results table for realtime mode const realtimeTableRows = report.realtimeResults.map((r, i) => ` - + 0 ? ' class="warn"' : ''}> ${i + 1} ${new Date(r.timestamp || Date.now()).toLocaleTimeString()} - ${r.latency_avg !== null ? r.latency_avg + ' ms' : 'Failed'} + ${r.latency_avg !== null ? r.latency_avg + ' ms' : 'Failed'} ${r.latency_min !== null ? r.latency_min + ' ms' : '-'} ${r.latency_max !== null ? r.latency_max + ' ms' : '-'} - ${r.packet_loss}% - ${getStatusText(r.latency_avg)} + 0 ? ' style="color:#dc2626;font-weight:600;"' : ''}>${r.packet_loss}% + ${getStatusText(r.latency_avg)} `).join('') @@ -156,324 +173,334 @@ const generateLatencyReport = (report: ReportData) => { const html = ` - - - Network Latency Report - ProxMenux Monitor - + + +Network Latency Report - ${report.targetLabel} + -
- -
-
-

Network Latency Report

-

ProxMenux Monitor - Network Performance Analysis

-
-
-
Generated: ${now}
-
Target: ${report.targetLabel}
-
Mode: ${report.isRealtime ? 'Real-time Test' : 'Historical Analysis'}
-
ID: PMXL-${Date.now().toString(36).toUpperCase()}
-
-
- -
-
1. Executive Summary
-
-
-
-
Overall Status
-
- ${statusText} -
-
Current Latency
-
- ${report.isRealtime - ? (report.realtimeResults[report.realtimeResults.length - 1]?.latency_avg ?? 'N/A') + (report.realtimeResults[report.realtimeResults.length - 1]?.latency_avg ? ' ms' : '') - : report.stats.current + ' ms'} -
-
-
-
-
Analysis Summary
-

- ${report.isRealtime - ? `This report contains ${report.realtimeResults.length} real-time latency test(s) performed against ${report.targetLabel}. ${ - report.realtimeResults.length > 0 - ? `The average latency across all tests is ${(report.realtimeResults.reduce((acc, r) => acc + (r.latency_avg || 0), 0) / report.realtimeResults.length).toFixed(1)} ms.` - : '' - }` - : `This report analyzes ${report.data.length} latency samples collected over ${timeframeLabel.toLowerCase()} against the network gateway. The average latency during this period was ${report.stats.avg} ms with a minimum of ${report.stats.min} ms and maximum of ${report.stats.max} ms.` - } -

-
-

Performance Rating

-

${ - statusText === 'Excellent' ? 'Network latency is excellent. No action required.' : - statusText === 'Good' ? 'Network latency is within acceptable parameters.' : - statusText === 'Fair' ? 'Network latency is elevated. Consider investigating network congestion or routing issues.' : - statusText === 'Poor' ? 'Network latency is critically high. Immediate investigation recommended.' : - 'Unable to determine network status.' - }

-
-
-
-
+ +
+
+ ProxMenux Network Latency Report + Review the report, then print or save as PDF +
+
+ ⌘P / Ctrl+P + +
+
- -
-
2. Latency Statistics
-
-
-
Current
-
- ${report.isRealtime - ? (report.realtimeResults[report.realtimeResults.length - 1]?.latency_avg ?? 'N/A') + ' ms' - : report.stats.current + ' ms'} -
-
-
-
Minimum
-
- ${report.isRealtime - ? (report.realtimeResults.length > 0 ? Math.min(...report.realtimeResults.map(r => r.latency_min || Infinity)).toFixed(1) : 'N/A') + ' ms' - : report.stats.min + ' ms'} -
-
-
-
Average
-
- ${report.isRealtime - ? (report.realtimeResults.length > 0 ? (report.realtimeResults.reduce((acc, r) => acc + (r.latency_avg || 0), 0) / report.realtimeResults.length).toFixed(1) : 'N/A') + ' ms' - : report.stats.avg + ' ms'} -
-
-
-
Maximum
-
- ${report.isRealtime - ? (report.realtimeResults.length > 0 ? Math.max(...report.realtimeResults.map(r => r.latency_max || 0)).toFixed(1) : 'N/A') + ' ms' - : report.stats.max + ' ms'} -
-
-
- ${!report.isRealtime && historyStats ? ` -
-
-
Sample Count
-
${historyStats.samples}
-
-
-
Period Start
-
${historyStats.startTime}
-
-
-
Period End
-
${historyStats.endTime}
-
-
- ` : ''} -
- - ${report.isRealtime && report.realtimeResults.length > 0 ? ` - -
-
3. Test Results
- - - - - - - - - - - - - - ${realtimeTableRows} - -
#TimeAvg LatencyMinMaxPacket LossStatus
-
- ` : ''} - - -
-
${report.isRealtime ? '4' : '3'}. Reference Thresholds
-
-
-
-
Excellent (< 50ms): Optimal network performance for all applications including real-time gaming and video calls.
-
-
-
-
Good (50-100ms): Acceptable latency for most applications. Minor impact on real-time interactions.
-
-
-
-
Fair (100-200ms): Noticeable delay in interactive applications. May affect VoIP and gaming quality.
-
-
-
-
Poor (> 200ms): Significant latency causing degraded user experience. Investigation recommended.
-
-
-
- - -
-
${report.isRealtime ? '5' : '4'}. Methodology
-
-

- Test Method: ICMP Echo Request (Ping) -

-

- Target: ${report.targetLabel} ${report.target === 'gateway' ? '(Default network gateway)' : `(${report.target === 'cloudflare' ? '1.1.1.1' : '8.8.8.8'})`} -

-

- Samples per Test: 3 consecutive pings -

-

- Metrics Collected: Round-trip time (RTT) minimum, average, maximum, and packet loss percentage -

-
-
- - -