feat: add state details button and modal to firewall logs for enhanced connection state visibility and user interaction
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user