refactor: enhance network traffic loading placeholder and error handling

This commit is contained in:
2025-12-17 15:46:33 -05:00
parent b2459ef59b
commit fdaa2bf7f1

View File

@@ -772,11 +772,13 @@
</div>
</div>
</div>
</div>
@endif
</div>
<!-- Live Network Traffic & Notes Row -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
<!-- Live Network Traffic -->
<div wire:ignore class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-4 h-full w-full mt-0">
<div wire:ignore class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-4">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2">
<h3 class="text-base font-semibold flex items-center gap-2">
@@ -836,23 +838,18 @@
<!-- Network Traffic Sections -->
<div id="network-traffic-container" data-live-traffic-endpoint="{{ route('proxmox.server.live-traffic', $server) }}">
<div class="bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-4">
<div class="flex items-center gap-2 mb-3">
<div class="w-4 h-4 bg-gray-200 dark:bg-gray-700 rounded animate-pulse"></div>
<div class="w-24 h-4 bg-gray-200 dark:bg-gray-700 rounded animate-pulse"></div>
</div>
<div class="space-y-2">
<div class="h-3 bg-gray-200 dark:bg-gray-700 rounded animate-pulse w-3/4"></div>
<div class="h-2 bg-gray-200 dark:bg-gray-700 rounded animate-pulse w-full"></div>
<div class="h-3 bg-gray-200 dark:bg-gray-700 rounded animate-pulse w-2/3"></div>
<div class="h-2 bg-gray-200 dark:bg-gray-700 rounded animate-pulse w-full"></div>
</div>
<!-- Initial placeholder - will be replaced with actual data on first load -->
<div class="text-center py-6 text-gray-500 dark:text-gray-400 text-sm" id="network-traffic-placeholder">
<svg class="w-8 h-8 mx-auto mb-2 animate-spin text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
</svg>
Connecting to network monitor...
</div>
</div>
</div>
<!-- Notes Section -->
<div id="notes-section" class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-4 h-full flex flex-col mt-0" x-data="{ showExportErrorModal: false }" x-cloak>
<div id="notes-section" class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-4 flex flex-col" x-data="{ showExportErrorModal: false }" x-cloak>
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2">
<h2 class="text-base font-semibold">Notes</h2>
@@ -966,7 +963,7 @@
@endif
</div>
</div>
</div>
@once
@@ -1212,11 +1209,11 @@
if (networkData.interfaces.length === 0) {
container.innerHTML = `
<div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-6 text-center">
<svg class="w-10 h-10 mx-auto text-gray-300 dark:text-gray-600 mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="text-center py-6 text-gray-500 dark:text-gray-400 text-sm">
<svg class="w-8 h-8 mx-auto mb-2 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<p class="text-sm text-gray-500 dark:text-gray-400">No network data available</p>
No network interfaces detected
</div>
`;
return;
@@ -1516,10 +1513,10 @@
const wasEmpty = !networkData || !networkData.interfaces || networkData.interfaces.length === 0;
const hasExistingInterfaces = container && container.querySelectorAll('.chart-toggle').length > 0;
// Check if container shows the loading placeholder (skeleton loader)
// Check if container shows the initial placeholder
const showsPlaceholder = container && (
container.querySelector('.animate-pulse') !== null ||
container.querySelector('.border-dashed') !== null
container.querySelector('#network-traffic-placeholder') !== null ||
container.querySelector('.animate-spin') !== null
);
networkData = data;
@@ -1527,13 +1524,13 @@
// Store globally for export access
window.networkTrafficData = data;
// Render interfaces if:
// 1. This is the first load (wasEmpty && no existing interfaces), OR
// 2. Container shows placeholder (was reset by tab switch), OR
// 3. No existing interfaces found in container
// Render interfaces only if:
// 1. This is the first load (showing placeholder), OR
// 2. No existing interfaces found in container
// Never re-render once we have data - just update values
if (data.interfaces && data.interfaces.length > 0) {
if (showsPlaceholder || !hasExistingInterfaces || wasEmpty) {
console.log('Rendering interfaces - showsPlaceholder:', showsPlaceholder, 'hasExistingInterfaces:', hasExistingInterfaces, 'wasEmpty:', wasEmpty);
if (showsPlaceholder || !hasExistingInterfaces) {
console.log('Rendering interfaces - showsPlaceholder:', showsPlaceholder, 'hasExistingInterfaces:', hasExistingInterfaces);
// Render immediately - no delay
renderInterfaces();
// Also update data immediately after render to ensure values are set
@@ -1611,17 +1608,20 @@
} catch (error) {
console.error('Failed to fetch live traffic data:', error);
const container = document.getElementById('network-traffic-container');
// Only show error if there's no existing network data (initial load failed)
// Keep existing content if we already have data (refresh failed)
const hasExistingContent = container && container.querySelectorAll('.chart-toggle').length > 0;
if (container && !hasExistingContent) {
// Only show error if still showing initial placeholder (no data loaded yet)
// Never replace existing network data with error state
const showsPlaceholder = container && (
container.querySelector('#network-traffic-placeholder') !== null ||
container.querySelector('.animate-spin') !== null
);
if (container && showsPlaceholder) {
container.innerHTML = `
<div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-6 text-center">
<svg class="w-10 h-10 mx-auto text-red-400 mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div class="text-center py-6 text-gray-500 dark:text-gray-400 text-sm">
<svg class="w-8 h-8 mx-auto mb-2 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<p class="text-sm text-gray-500 dark:text-gray-400">Failed to load network data</p>
<p class="text-xs text-gray-400 dark:text-gray-500 mt-1">${error.message}</p>
Failed to load network data
<p class="text-xs text-gray-400 mt-1">${error.message}</p>
</div>
`;
}