Private
Public Access
1
0

feat: add state details button and modal to firewall logs for enhanced connection state visibility and user interaction

This commit is contained in:
2025-12-03 18:54:07 -05:00
parent b6e045dc93
commit a6cec4ee22

View File

@@ -348,8 +348,8 @@
border-top: 1px solid rgba(var(--color-neutral), 0.3);
}
/* Network Analysis Link */
.firewall-network-link {
/* State Details Button */
.firewall-state-btn {
display: inline-flex;
align-items: center;
gap: 0.375rem;
@@ -357,17 +357,17 @@
font-size: 0.7rem;
font-weight: 500;
border-radius: 0.375rem;
background-color: rgba(var(--color-primary), 0.1);
color: rgba(var(--color-primary), 1);
border: 1px solid rgba(var(--color-primary), 0.3);
text-decoration: none;
background-color: rgba(var(--color-info), 0.1);
color: rgba(var(--color-info), 1);
border: 1px solid rgba(var(--color-info), 0.3);
cursor: pointer;
transition: all 0.15s ease;
white-space: nowrap;
}
.firewall-network-link:hover {
background-color: rgba(var(--color-primary), 0.2);
border-color: rgba(var(--color-primary), 0.5);
color: rgba(var(--color-primary), 1);
.firewall-state-btn:hover {
background-color: rgba(var(--color-info), 0.2);
border-color: rgba(var(--color-info), 0.5);
color: rgba(var(--color-info), 1);
}
</style>
@@ -1466,14 +1466,146 @@
<!-- Actions -->
<td class="py-3 px-4 text-sm">
<template x-if="log.source && log.source !== '-'">
<a :href="'{{ route('proxmox.server.statistics', ['server' => $server->id]) }}?network_search=' + encodeURIComponent(log.source) + '#network-analysis-card'"
class="firewall-network-link"
title="View connection in Network Analysis">
<x-ri-line-chart-line style="width: 14px; height: 14px;" />
<span>Network</span>
</a>
</template>
<div x-data="{ showStateModal: false }">
<button type="button"
@click="showStateModal = true"
class="firewall-state-btn"
title="View connection state details">
<x-ri-information-line style="width: 14px; height: 14px;" />
<span>Details</span>
</button>
<!-- State Details Modal -->
<div x-show="showStateModal"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
@click="showStateModal = false"
@keydown.escape.window="showStateModal = false"
class="fixed inset-0 z-50 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4"
style="display: none;">
<div @click.stop class="relative w-full max-w-lg bg-background-secondary rounded-xl border border-neutral/20 shadow-2xl max-h-[90vh] overflow-y-auto">
<button @click="showStateModal = false" class="absolute top-4 right-4 text-base/50 hover:text-base transition-colors z-10">
<x-ri-close-line class="size-5" />
</button>
<div class="p-6">
<!-- Header -->
<div class="flex items-center gap-3 mb-6 pb-4 border-b border-neutral/20">
<div class="p-2 rounded-lg" :class="log.action === 'DROP' || log.action === 'REJECT' ? 'bg-danger/20' : 'bg-success/20'">
<template x-if="log.action === 'DROP' || log.action === 'REJECT'">
<x-ri-shield-cross-line class="size-6 text-danger" />
</template>
<template x-if="log.action === 'ACCEPT'">
<x-ri-shield-check-line class="size-6 text-success" />
</template>
<template x-if="log.action !== 'DROP' && log.action !== 'REJECT' && log.action !== 'ACCEPT'">
<x-ri-shield-line class="size-6 text-base/70" />
</template>
</div>
<div>
<h3 class="text-lg font-semibold">Connection State</h3>
<p class="text-sm text-base/60" x-text="log.timestamp_display || 'Unknown time'"></p>
</div>
</div>
<!-- Action Badge -->
<div class="mb-4">
<span class="px-3 py-1.5 rounded-lg text-sm font-semibold" :class="log.action_badge_class" x-text="log.action || 'UNKNOWN'"></span>
</div>
<!-- Connection Details Grid -->
<div class="grid grid-cols-2 gap-4">
<!-- Source Section -->
<div class="col-span-2 sm:col-span-1 p-4 bg-background rounded-lg border border-neutral/20">
<div class="flex items-center gap-2 mb-3">
<x-ri-arrow-right-up-line class="size-4 text-info" />
<span class="text-xs font-semibold text-base/60 uppercase tracking-wide">Source</span>
</div>
<div class="space-y-2">
<div>
<span class="text-xs text-base/50">IP Address</span>
<p class="font-mono text-sm font-medium break-all" x-text="log.source || '-'"></p>
</div>
<div>
<span class="text-xs text-base/50">Port</span>
<p class="font-mono text-sm font-medium" x-text="log.source_port || '-'"></p>
</div>
</div>
</div>
<!-- Destination Section -->
<div class="col-span-2 sm:col-span-1 p-4 bg-background rounded-lg border border-neutral/20">
<div class="flex items-center gap-2 mb-3">
<x-ri-arrow-right-down-line class="size-4 text-warning" />
<span class="text-xs font-semibold text-base/60 uppercase tracking-wide">Destination</span>
</div>
<div class="space-y-2">
<div>
<span class="text-xs text-base/50">IP Address</span>
<p class="font-mono text-sm font-medium break-all" x-text="log.destination || '-'"></p>
</div>
<div>
<span class="text-xs text-base/50">Port</span>
<p class="font-mono text-sm font-medium" x-text="log.destination_port || '-'"></p>
</div>
</div>
</div>
<!-- Protocol & Level -->
<div class="col-span-2 p-4 bg-background rounded-lg border border-neutral/20">
<div class="grid grid-cols-2 sm:grid-cols-4 gap-4">
<div>
<span class="text-xs text-base/50">Protocol</span>
<p class="text-sm font-semibold" x-text="log.protocol || '-'"></p>
</div>
<div>
<span class="text-xs text-base/50">Level</span>
<p class="text-sm">
<span class="px-2 py-0.5 rounded text-xs font-semibold uppercase" :class="log.level_badge_class" x-text="log.level_label || '-'"></span>
</p>
</div>
<div>
<span class="text-xs text-base/50">Interface</span>
<p class="font-mono text-sm font-medium" x-text="log.interface || '-'"></p>
</div>
<div>
<span class="text-xs text-base/50">MAC Address</span>
<p class="font-mono text-xs font-medium break-all" x-text="log.mac || '-'"></p>
</div>
</div>
</div>
<!-- Raw Log (if available) -->
<template x-if="log.raw">
<div class="col-span-2 p-4 bg-background rounded-lg border border-neutral/20">
<div class="flex items-center gap-2 mb-2">
<x-ri-code-line class="size-4 text-base/50" />
<span class="text-xs font-semibold text-base/60 uppercase tracking-wide">Raw Log Entry</span>
</div>
<pre class="text-xs font-mono text-base/70 whitespace-pre-wrap break-all bg-background-secondary p-3 rounded-lg border border-neutral/10 max-h-32 overflow-y-auto" x-text="log.raw"></pre>
</div>
</template>
</div>
<!-- Footer Actions -->
<div class="mt-6 pt-4 border-t border-neutral/20 flex justify-end gap-2">
<a :href="'{{ route('proxmox.server.statistics', ['server' => $server->id]) }}?network_search=' + encodeURIComponent(log.source || '') + '#network-analysis-card'"
class="px-4 py-2 text-sm font-medium bg-primary/10 text-primary border border-primary/30 rounded-lg hover:bg-primary/20 transition-colors inline-flex items-center gap-2">
<x-ri-line-chart-line class="size-4" />
View in Network Analysis
</a>
<button @click="showStateModal = false" class="px-4 py-2 text-sm font-medium bg-base/10 text-base/70 border border-neutral/30 rounded-lg hover:bg-base/20 transition-colors">
Close
</button>
</div>
</div>
</div>
</div>
</div>
</td>
</tr>
</template>