mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-04-30 11:26:23 +00:00
Update latency-detail-modal.tsx
This commit is contained in:
@@ -462,14 +462,121 @@ ${report.isRealtime && report.realtimeResults.length > 0 ? `
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Latency Chart -->
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">\${report.isRealtime ? '4' : '3'}. Latency Graph</div>
|
||||||
|
<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:16px;">
|
||||||
|
\${(() => {
|
||||||
|
const chartData = report.isRealtime
|
||||||
|
? report.realtimeResults.map(r => r.latency_avg || 0)
|
||||||
|
: report.data.map(d => d.value || 0);
|
||||||
|
if (chartData.length < 2) return '<p style="text-align:center;color:#64748b;padding:20px;">Not enough data points for chart</p>';
|
||||||
|
|
||||||
|
const minVal = Math.min(...chartData);
|
||||||
|
const maxVal = Math.max(...chartData);
|
||||||
|
const range = maxVal - minVal || 1;
|
||||||
|
const width = 700;
|
||||||
|
const height = 120;
|
||||||
|
const padding = 30;
|
||||||
|
|
||||||
|
const points = chartData.map((val, i) => {
|
||||||
|
const x = padding + (i / (chartData.length - 1)) * (width - padding * 2);
|
||||||
|
const y = height - padding - ((val - minVal) / range) * (height - padding * 2);
|
||||||
|
return \`\${x},\${y}\`;
|
||||||
|
}).join(' ');
|
||||||
|
|
||||||
|
const areaPoints = \`\${padding},\${height - padding} \${points} \${width - padding},\${height - padding}\`;
|
||||||
|
|
||||||
|
return \`
|
||||||
|
<svg width="100%" viewBox="0 0 \${width} \${height}" style="display:block;">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="areaGrad" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stop-color="\${statusColor}" stop-opacity="0.3"/>
|
||||||
|
<stop offset="100%" stop-color="\${statusColor}" stop-opacity="0.05"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<!-- Grid lines -->
|
||||||
|
<line x1="\${padding}" y1="\${padding}" x2="\${padding}" y2="\${height - padding}" stroke="#e2e8f0" stroke-width="1"/>
|
||||||
|
<line x1="\${padding}" y1="\${height - padding}" x2="\${width - padding}" y2="\${height - padding}" stroke="#e2e8f0" stroke-width="1"/>
|
||||||
|
<line x1="\${padding}" y1="\${height / 2}" x2="\${width - padding}" y2="\${height / 2}" stroke="#e2e8f0" stroke-width="1" stroke-dasharray="4"/>
|
||||||
|
<!-- Y-axis labels -->
|
||||||
|
<text x="\${padding - 5}" y="\${padding + 4}" font-size="9" fill="#64748b" text-anchor="end">\${maxVal.toFixed(0)}ms</text>
|
||||||
|
<text x="\${padding - 5}" y="\${height / 2 + 3}" font-size="9" fill="#64748b" text-anchor="end">\${((minVal + maxVal) / 2).toFixed(0)}ms</text>
|
||||||
|
<text x="\${padding - 5}" y="\${height - padding + 4}" font-size="9" fill="#64748b" text-anchor="end">\${minVal.toFixed(0)}ms</text>
|
||||||
|
<!-- Area fill -->
|
||||||
|
<polygon points="\${areaPoints}" fill="url(#areaGrad)"/>
|
||||||
|
<!-- Line -->
|
||||||
|
<polyline points="\${points}" fill="none" stroke="\${statusColor}" stroke-width="2"/>
|
||||||
|
<!-- Labels -->
|
||||||
|
<text x="\${width / 2}" y="\${height - 5}" font-size="9" fill="#64748b" text-anchor="middle">\${chartData.length} samples</text>
|
||||||
|
</svg>
|
||||||
|
\`;
|
||||||
|
})()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Reference Thresholds -->
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">\${report.isRealtime ? '5' : '4'}. Performance Thresholds</div>
|
||||||
|
<div class="threshold-item">
|
||||||
|
<div class="threshold-dot" style="background:#16a34a;"></div>
|
||||||
|
<p><strong>Excellent (< 50ms):</strong> Optimal for real-time applications, gaming, and video calls.</p>
|
||||||
|
</div>
|
||||||
|
<div class="threshold-item">
|
||||||
|
<div class="threshold-dot" style="background:#16a34a;"></div>
|
||||||
|
<p><strong>Good (50-100ms):</strong> Acceptable for most applications with minimal impact.</p>
|
||||||
|
</div>
|
||||||
|
<div class="threshold-item">
|
||||||
|
<div class="threshold-dot" style="background:#ca8a04;"></div>
|
||||||
|
<p><strong>Fair (100-200ms):</strong> Noticeable delay. May affect VoIP and interactive applications.</p>
|
||||||
|
</div>
|
||||||
|
<div class="threshold-item">
|
||||||
|
<div class="threshold-dot" style="background:#dc2626;"></div>
|
||||||
|
<p><strong>Poor (> 200ms):</strong> Significant latency. Investigation recommended.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Methodology -->
|
<!-- Methodology -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section-title">${report.isRealtime ? '5' : '4'}. Methodology</div>
|
<div class="section-title">\${report.isRealtime ? '6' : '5'}. Methodology</div>
|
||||||
<div class="grid-2">
|
<div class="grid-2">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-label">Test Method</div>
|
<div class="card-label">Test Method</div>
|
||||||
<div class="card-value" style="font-size:12px;">ICMP Echo Request (Ping)</div>
|
<div class="card-value" style="font-size:12px;">ICMP Echo Request (Ping)</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-label">Samples per Test</div>
|
||||||
|
<div class="card-value" style="font-size:12px;">3 consecutive pings</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-label">Target</div>
|
||||||
|
<div class="card-value" style="font-size:12px;">\${report.targetLabel}</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-label">Target IP</div>
|
||||||
|
<div class="card-value" style="font-size:12px;">\${report.target === 'gateway' ? 'Default Gateway' : report.target === 'cloudflare' ? '1.1.1.1' : '8.8.8.8'}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-box">
|
||||||
|
<h4>Performance Assessment</h4>
|
||||||
|
<p>\${
|
||||||
|
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.'
|
||||||
|
}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<div class="rpt-footer">
|
||||||
|
<div>
|
||||||
|
<img src="\${logoUrl}" alt="ProxMenux" style="height:20px;vertical-align:middle;margin-right:8px;" onerror="this.style.display='none'" />
|
||||||
|
ProxMenux Monitor - Network Performance Report
|
||||||
|
</div>
|
||||||
|
<div>Generated: \${now} | Report ID: PMXL-\${Date.now().toString(36).toUpperCase()}</div>
|
||||||
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-label">Samples per Test</div>
|
<div class="card-label">Samples per Test</div>
|
||||||
<div class="card-value" style="font-size:12px;">3 consecutive pings</div>
|
<div class="card-value" style="font-size:12px;">3 consecutive pings</div>
|
||||||
@@ -655,8 +762,12 @@ export function LatencyDetailModal({ open, onOpenChange, currentLatency }: Laten
|
|||||||
|
|
||||||
const statusInfo = getStatusInfo(displayStats.current)
|
const statusInfo = getStatusInfo(displayStats.current)
|
||||||
|
|
||||||
// Calculate test duration for report
|
// Calculate test duration for report based on first and last result timestamps
|
||||||
const testDuration = testStartTime ? Math.round((Date.now() - testStartTime) / 1000) : 0
|
const testDuration = realtimeResults.length >= 2
|
||||||
|
? Math.round(((realtimeResults[realtimeResults.length - 1].timestamp || Date.now()) - (realtimeResults[0].timestamp || Date.now())) / 1000)
|
||||||
|
: realtimeResults.length === 1
|
||||||
|
? 5 // Single sample = 5 seconds (one test)
|
||||||
|
: 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
|
|||||||
Reference in New Issue
Block a user