diff --git a/extensions/Servers/Proxmox/views/firewall.blade.php b/extensions/Servers/Proxmox/views/firewall.blade.php index b480e3444..db89cc003 100644 --- a/extensions/Servers/Proxmox/views/firewall.blade.php +++ b/extensions/Servers/Proxmox/views/firewall.blade.php @@ -330,6 +330,8 @@ sortDirection: 'desc', currentPage: 1, perPage: 10, + actionFilter: 'all', + protocolFilter: 'all', initialize(initialLogs) { console.log('Initializing logs, received:', initialLogs ? initialLogs.length : 0, 'entries'); this.logs = (initialLogs || []).map((log, index) => ({ @@ -345,12 +347,69 @@ this.sortField = field; this.sortDirection = 'asc'; } - this.currentPage = 1; // Reset to first page when sorting + this.currentPage = 1; + }, + setActionFilter(filter) { + this.actionFilter = filter; + this.currentPage = 1; + }, + setProtocolFilter(filter) { + this.protocolFilter = filter; + this.currentPage = 1; + }, + get actionCounts() { + const counts = { all: this.logs.length, blocked: 0, allowed: 0 }; + this.logs.forEach(log => { + const action = (log.action || '').toUpperCase(); + if (action === 'DROP' || action === 'REJECT' || action.includes('DROP') || action.includes('REJECT')) { + counts.blocked++; + } else if (action === 'ACCEPT' || action.includes('ACCEPT')) { + counts.allowed++; + } + }); + return counts; + }, + get protocolCounts() { + const counts = { all: this.logs.length, tcp: 0, udp: 0, icmp: 0, other: 0 }; + this.logs.forEach(log => { + const proto = (log.protocol || '').toUpperCase(); + if (proto === 'TCP') counts.tcp++; + else if (proto === 'UDP') counts.udp++; + else if (proto === 'ICMP' || proto === 'ICMPV6') counts.icmp++; + else if (proto) counts.other++; + }); + return counts; }, get filteredLogs() { const term = this.searchTerm.trim().toLowerCase(); let entries = this.logs; + // Apply action filter + if (this.actionFilter === 'blocked') { + entries = entries.filter(log => { + const action = (log.action || '').toUpperCase(); + return action === 'DROP' || action === 'REJECT' || action.includes('DROP') || action.includes('REJECT'); + }); + } else if (this.actionFilter === 'allowed') { + entries = entries.filter(log => { + const action = (log.action || '').toUpperCase(); + return action === 'ACCEPT' || action.includes('ACCEPT'); + }); + } + + // Apply protocol filter + if (this.protocolFilter !== 'all') { + entries = entries.filter(log => { + const proto = (log.protocol || '').toUpperCase(); + if (this.protocolFilter === 'tcp') return proto === 'TCP'; + if (this.protocolFilter === 'udp') return proto === 'UDP'; + if (this.protocolFilter === 'icmp') return proto === 'ICMP' || proto === 'ICMPV6'; + if (this.protocolFilter === 'other') return proto && proto !== 'TCP' && proto !== 'UDP' && proto !== 'ICMP' && proto !== 'ICMPV6'; + return true; + }); + } + + // Apply search filter if (term) { entries = entries.filter((log) => { return Object.values(log).some((value) => { @@ -453,29 +512,111 @@ x-effect="if (currentPage > totalPages && totalPages > 0) currentPage = totalPages" class="space-y-4" > -
-
- - + +
+ +
+ Policy: + + +
-
-
- Showing - - of - + + +
+ Protocol: + + + + + +
+ + +
+
+ +
-
- Page - - / - +
+
+ Showing + + of + +
+
+ Page + + / + +