Private
Public Access
1
0

refactor: update Proxmox Firewall view to improve log loading functionality and user interaction, including a refresh button and enhanced error handling

This commit is contained in:
2025-12-02 16:47:45 -05:00
parent fd8eb7a9ee
commit c75f72efce

View File

@@ -1,4 +1,4 @@
<x-proxmox::layout :server="$server" view="firewall" :status="$status" :status-polling="true" :status-polling-interval="'2s'"> <x-proxmox::layout :server="$server" view="firewall" :status="$status" :status-polling"false" :status-polling-interval="'2s'">
<style> <style>
.firewall-toggle-switch { .firewall-toggle-switch {
@@ -298,57 +298,70 @@
</div> </div>
<div> <div>
<h2 class="text-xl font-semibold">Firewall Logs</h2> <h2 class="text-xl font-semibold">Firewall Logs</h2>
<p class="text-sm text-base/60 mt-1">Recent firewall activity and blocked/allowed connections (loaded on page load)</p> <p class="text-sm text-base/60 mt-1">Recent firewall activity and blocked/allowed connections</p>
</div>
</div>
<button
wire:click="loadFirewallLogs"
wire:loading.attr="disabled"
class="px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors text-sm font-medium">
<x-ri-refresh-line class="size-4 inline mr-1" />
Refresh
</button>
</div>
@if(!empty($logError))
<div class="bg-warning/10 border border-warning/30 rounded-lg p-4 mb-4">
<div class="flex items-start gap-3">
<x-ri-error-warning-line class="size-5 text-warning flex-shrink-0 mt-0.5" />
<div class="flex-1">
<p class="text-sm text-warning/90">{{ $logError }}</p>
</div> </div>
</div> </div>
</div> </div>
@endif
<script> @if(count($firewallLogs) > 0)
// Initialize firewall logs storage <div
if (typeof window.firewallLogsData === 'undefined') {
window.firewallLogsData = [];
window.firewallLogsLoaded = false;
window.firewallLogsError = '';
}
// Listen for Livewire dispatch event
Livewire.on('firewall-logs-loaded', (event) => {
const data = event[0] || event;
window.firewallLogsData = data.logs || [];
window.firewallLogsError = data.error || '';
window.firewallLogsLoaded = true;
// Trigger Alpine update
const container = document.getElementById('firewall-logs-container');
if (container && container.__x) {
container.__x.$data.logs = window.firewallLogsData;
container.__x.$data.error = window.firewallLogsError;
container.__x.$data.loading = false;
}
});
</script>
<div id="firewall-logs-container"
x-data="{ x-data="{
logs: window.firewallLogsData || [], logs: [],
loading: !window.firewallLogsLoaded,
error: window.firewallLogsError || '',
searchTerm: '', searchTerm: '',
sortField: 'timestamp_iso', sortField: 'timestamp_iso',
sortDirection: 'desc', sortDirection: 'desc',
async initializeLogs() { initialized: false,
// Only load logs once on page load seenRaws: new Set(),
if (window.firewallLogsLoaded) { initialize(initialLogs) {
return; if (this.initialized) return;
}
try { if (initialLogs && initialLogs.length > 0) {
this.loading = true; this.logs = initialLogs.map((log, index) => ({
// Dispatch to Livewire to fetch logs index,
@this.dispatch('fetchFirewallLogsAction'); ...log,
} catch (err) { }));
this.error = 'Failed to load firewall logs: ' + (err.message || 'Unknown error'); // Track which logs we've seen
console.error('Error loading firewall logs:', err); this.logs.forEach(log => {
if (log.raw) this.seenRaws.add(log.raw);
});
this.initialized = true;
}
},
updateLogs(newLogs) {
if (!newLogs || newLogs.length === 0) return;
// Filter out logs we've already seen
const logsToAdd = newLogs.filter(log => {
if (!log.raw) return false;
if (this.seenRaws.has(log.raw)) return false;
this.seenRaws.add(log.raw);
return true;
});
if (logsToAdd.length > 0) {
// Add new logs to the beginning (most recent first)
this.logs = [...logsToAdd, ...this.logs].map((log, index) => ({
index,
...log,
}));
} }
}, },
sort(field) { sort(field) {
@@ -395,26 +408,17 @@
}); });
}, },
}" }"
x-init="initializeLogs()" x-init="initialize(@js($firewallLogs))"
@logs-updated.window="updateLogs($event.detail.logs || $event.detail[0]?.logs || $event.detail[0] || [])"
x-effect="
// Watch for changes in the backend data and merge new logs
const backendLogs = @js($firewallLogs);
if (initialized && backendLogs && backendLogs.length > 0) {
updateLogs(backendLogs);
}
"
class="space-y-4"
> >
<div x-show="loading" x-cloak class="text-center py-8 text-base/60">
<div class="animate-spin inline-block">
<x-ri-loader-4-line class="size-8 mx-auto mb-3 opacity-50" />
</div>
<p>Loading firewall logs...</p>
</div>
<div x-show="error" x-cloak class="bg-error/10 border border-error/30 rounded-lg p-4">
<div class="flex items-start gap-3">
<x-ri-error-warning-line class="size-5 text-error flex-shrink-0 mt-0.5" />
<div class="flex-1">
<p class="text-sm text-error/90" x-text="error"></p>
</div>
</div>
</div>
<template x-if="!loading && !error && logs.length > 0">
<div class="space-y-4">
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-3"> <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-3">
<div class="relative w-full md:w-72"> <div class="relative w-full md:w-72">
<x-ri-search-line class="size-4 absolute left-3 top-1/2 -translate-y-1/2 text-base/40" /> <x-ri-search-line class="size-4 absolute left-3 top-1/2 -translate-y-1/2 text-base/40" />
@@ -1033,16 +1037,13 @@
<p>No logs matched your search.</p> <p>No logs matched your search.</p>
</div> </div>
</div> </div>
</template> @elseif(empty($logError))
<template x-if="!loading && !error && logs.length === 0">
<div class="text-center py-8 text-base/60"> <div class="text-center py-8 text-base/60">
<x-ri-file-list-3-line class="size-12 mx-auto mb-3 opacity-50" /> <x-ri-file-list-3-line class="size-12 mx-auto mb-3 opacity-50" />
<p>No firewall logs available</p> <p>No firewall logs available</p>
<p class="text-xs mt-2">Ensure firewall logging is enabled in Proxmox (Datacenter > Firewall > Options)</p> <p class="text-xs mt-2">Ensure firewall logging is enabled in Proxmox (Datacenter > Firewall > Options)</p>
</div> </div>
</template> @endif
</div>
</div> </div>
@else @else
<div class="bg-background-secondary border border-neutral/20 rounded-lg p-8 text-center"> <div class="bg-background-secondary border border-neutral/20 rounded-lg p-8 text-center">
@@ -1452,4 +1453,3 @@
</script> </script>
</x-proxmox::layout> </x-proxmox::layout>