Refactor Proxmox server views for improved UI consistency and usability
- Updated server card component to use new UI elements and improved layout. - Enhanced status display with badges and better status indicators. - Refined quick info row for server details with consistent styling. - Reorganized server configuration statistics into stat cards for clarity. - Improved help modals for statistics and storage management sections. - Streamlined alerts and warnings for better user experience. - Updated storage management view to utilize new UI components and improve readability.
This commit is contained in:
@@ -56,85 +56,36 @@
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
{{-- Page Header --}}
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold">Firewall Management</h1>
|
||||
<p class="text-sm text-base/60 mt-1">Configure firewall rules, policies, aliases, and IPSets for your virtual machine</p>
|
||||
</div>
|
||||
<x-proxmox::ui.section-header
|
||||
title="Firewall Management"
|
||||
subtitle="Configure firewall rules, policies, aliases, and IPSets for your virtual machine"
|
||||
icon="ri-shield-line"
|
||||
/>
|
||||
|
||||
{{-- Error Modal --}}
|
||||
@if($error && $showErrorModal)
|
||||
<div class="fixed inset-0 z-[60] bg-black/50 backdrop-blur-sm flex items-center justify-center p-4">
|
||||
<div class="relative w-full max-w-md bg-background-secondary rounded-xl border border-neutral/20 shadow-2xl p-6">
|
||||
<x-proxmox::ui.modal title="Error" icon="ri-error-warning-line" icon-class="text-error" :show="true" wire:key="error-modal">
|
||||
<x-slot name="header">
|
||||
<button wire:click="$set('showErrorModal', false)" class="absolute top-4 right-4 text-base/50 hover:text-base transition-colors">
|
||||
<x-ri-close-line class="size-5" />
|
||||
</button>
|
||||
<div class="flex items-start gap-3 mb-4">
|
||||
<div class="flex-shrink-0 w-10 h-10 rounded-full bg-error/20 flex items-center justify-center">
|
||||
<x-ri-error-warning-line class="size-5 text-error" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold">Error</h3>
|
||||
<p class="text-sm text-base/70 mt-1">{{ $error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
<button wire:click="$set('showErrorModal', false)" class="px-4 py-2 bg-background border border-neutral rounded-lg hover:bg-background-secondary transition-colors text-sm font-medium">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-slot>
|
||||
<p class="text-sm text-base/70">{{ $error }}</p>
|
||||
<x-slot name="footer">
|
||||
<x-proxmox::ui.button wire:click="$set('showErrorModal', false)" variant="secondary">
|
||||
Close
|
||||
</x-proxmox::ui.button>
|
||||
</x-slot>
|
||||
</x-proxmox::ui.modal>
|
||||
@endif
|
||||
|
||||
{{-- Main Firewall Toggle & Status --}}
|
||||
<div class="bg-gradient-to-br from-primary/10 to-primary/5 border border-primary/20 rounded-xl p-6 mb-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="w-12 h-12 rounded-xl bg-primary/20 flex items-center justify-center">
|
||||
<x-ri-shield-line class="size-6 text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-xl font-semibold">Master Firewall Control</h2>
|
||||
<p class="text-sm text-base/60 mt-1">
|
||||
@if($firewallEnabled)
|
||||
<span class="text-success font-medium">✓ Active - Your VM is protected by firewall rules</span>
|
||||
@else
|
||||
<span class="text-warning font-medium">⚠ Disabled - Your VM has no firewall protection</span>
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
@if($firewallEnabled)
|
||||
<button type="button"
|
||||
wire:click="toggleFirewall"
|
||||
wire:loading.attr="disabled"
|
||||
style="padding: 0.5rem 1rem; background-color: #ef4444; color: white; border-radius: 0.5rem; transition: all 0.2s; font-size: 0.875rem; font-weight: 500; display: flex; align-items: center; gap: 0.5rem;"
|
||||
onmouseover="this.style.backgroundColor='#dc2626'"
|
||||
onmouseout="this.style.backgroundColor='#ef4444'">
|
||||
<x-ri-close-line class="size-4" />
|
||||
<span wire:loading.remove wire:target="toggleFirewall">Disable Firewall</span>
|
||||
<span wire:loading wire:target="toggleFirewall">Disabling...</span>
|
||||
</button>
|
||||
@else
|
||||
<button type="button"
|
||||
wire:click="toggleFirewall"
|
||||
wire:loading.attr="disabled"
|
||||
class="px-4 py-2 bg-success text-white rounded-lg hover:bg-success/90 transition-colors text-sm font-medium flex items-center gap-2">
|
||||
<x-ri-shield-line class="size-4" />
|
||||
<span wire:loading.remove wire:target="toggleFirewall">Enable Firewall</span>
|
||||
<span wire:loading wire:target="toggleFirewall">Enabling...</span>
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{-- Main Firewall Toggle & Status --}}\n <div class=\"relative overflow-hidden rounded-xl border border-primary/20 bg-gradient-to-br from-primary/10 via-primary/5 to-transparent p-6 mb-6\">\n {{-- Decorative elements --}}\n <div class=\"absolute top-0 right-0 w-32 h-32 bg-primary/10 rounded-full -translate-y-1/2 translate-x-1/2 blur-2xl\"></div>\n <div class=\"absolute bottom-0 left-0 w-24 h-24 bg-primary/5 rounded-full translate-y-1/2 -translate-x-1/2 blur-xl\"></div>\n \n <div class=\"relative flex flex-col sm:flex-row sm:items-center justify-between gap-4\">\n <div class=\"flex items-center gap-4\">\n <div class=\"w-12 h-12 rounded-xl bg-primary/20 flex items-center justify-center ring-4 ring-primary/10\">\n <x-ri-shield-line class=\"size-6 text-primary\" />\n </div>\n <div>\n <h2 class=\"text-xl font-bold\">Master Firewall Control</h2>\n <p class=\"text-sm mt-1\">\n @if($firewallEnabled)\n <span class=\"inline-flex items-center gap-1.5 text-success font-medium\">\n <span class=\"relative flex h-2 w-2\">\n <span class=\"absolute inline-flex h-full w-full rounded-full bg-success opacity-75 animate-ping\"></span>\n <span class=\"relative inline-flex rounded-full h-2 w-2 bg-success\"></span>\n </span>\n Active - Your VM is protected\n </span>\n @else\n <span class=\"inline-flex items-center gap-1.5 text-warning font-medium\">\n <x-ri-error-warning-line class=\"size-4\" />\n Disabled - No firewall protection\n </span>\n @endif\n </p>\n </div>\n </div>\n <div class=\"flex items-center gap-2\">\n @if($firewallEnabled)\n <x-proxmox::ui.button \n wire:click=\"toggleFirewall\" \n wire:loading.attr=\"disabled\"\n variant=\"danger\"\n icon=\"ri-shield-off-line\">\n <span wire:loading.remove wire:target=\"toggleFirewall\">Disable</span>\n <span wire:loading wire:target=\"toggleFirewall\">Disabling...</span>\n </x-proxmox::ui.button>\n @else\n <x-proxmox::ui.button \n wire:click=\"toggleFirewall\" \n wire:loading.attr=\"disabled\"\n variant=\"success\"\n icon=\"ri-shield-check-line\">\n <span wire:loading.remove wire:target=\"toggleFirewall\">Enable Firewall</span>\n <span wire:loading wire:target=\"toggleFirewall\">Enabling...</span>\n </x-proxmox::ui.button>\n @endif\n </div>\n </div>\n </div>
|
||||
|
||||
{{-- Firewall Policies & Network Adapters Grid --}}
|
||||
@if($firewallEnabled)
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
||||
{{-- Default Policies Card --}}
|
||||
<div class="bg-background border border-neutral rounded-xl p-6">
|
||||
<x-proxmox::ui.card>
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-lg bg-warning/10 flex items-center justify-center">
|
||||
@@ -151,35 +102,36 @@
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-2">Incoming Traffic (Policy In)</label>
|
||||
<select wire:model="policyIn" class="w-full px-3 py-2 border border-neutral rounded-lg bg-background text-sm">
|
||||
<option value="ACCEPT">Accept</option>
|
||||
<option value="REJECT">Reject</option>
|
||||
<option value="DROP">Drop</option>
|
||||
</select>
|
||||
<p class="text-xs text-base/60 mt-1">Default action for incoming traffic not matching any rule</p>
|
||||
</div>
|
||||
<x-proxmox::ui.select
|
||||
wire:model="policyIn"
|
||||
label="Incoming Traffic (Policy In)"
|
||||
help="Default action for incoming traffic not matching any rule">
|
||||
<option value="ACCEPT">Accept</option>
|
||||
<option value="REJECT">Reject</option>
|
||||
<option value="DROP">Drop</option>
|
||||
</x-proxmox::ui.select>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium mb-2">Outgoing Traffic (Policy Out)</label>
|
||||
<select wire:model="policyOut" class="w-full px-3 py-2 border border-neutral rounded-lg bg-background text-sm">
|
||||
<option value="ACCEPT">Accept</option>
|
||||
<option value="REJECT">Reject</option>
|
||||
<option value="DROP">Drop</option>
|
||||
</select>
|
||||
<p class="text-xs text-base/60 mt-1">Default action for outgoing traffic not matching any rule</p>
|
||||
</div>
|
||||
<x-proxmox::ui.select
|
||||
wire:model="policyOut"
|
||||
label="Outgoing Traffic (Policy Out)"
|
||||
help="Default action for outgoing traffic not matching any rule">
|
||||
<option value="ACCEPT">Accept</option>
|
||||
<option value="REJECT">Reject</option>
|
||||
<option value="DROP">Drop</option>
|
||||
</x-proxmox::ui.select>
|
||||
|
||||
<button type="button" wire:click="updatePolicies" wire:loading.attr="disabled" class="w-full px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors text-sm font-medium mt-4">
|
||||
<x-proxmox::ui.button
|
||||
wire:click="updatePolicies"
|
||||
wire:loading.attr="disabled"
|
||||
class="w-full mt-4">
|
||||
<span wire:loading.remove wire:target="updatePolicies">Update Policies</span>
|
||||
<span wire:loading wire:target="updatePolicies">Updating...</span>
|
||||
</button>
|
||||
</x-proxmox::ui.button>
|
||||
</div>
|
||||
</div>
|
||||
</x-proxmox::ui.card>
|
||||
|
||||
{{-- Network Adapters --}}
|
||||
<div class="bg-background border border-neutral rounded-xl p-6">
|
||||
<x-proxmox::ui.card>
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-10 h-10 rounded-lg bg-success/10 flex items-center justify-center">
|
||||
<x-ri-router-line class="size-5 text-success" />
|
||||
@@ -198,11 +150,9 @@
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center gap-2 mb-1">
|
||||
<span class="font-semibold text-sm">{{ $adapter['name'] }}</span>
|
||||
@if($adapterFirewallStates[$adapter['name']] ?? false)
|
||||
<span class="px-2 py-0.5 bg-success/20 text-success text-xs font-medium rounded-full">Active</span>
|
||||
@else
|
||||
<span class="px-2 py-0.5 bg-base/20 text-base/60 text-xs font-medium rounded-full">Off</span>
|
||||
@endif
|
||||
<x-proxmox::ui.badge :variant="($adapterFirewallStates[$adapter['name']] ?? false) ? 'success' : 'secondary'">
|
||||
{{ ($adapterFirewallStates[$adapter['name']] ?? false) ? 'Active' : 'Off' }}
|
||||
</x-proxmox::ui.badge>
|
||||
</div>
|
||||
<div class="text-xs text-base/60">
|
||||
{{ ucfirst($adapter['model'] ?? 'Unknown') }}
|
||||
@@ -213,27 +163,27 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
@if($adapterFirewallStates[$adapter['name']] ?? false)
|
||||
<button type="button"
|
||||
wire:click="toggleAdapterFirewall('{{ $adapter['name'] }}')"
|
||||
wire:loading.attr="disabled"
|
||||
wire:key="adapter-{{ $adapter['name'] }}"
|
||||
style="padding: 0.375rem 0.75rem; background-color: #ef4444; color: white; border-radius: 0.5rem; transition: all 0.2s; font-size: 0.75rem; font-weight: 500; display: flex; align-items: center; gap: 0.375rem;"
|
||||
onmouseover="this.style.backgroundColor='#dc2626'"
|
||||
onmouseout="this.style.backgroundColor='#ef4444'">
|
||||
<x-ri-close-line class="size-3.5" />
|
||||
<x-proxmox::ui.button
|
||||
wire:click="toggleAdapterFirewall('{{ $adapter['name'] }}')"
|
||||
wire:loading.attr="disabled"
|
||||
wire:key="adapter-{{ $adapter['name'] }}"
|
||||
variant="danger"
|
||||
size="sm"
|
||||
icon="ri-close-line">
|
||||
<span wire:loading.remove wire:target="toggleAdapterFirewall('{{ $adapter['name'] }}')">Disable</span>
|
||||
<span wire:loading wire:target="toggleAdapterFirewall('{{ $adapter['name'] }}')">...</span>
|
||||
</button>
|
||||
</x-proxmox::ui.button>
|
||||
@else
|
||||
<button type="button"
|
||||
wire:click="toggleAdapterFirewall('{{ $adapter['name'] }}')"
|
||||
wire:loading.attr="disabled"
|
||||
wire:key="adapter-{{ $adapter['name'] }}"
|
||||
class="px-3 py-1.5 bg-success text-white rounded-lg hover:bg-success/90 transition-colors text-xs font-medium flex items-center gap-1.5">
|
||||
<x-ri-shield-line class="size-3.5" />
|
||||
<x-proxmox::ui.button
|
||||
wire:click="toggleAdapterFirewall('{{ $adapter['name'] }}')"
|
||||
wire:loading.attr="disabled"
|
||||
wire:key="adapter-{{ $adapter['name'] }}"
|
||||
variant="success"
|
||||
size="sm"
|
||||
icon="ri-shield-line">
|
||||
<span wire:loading.remove wire:target="toggleAdapterFirewall('{{ $adapter['name'] }}')">Enable</span>
|
||||
<span wire:loading wire:target="toggleAdapterFirewall('{{ $adapter['name'] }}')">...</span>
|
||||
</button>
|
||||
</x-proxmox::ui.button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@@ -241,12 +191,12 @@
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<div class="text-center py-4 text-base/60 text-sm">
|
||||
<x-ri-router-line class="size-8 mx-auto mb-2 opacity-50" />
|
||||
<p>No network adapters found</p>
|
||||
</div>
|
||||
<x-proxmox::ui.empty-state
|
||||
icon="ri-router-line"
|
||||
title="No Network Adapters"
|
||||
description="No network adapters found on this VM" />
|
||||
@endif
|
||||
</div>
|
||||
</x-proxmox::ui.card>
|
||||
</div>
|
||||
|
||||
{{-- Policy Info Modal --}}
|
||||
@@ -1817,19 +1767,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 12px; justify-content: flex-end;">
|
||||
<button wire:click="cancelDeleteRule"
|
||||
type="button"
|
||||
style="padding: 8px 16px; background-color: rgba(var(--background), 1); border: 1px solid rgba(var(--neutral), 0.3); border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s;">
|
||||
<div class="flex gap-3 justify-end">
|
||||
<x-proxmox::ui.button wire:click="cancelDeleteRule" variant="secondary">
|
||||
Cancel
|
||||
</button>
|
||||
<button wire:click="deleteRule"
|
||||
wire:loading.attr="disabled"
|
||||
type="button"
|
||||
style="padding: 8px 16px; background-color: #ef4444; color: white; border: none; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s;">
|
||||
</x-proxmox::ui.button>
|
||||
<x-proxmox::ui.button wire:click="deleteRule" wire:loading.attr="disabled" variant="danger">
|
||||
<span wire:loading.remove wire:target="deleteRule">Delete Rule</span>
|
||||
<span wire:loading wire:target="deleteRule">Deleting...</span>
|
||||
</button>
|
||||
</x-proxmox::ui.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1894,16 +1839,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-3 justify-end">
|
||||
<button wire:click="cancelDeleteAlias" class="px-4 py-2 bg-background border border-neutral rounded-lg hover:bg-background-secondary transition-colors text-sm font-medium">
|
||||
<x-proxmox::ui.button wire:click="cancelDeleteAlias" variant="secondary">
|
||||
Cancel
|
||||
</button>
|
||||
<button wire:click="deleteAlias" wire:loading.attr="disabled"
|
||||
style="padding: 0.5rem 1rem; background-color: #ef4444; color: white; border-radius: 0.5rem; transition: all 0.2s; font-size: 0.875rem; font-weight: 500;"
|
||||
onmouseover="this.style.backgroundColor='#dc2626'"
|
||||
onmouseout="this.style.backgroundColor='#ef4444'">
|
||||
</x-proxmox::ui.button>
|
||||
<x-proxmox::ui.button wire:click="deleteAlias" wire:loading.attr="disabled" variant="danger">
|
||||
<span wire:loading.remove wire:target="deleteAlias">Delete</span>
|
||||
<span wire:loading wire:target="deleteAlias">Deleting...</span>
|
||||
</button>
|
||||
</x-proxmox::ui.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1966,16 +1908,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-3 justify-end">
|
||||
<button wire:click="cancelDeleteIPSet" class="px-4 py-2 bg-background border border-neutral rounded-lg hover:bg-background-secondary transition-colors text-sm font-medium">
|
||||
<x-proxmox::ui.button wire:click="cancelDeleteIPSet" variant="secondary">
|
||||
Cancel
|
||||
</button>
|
||||
<button wire:click="deleteIPSet" wire:loading.attr="disabled"
|
||||
style="padding: 0.5rem 1rem; background-color: #ef4444; color: white; border-radius: 0.5rem; transition: all 0.2s; font-size: 0.875rem; font-weight: 500;"
|
||||
onmouseover="this.style.backgroundColor='#dc2626'"
|
||||
onmouseout="this.style.backgroundColor='#ef4444'">
|
||||
</x-proxmox::ui.button>
|
||||
<x-proxmox::ui.button wire:click="deleteIPSet" wire:loading.attr="disabled" variant="danger">
|
||||
<span wire:loading.remove wire:target="deleteIPSet">Delete</span>
|
||||
<span wire:loading wire:target="deleteIPSet">Deleting...</span>
|
||||
</button>
|
||||
</x-proxmox::ui.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2041,16 +1980,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-3 justify-end">
|
||||
<button wire:click="cancelDeleteIPSetMember" class="px-4 py-2 bg-background border border-neutral rounded-lg hover:bg-background-secondary transition-colors text-sm font-medium">
|
||||
<x-proxmox::ui.button wire:click="cancelDeleteIPSetMember" variant="secondary">
|
||||
Cancel
|
||||
</button>
|
||||
<button wire:click="deleteIPSetMember" wire:loading.attr="disabled"
|
||||
style="padding: 0.5rem 1rem; background-color: #ef4444; color: white; border-radius: 0.5rem; transition: all 0.2s; font-size: 0.875rem; font-weight: 500;"
|
||||
onmouseover="this.style.backgroundColor='#dc2626'"
|
||||
onmouseout="this.style.backgroundColor='#ef4444'">
|
||||
</x-proxmox::ui.button>
|
||||
<x-proxmox::ui.button wire:click="deleteIPSetMember" wire:loading.attr="disabled" variant="danger">
|
||||
<span wire:loading.remove wire:target="deleteIPSetMember">Remove</span>
|
||||
<span wire:loading wire:target="deleteIPSetMember">Removing...</span>
|
||||
</button>
|
||||
</x-proxmox::ui.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2334,16 +2270,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-3 justify-end">
|
||||
<button wire:click="cancelDeleteConfiguration" class="px-4 py-2 bg-background border border-neutral rounded-lg hover:bg-background-secondary transition-colors text-sm font-medium">
|
||||
<x-proxmox::ui.button wire:click="cancelDeleteConfiguration" variant="secondary">
|
||||
Cancel
|
||||
</button>
|
||||
<button wire:click="deleteConfiguration" wire:loading.attr="disabled"
|
||||
style="padding: 0.5rem 1rem; background-color: #ef4444; color: white; border-radius: 0.5rem; transition: all 0.2s; font-size: 0.875rem; font-weight: 500;"
|
||||
onmouseover="this.style.backgroundColor='#dc2626'"
|
||||
onmouseout="this.style.backgroundColor='#ef4444'">
|
||||
</x-proxmox::ui.button>
|
||||
<x-proxmox::ui.button wire:click="deleteConfiguration" wire:loading.attr="disabled" variant="danger">
|
||||
<span wire:loading.remove wire:target="deleteConfiguration">Delete</span>
|
||||
<span wire:loading wire:target="deleteConfiguration">Deleting...</span>
|
||||
</button>
|
||||
</x-proxmox::ui.button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user