diff --git a/extensions/Servers/Proxmox/views/firewall.blade.php b/extensions/Servers/Proxmox/views/firewall.blade.php index f23121b49..77e454a63 100644 --- a/extensions/Servers/Proxmox/views/firewall.blade.php +++ b/extensions/Servers/Proxmox/views/firewall.blade.php @@ -128,30 +128,75 @@ color: #ffffff; } - .firewall-filter-btn.active-blocked { - background-color: #ef4444; - border-color: #ef4444; + /* DROP - Red */ + .firewall-filter-btn.active-drop { + background-color: #dc2626; + border-color: #dc2626; color: white; + box-shadow: 0 2px 8px rgba(220, 38, 38, 0.3); } - .firewall-filter-btn.active-blocked .firewall-filter-btn-count { - background-color: rgba(255, 255, 255, 0.2); + .firewall-filter-btn.active-drop .firewall-filter-btn-count { + background-color: rgba(255, 255, 255, 0.25); } - .firewall-filter-btn:not(.active-blocked) .firewall-filter-btn-count.count-blocked { - background-color: rgba(239, 68, 68, 0.1); - color: #ef4444; + .firewall-filter-btn:not(.active-drop) .firewall-filter-btn-count.count-drop { + background-color: rgba(220, 38, 38, 0.1); + color: #dc2626; } - .firewall-filter-btn.active-allowed { - background-color: #22c55e; - border-color: #22c55e; + /* REJECT - Orange-Red */ + .firewall-filter-btn.active-reject { + background-color: #ea580c; + border-color: #ea580c; color: white; + box-shadow: 0 2px 8px rgba(234, 88, 12, 0.3); } - .firewall-filter-btn.active-allowed .firewall-filter-btn-count { - background-color: rgba(255, 255, 255, 0.2); + .firewall-filter-btn.active-reject .firewall-filter-btn-count { + background-color: rgba(255, 255, 255, 0.25); } - .firewall-filter-btn:not(.active-allowed) .firewall-filter-btn-count.count-allowed { - background-color: rgba(34, 197, 94, 0.1); - color: #22c55e; + .firewall-filter-btn:not(.active-reject) .firewall-filter-btn-count.count-reject { + background-color: rgba(234, 88, 12, 0.1); + color: #ea580c; + } + + /* ACCEPT - Green */ + .firewall-filter-btn.active-accept { + background-color: #16a34a; + border-color: #16a34a; + color: white; + box-shadow: 0 2px 8px rgba(22, 163, 74, 0.3); + } + .firewall-filter-btn.active-accept .firewall-filter-btn-count { + background-color: rgba(255, 255, 255, 0.25); + } + .firewall-filter-btn:not(.active-accept) .firewall-filter-btn-count.count-accept { + background-color: rgba(22, 163, 74, 0.1); + color: #16a34a; + } + + /* LOG - Cyan */ + .firewall-filter-btn.active-log { + background-color: #0891b2; + border-color: #0891b2; + color: white; + box-shadow: 0 2px 8px rgba(8, 145, 178, 0.3); + } + .firewall-filter-btn.active-log .firewall-filter-btn-count { + background-color: rgba(255, 255, 255, 0.25); + } + .firewall-filter-btn:not(.active-log) .firewall-filter-btn-count.count-log { + background-color: rgba(8, 145, 178, 0.1); + color: #0891b2; + } + + /* Action Other - Gray */ + .firewall-filter-btn.active-action-other { + background-color: #525252; + border-color: #525252; + color: white; + box-shadow: 0 2px 8px rgba(82, 82, 82, 0.3); + } + .firewall-filter-btn.active-action-other .firewall-filter-btn-count { + background-color: rgba(255, 255, 255, 0.25); } /* Active states for Protocol filters */ @@ -205,13 +250,90 @@ color: #a855f7; } - .firewall-filter-btn.active-other { - background-color: rgba(var(--color-base), 0.7); - border-color: rgba(var(--color-base), 0.7); + /* GRE - Teal */ + .firewall-filter-btn.active-gre { + background-color: #0d9488; + border-color: #0d9488; color: white; + box-shadow: 0 2px 8px rgba(13, 148, 136, 0.3); } - .firewall-filter-btn.active-other .firewall-filter-btn-count { - background-color: rgba(255, 255, 255, 0.2); + .firewall-filter-btn.active-gre .firewall-filter-btn-count { + background-color: rgba(255, 255, 255, 0.25); + } + .firewall-filter-btn:not(.active-gre) .firewall-filter-btn-count.count-gre { + background-color: rgba(13, 148, 136, 0.1); + color: #0d9488; + } + + /* ESP - Indigo */ + .firewall-filter-btn.active-esp { + background-color: #4f46e5; + border-color: #4f46e5; + color: white; + box-shadow: 0 2px 8px rgba(79, 70, 229, 0.3); + } + .firewall-filter-btn.active-esp .firewall-filter-btn-count { + background-color: rgba(255, 255, 255, 0.25); + } + .firewall-filter-btn:not(.active-esp) .firewall-filter-btn-count.count-esp { + background-color: rgba(79, 70, 229, 0.1); + color: #4f46e5; + } + + /* AH - Violet */ + .firewall-filter-btn.active-ah { + background-color: #7c3aed; + border-color: #7c3aed; + color: white; + box-shadow: 0 2px 8px rgba(124, 58, 237, 0.3); + } + .firewall-filter-btn.active-ah .firewall-filter-btn-count { + background-color: rgba(255, 255, 255, 0.25); + } + .firewall-filter-btn:not(.active-ah) .firewall-filter-btn-count.count-ah { + background-color: rgba(124, 58, 237, 0.1); + color: #7c3aed; + } + + /* SCTP - Pink */ + .firewall-filter-btn.active-sctp { + background-color: #db2777; + border-color: #db2777; + color: white; + box-shadow: 0 2px 8px rgba(219, 39, 119, 0.3); + } + .firewall-filter-btn.active-sctp .firewall-filter-btn-count { + background-color: rgba(255, 255, 255, 0.25); + } + .firewall-filter-btn:not(.active-sctp) .firewall-filter-btn-count.count-sctp { + background-color: rgba(219, 39, 119, 0.1); + color: #db2777; + } + + /* IGMP - Lime */ + .firewall-filter-btn.active-igmp { + background-color: #65a30d; + border-color: #65a30d; + color: white; + box-shadow: 0 2px 8px rgba(101, 163, 13, 0.3); + } + .firewall-filter-btn.active-igmp .firewall-filter-btn-count { + background-color: rgba(255, 255, 255, 0.25); + } + .firewall-filter-btn:not(.active-igmp) .firewall-filter-btn-count.count-igmp { + background-color: rgba(101, 163, 13, 0.1); + color: #65a30d; + } + + /* Protocol Other - Dark Gray */ + .firewall-filter-btn.active-proto-other { + background-color: #525252; + border-color: #525252; + color: white; + box-shadow: 0 2px 8px rgba(82, 82, 82, 0.3); + } + .firewall-filter-btn.active-proto-other .firewall-filter-btn-count { + background-color: rgba(255, 255, 255, 0.25); } .firewall-filter-row { @@ -478,8 +600,8 @@ sortDirection: 'desc', currentPage: 1, perPage: 10, - actionFilter: 'all', - protocolFilter: 'all', + actionFilters: [], + protocolFilters: [], initialize(initialLogs) { console.log('Initializing logs, received:', initialLogs ? initialLogs.length : 0, 'entries'); this.logs = (initialLogs || []).map((log, index) => ({ @@ -497,33 +619,68 @@ } this.currentPage = 1; }, - setActionFilter(filter) { - this.actionFilter = filter; + toggleActionFilter(filter) { + const idx = this.actionFilters.indexOf(filter); + if (idx === -1) { + this.actionFilters.push(filter); + } else { + this.actionFilters.splice(idx, 1); + } this.currentPage = 1; }, - setProtocolFilter(filter) { - this.protocolFilter = filter; + toggleProtocolFilter(filter) { + const idx = this.protocolFilters.indexOf(filter); + if (idx === -1) { + this.protocolFilters.push(filter); + } else { + this.protocolFilters.splice(idx, 1); + } this.currentPage = 1; }, + clearActionFilters() { + this.actionFilters = []; + this.currentPage = 1; + }, + clearProtocolFilters() { + this.protocolFilters = []; + this.currentPage = 1; + }, + isActionActive(filter) { + return this.actionFilters.includes(filter); + }, + isProtocolActive(filter) { + return this.protocolFilters.includes(filter); + }, get actionCounts() { - const counts = { all: this.logs.length, blocked: 0, allowed: 0 }; + const counts = { all: this.logs.length, drop: 0, reject: 0, accept: 0, log: 0, other: 0 }; this.logs.forEach(log => { const action = (log.action || '').toUpperCase(); - if (action === 'DROP' || action === 'REJECT' || action.includes('DROP') || action.includes('REJECT')) { - counts.blocked++; + if (action === 'DROP' || action.includes('DROP')) { + counts.drop++; + } else if (action === 'REJECT' || action.includes('REJECT')) { + counts.reject++; } else if (action === 'ACCEPT' || action.includes('ACCEPT')) { - counts.allowed++; + counts.accept++; + } else if (action === 'LOG' || action.includes('LOG')) { + counts.log++; + } else if (action) { + counts.other++; } }); return counts; }, get protocolCounts() { - const counts = { all: this.logs.length, tcp: 0, udp: 0, icmp: 0, other: 0 }; + const counts = { all: this.logs.length, tcp: 0, udp: 0, icmp: 0, gre: 0, esp: 0, ah: 0, sctp: 0, igmp: 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 === 'GRE') counts.gre++; + else if (proto === 'ESP') counts.esp++; + else if (proto === 'AH') counts.ah++; + else if (proto === 'SCTP') counts.sctp++; + else if (proto === 'IGMP') counts.igmp++; else if (proto) counts.other++; }); return counts; @@ -532,28 +689,37 @@ const term = this.searchTerm.trim().toLowerCase(); let entries = this.logs; - // Apply action filter - if (this.actionFilter === 'blocked') { + // Apply action filters (multi-select) + if (this.actionFilters.length > 0) { 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'); + for (const filter of this.actionFilters) { + if (filter === 'drop' && (action === 'DROP' || action.includes('DROP'))) return true; + if (filter === 'reject' && (action === 'REJECT' || action.includes('REJECT'))) return true; + if (filter === 'accept' && (action === 'ACCEPT' || action.includes('ACCEPT'))) return true; + if (filter === 'log' && (action === 'LOG' || action.includes('LOG'))) return true; + if (filter === 'other' && action && !['DROP', 'REJECT', 'ACCEPT', 'LOG'].some(a => action.includes(a))) return true; + } + return false; }); } - // Apply protocol filter - if (this.protocolFilter !== 'all') { + // Apply protocol filters (multi-select) + if (this.protocolFilters.length > 0) { 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; + for (const filter of this.protocolFilters) { + if (filter === 'tcp' && proto === 'TCP') return true; + if (filter === 'udp' && proto === 'UDP') return true; + if (filter === 'icmp' && (proto === 'ICMP' || proto === 'ICMPV6')) return true; + if (filter === 'gre' && proto === 'GRE') return true; + if (filter === 'esp' && proto === 'ESP') return true; + if (filter === 'ah' && proto === 'AH') return true; + if (filter === 'sctp' && proto === 'SCTP') return true; + if (filter === 'igmp' && proto === 'IGMP') return true; + if (filter === 'other' && proto && !['TCP', 'UDP', 'ICMP', 'ICMPV6', 'GRE', 'ESP', 'AH', 'SCTP', 'IGMP'].includes(proto)) return true; + } + return false; }); } @@ -662,13 +828,13 @@ >
- +
Policy: + + +
- +
Protocol: + + + + +