refactor: streamline UI elements and improve layout for better readability and consistency
This commit is contained in:
@@ -314,19 +314,14 @@
|
||||
<div class="pt-3 border-t border-gray-200 dark:border-gray-700 space-y-1.5 text-xs text-gray-600 dark:text-gray-400">
|
||||
<p><span class="font-semibold text-gray-700 dark:text-gray-300">CPU:</span> Live usage % of vCPU entitlement.</p>
|
||||
<p><span class="font-semibold text-gray-700 dark:text-gray-300">Memory:</span> RAM usage vs provisioned.</p>
|
||||
<p class="block font-sans text-xs font-normal leading-relaxed text-base/75">
|
||||
<span class="font-semibold text-base/90">Hypervisor Uptime:</span> Shows the live uptime plus power event statistics from the task history.
|
||||
</p>
|
||||
<p class="block font-sans text-xs font-normal leading-relaxed text-base/75">
|
||||
<span class="font-semibold text-base/90">Status Badges:</span> "Healthy" (green) for normal usage, "Watchlist" (yellow) at 85%+, "Over entitlement" (red) when exceeded.
|
||||
</p>
|
||||
<p><span class="font-semibold text-gray-700 dark:text-gray-300">Uptime:</span> Live uptime + power events.</p>
|
||||
<p><span class="font-semibold text-gray-700 dark:text-gray-300">Badges:</span> Healthy (green), Watchlist (yellow 85%+), Over (red).</p>
|
||||
</div>
|
||||
</x-proxmox::ui.help-modal>
|
||||
<p class="text-sm text-base/70 ml-2 hidden md:block">Instantly compare entitlement with current consumption.</p>
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400 ml-2 hidden md:inline">Live refresh</span>
|
||||
</div>
|
||||
<p class="text-xs text-base/50">Values refresh alongside the live status poll.</p>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-3">
|
||||
@foreach($resourceAllocations as $resource)
|
||||
<x-proxmox::ui.allocation-card
|
||||
:label="$resource['label']"
|
||||
@@ -341,114 +336,96 @@
|
||||
</div>
|
||||
</x-proxmox::ui.card>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 mt-8 md:items-stretch">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mt-4 md:items-stretch">
|
||||
|
||||
<div class="grid gap-8 items-start">
|
||||
<div class="grid gap-4 items-start">
|
||||
<!-- Details -->
|
||||
<div class="">
|
||||
<div>
|
||||
|
||||
<div>
|
||||
<div style="background-image: url('https://billing.virtnet.bond/assets/images/main.png'); background-size: 100%; height: 5.5vh;" class="flex flex-col p-4 rounded-t-lg border-t border-x border-neutral"></div>
|
||||
<div style="background-image: url('https://billing.virtnet.bond/assets/images/main.png'); background-size: cover; height: 3rem;" class="rounded-t-lg border-t border-x border-gray-200 dark:border-gray-700"></div>
|
||||
|
||||
<!-- Status Section -->
|
||||
<div class="bg-background-secondary border-x border-neutral p-4 space-y-4 rounded-m-lg">
|
||||
<div class="bg-white dark:bg-gray-800 border-x border-gray-200 dark:border-gray-700 p-3 space-y-3">
|
||||
<!-- Status -->
|
||||
<div class="space-y-2">
|
||||
<label class="text-sm font-semibold text-base/80">Status</label>
|
||||
<div class="flex items-center gap-2 px-3 py-2 text-sm text-base/80">
|
||||
<div class="relative inline-flex size-5">
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="text-xs font-semibold text-gray-600 dark:text-gray-400">Status</label>
|
||||
<div class="flex items-center gap-1.5 text-sm">
|
||||
<div class="relative inline-flex size-4">
|
||||
@if ($status && $status->status === 'running')
|
||||
<span class="absolute inset-0 rounded-full bg-success/20 animate-ping"></span>
|
||||
<span class="relative flex items-center justify-center size-5 p-1 rounded-full text-success bg-success/20">
|
||||
<x-ri-circle-fill />
|
||||
<span class="absolute inset-0 rounded-full bg-green-500 animate-ping opacity-75"></span>
|
||||
<span class="relative flex items-center justify-center size-4 rounded-full text-green-600 bg-green-100 dark:bg-green-900">
|
||||
<x-ri-circle-fill class="size-2" />
|
||||
</span>
|
||||
@else
|
||||
<span class="flex items-center justify-center size-5 p-1 rounded-full text-warning bg-warning/20">
|
||||
<x-ri-error-warning-fill />
|
||||
<span class="flex items-center justify-center size-4 rounded-full text-amber-600 bg-amber-100 dark:bg-amber-900">
|
||||
<x-ri-error-warning-fill class="size-2" />
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
<span class="truncate flex-1">
|
||||
<span class="font-medium text-gray-800 dark:text-gray-200">
|
||||
{{ $status && $status->status === 'running' ? 'Running' : 'Stopped' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Operating System -->
|
||||
<div class="space-y-2">
|
||||
<label class="text-sm font-semibold text-base/80">Operating System</label>
|
||||
<div class="flex items-center gap-2 px-3 py-2 text-sm text-base/80">
|
||||
<span class="truncate flex-1">
|
||||
{{ $server->os->name }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="text-xs font-semibold text-gray-600 dark:text-gray-400">OS</label>
|
||||
<span class="text-sm text-gray-800 dark:text-gray-200">{{ $server->os->name }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Hostname -->
|
||||
<div class="space-y-2" x-data="{ showHostnameEditModal: @entangle('isEditingHostname') }">
|
||||
<label class="text-sm font-semibold text-base/80">Hostname</label>
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center gap-2 border border-neutral rounded-md bg-background px-3 py-2 text-sm text-base/80">
|
||||
<span class="truncate flex-1">
|
||||
{{ $server->hostname ?? $status->name ?? 'N/A' }}
|
||||
</span>
|
||||
<button wire:click="startEditingHostname" type="button"
|
||||
class="text-base/70 hover:text-base/60 ml-2"
|
||||
aria-label="Edit Hostname">
|
||||
<x-ri-edit-fill class="inline size-4" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center justify-between" x-data="{ showHostnameEditModal: @entangle('isEditingHostname') }">
|
||||
<label class="text-xs font-semibold text-gray-600 dark:text-gray-400">Hostname</label>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-sm font-mono text-gray-800 dark:text-gray-200">{{ $server->hostname ?? $status->name ?? 'N/A' }}</span>
|
||||
<button wire:click="startEditingHostname" type="button" class="text-gray-500 hover:text-gray-700 dark:text-gray-400">
|
||||
<x-ri-edit-fill class="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Hostname Edit Modal -->
|
||||
<!-- Modal Backdrop -->
|
||||
<div x-cloak x-show="showHostnameEditModal"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
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-200"
|
||||
x-transition:leave="transition ease-in duration-150"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
@click="showHostnameEditModal = false; $wire.cancelEditingHostname()"
|
||||
@keydown.escape.window="showHostnameEditModal = false; $wire.cancelEditingHostname()"
|
||||
class="fixed inset-0 z-50 bg-black/50 backdrop-blur-sm"
|
||||
class="fixed inset-0 z-50 bg-gray-900 bg-opacity-50"
|
||||
style="display: none;">
|
||||
</div>
|
||||
<!-- Modal -->
|
||||
<div x-cloak x-show="showHostnameEditModal"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0 scale-95"
|
||||
x-transition:enter-end="opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave="transition ease-in duration-150"
|
||||
x-transition:leave-start="opacity-100 scale-100"
|
||||
x-transition:leave-end="opacity-0 scale-95"
|
||||
@click.away="showHostnameEditModal = false; $wire.cancelEditingHostname()"
|
||||
class="fixed inset-0 z-50 flex items-center justify-center p-4"
|
||||
style="display: none;">
|
||||
<div class="relative bg-background-secondary border border-neutral rounded-lg shadow-xl w-full max-w-xl mx-4 p-5 space-y-4">
|
||||
<div class="relative bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-xl w-full max-w-md p-4 space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<h4 class="text-base font-semibold text-base/90">Edit Hostname</h4>
|
||||
<button type="button"
|
||||
class="bg-background border border-neutral p-1.5 rounded-md hover:bg-background/80"
|
||||
@click="showHostnameEditModal = false; $wire.cancelEditingHostname()"
|
||||
aria-label="Close hostname edit modal">
|
||||
<h4 class="text-sm font-semibold text-gray-800 dark:text-gray-100">Edit Hostname</h4>
|
||||
<button type="button" class="text-gray-400 hover:text-gray-600 p-1"
|
||||
@click="showHostnameEditModal = false; $wire.cancelEditingHostname()">
|
||||
<x-ri-close-line class="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="space-y-3">
|
||||
<div class="space-y-2">
|
||||
<div>
|
||||
<label class="text-xs font-semibold text-base/70">Hostname</label>
|
||||
<input type="text"
|
||||
wire:model.defer="hostname"
|
||||
class="form-input w-full mt-1"
|
||||
placeholder="Enter hostname" />
|
||||
<label class="text-xs font-medium text-gray-600 dark:text-gray-400">Hostname</label>
|
||||
<input type="text" wire:model.defer="hostname" class="form-input w-full mt-1 text-sm" placeholder="Enter hostname" />
|
||||
</div>
|
||||
@if($hostnameError)
|
||||
<div class="text-sm text-error">{{ $hostnameError }}</div>
|
||||
<div class="text-xs text-red-600">{{ $hostnameError }}</div>
|
||||
@endif
|
||||
<p class="text-xs text-base/60">
|
||||
<strong>Save:</strong> Updates the hostname in the database and order properties.<br>
|
||||
<strong>Save & Apply:</strong> Saves to database and applies the hostname. (Will be configured on next boot via cloud-init)
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||
<strong>Save:</strong> Database only. <strong>Save & Apply:</strong> + cloud-init on next boot.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex justify-end gap-2">
|
||||
@@ -468,119 +445,71 @@
|
||||
|
||||
<!-- Primary IPv4 Address -->
|
||||
@if($server->primaryIpv4)
|
||||
<div class="space-y-2">
|
||||
<label class="text-sm font-semibold text-base/80">Primary IPv4 Address</label>
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center gap-2 border border-neutral rounded-md bg-background px-3 py-2 text-sm text-base/80"
|
||||
x-data="{
|
||||
copied: false,
|
||||
copyText: '{{ $server->primaryIpv4->ip }}',
|
||||
copyToClipboard() {
|
||||
navigator.clipboard.writeText(this.copyText);
|
||||
this.copied = true;
|
||||
setTimeout(() => this.copied = false, 3000);
|
||||
}
|
||||
}">
|
||||
<span class="truncate flex-1">
|
||||
{{ $server->primaryIpv4->ip }}
|
||||
</span>
|
||||
<button @click="copyToClipboard()" type="button"
|
||||
class="text-base/70 hover:text-base/60 ml-2 relative inline-flex items-center justify-center w-4 h-4"
|
||||
aria-label="Copy IPv4 Address">
|
||||
<span x-show="copied" x-transition class="absolute">
|
||||
<x-ri-check-fill class="inline size-4 text-success stroke-current" />
|
||||
</span>
|
||||
<span x-show="!copied" x-transition class="absolute">
|
||||
<x-ri-file-copy-fill class="inline size-4" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center justify-between" x-data="{ copied: false, copyText: '{{ $server->primaryIpv4->ip }}', copy() { navigator.clipboard.writeText(this.copyText); this.copied = true; setTimeout(() => this.copied = false, 2000); } }">
|
||||
<label class="text-xs font-semibold text-gray-600 dark:text-gray-400">IPv4</label>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="text-sm font-mono text-gray-800 dark:text-gray-200">{{ $server->primaryIpv4->ip }}</span>
|
||||
<button @click="copy()" type="button" class="text-gray-500 hover:text-gray-700 dark:text-gray-400">
|
||||
<x-ri-check-fill x-show="copied" class="size-3.5 text-green-600" />
|
||||
<x-ri-file-copy-fill x-show="!copied" class="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Primary IPv6 Address -->
|
||||
@if($server->primaryIpv6)
|
||||
<div class="space-y-2">
|
||||
<label class="text-sm font-semibold text-base/80">Primary IPv6 Address</label>
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center gap-2 border border-neutral rounded-md bg-background px-3 py-2 text-sm text-base/80"
|
||||
x-data="{
|
||||
copied: false,
|
||||
copyText: '{{ $server->primaryIpv6->ip }}',
|
||||
copyToClipboard() {
|
||||
navigator.clipboard.writeText(this.copyText);
|
||||
this.copied = true;
|
||||
setTimeout(() => this.copied = false, 3000);
|
||||
}
|
||||
}">
|
||||
<span class="truncate flex-1">
|
||||
{{ $server->primaryIpv6->ip }}
|
||||
</span>
|
||||
<button @click="copyToClipboard()" type="button"
|
||||
class="text-base/70 hover:text-base/60 ml-2 relative inline-flex items-center justify-center w-4 h-4"
|
||||
aria-label="Copy IPv6 Address">
|
||||
<span x-show="copied" x-transition class="absolute">
|
||||
<x-ri-check-fill class="inline size-4 text-success stroke-current" />
|
||||
</span>
|
||||
<span x-show="!copied" x-transition class="absolute">
|
||||
<x-ri-file-copy-fill class="inline size-4" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center justify-between" x-data="{ copied: false, copyText: '{{ $server->primaryIpv6->ip }}', copy() { navigator.clipboard.writeText(this.copyText); this.copied = true; setTimeout(() => this.copied = false, 2000); } }">
|
||||
<label class="text-xs font-semibold text-gray-600 dark:text-gray-400">IPv6</label>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="text-xs font-mono text-gray-800 dark:text-gray-200 truncate max-w-[180px]">{{ $server->primaryIpv6->ip }}</span>
|
||||
<button @click="copy()" type="button" class="text-gray-500 hover:text-gray-700 dark:text-gray-400">
|
||||
<x-ri-check-fill x-show="copied" class="size-3.5 text-green-600" />
|
||||
<x-ri-file-copy-fill x-show="!copied" class="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Root Password -->
|
||||
<div class="space-y-2" x-data="{ showPasswordViewModal: false, showPasswordEditModal: @entangle('isEditingPassword') }">
|
||||
<label class="text-sm font-semibold text-base/80">Root Password</label>
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center gap-2 border border-neutral rounded-md bg-background px-3 py-2 text-sm text-base/80">
|
||||
<span class="truncate flex-1">
|
||||
@if(isset($server->password) && $server->password)
|
||||
••••••••••••
|
||||
@else
|
||||
Password is sent via email on install.
|
||||
@endif
|
||||
</span>
|
||||
<div class="flex items-center justify-between" x-data="{ showPasswordViewModal: false, showPasswordEditModal: @entangle('isEditingPassword') }">
|
||||
<label class="text-xs font-semibold text-gray-600 dark:text-gray-400">Password</label>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="text-sm text-gray-800 dark:text-gray-200">
|
||||
@if(isset($server->password) && $server->password)
|
||||
<button type="button"
|
||||
class="text-base/70 hover:text-base/60 ml-2"
|
||||
@click="showPasswordViewModal = true"
|
||||
aria-label="View Root Password">
|
||||
<x-ri-eye-line class="inline size-4" />
|
||||
</button>
|
||||
••••••••
|
||||
@else
|
||||
Emailed
|
||||
@endif
|
||||
<button type="button"
|
||||
class="text-base/70 hover:text-base/60 ml-2"
|
||||
wire:click="startEditingPassword"
|
||||
aria-label="Edit Root Password">
|
||||
<x-ri-edit-fill class="inline size-4" />
|
||||
</span>
|
||||
@if(isset($server->password) && $server->password)
|
||||
<button type="button" class="text-gray-500 hover:text-gray-700 dark:text-gray-400" @click="showPasswordViewModal = true">
|
||||
<x-ri-eye-line class="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
@endif
|
||||
<button type="button" class="text-gray-500 hover:text-gray-700 dark:text-gray-400" wire:click="startEditingPassword">
|
||||
<x-ri-edit-fill class="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Password View Modal -->
|
||||
<!-- Modal Backdrop -->
|
||||
<div x-cloak x-show="showPasswordViewModal"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
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-200"
|
||||
x-transition:leave="transition ease-in duration-150"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
@click="showPasswordViewModal = false"
|
||||
@keydown.escape.window="showPasswordViewModal = false"
|
||||
class="fixed inset-0 z-50 bg-black/50 backdrop-blur-sm"
|
||||
class="fixed inset-0 z-50 bg-gray-900 bg-opacity-50"
|
||||
style="display: none;">
|
||||
</div>
|
||||
<!-- Modal -->
|
||||
<div x-cloak x-show="showPasswordViewModal"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0 scale-95"
|
||||
x-transition:enter-end="opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave="transition ease-in duration-150"
|
||||
x-transition:leave-start="opacity-100 scale-100"
|
||||
x-transition:leave-end="opacity-0 scale-95"
|
||||
@click.away="showPasswordViewModal = false"
|
||||
@@ -589,29 +518,20 @@
|
||||
x-data="{
|
||||
copied: false,
|
||||
copyText: {{ json_encode($server->password) }},
|
||||
copyToClipboard() {
|
||||
navigator.clipboard.writeText(this.copyText);
|
||||
this.copied = true;
|
||||
setTimeout(() => this.copied = false, 3000);
|
||||
}
|
||||
copy() { navigator.clipboard.writeText(this.copyText); this.copied = true; setTimeout(() => this.copied = false, 2000); }
|
||||
}">
|
||||
<div class="relative bg-background-secondary border border-neutral rounded-lg shadow-xl w-full max-w-xl mx-4 p-5 space-y-4">
|
||||
<div class="relative bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-xl w-full max-w-md p-4 space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<h4 class="text-base font-semibold text-base/90">Root Password</h4>
|
||||
<button type="button"
|
||||
class="bg-background border border-neutral p-1.5 rounded-md hover:bg-background/80"
|
||||
@click="showPasswordViewModal = false"
|
||||
aria-label="Close password view modal">
|
||||
<h4 class="text-sm font-semibold text-gray-800 dark:text-gray-100">Root Password</h4>
|
||||
<button type="button" class="text-gray-400 hover:text-gray-600 p-1" @click="showPasswordViewModal = false">
|
||||
<x-ri-close-line class="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="bg-background border border-neutral rounded-md p-3 text-sm text-base/80 overflow-auto">
|
||||
<code class="whitespace-pre-wrap break-all block">{{ $server->password }}</code>
|
||||
<div class="bg-gray-100 dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded p-2 text-sm text-gray-800 dark:text-gray-200 overflow-auto">
|
||||
<code class="break-all block font-mono text-xs">{{ $server->password }}</code>
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
<button type="button"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 rounded-md bg-primary text-white text-xs font-semibold hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary"
|
||||
@click="copyToClipboard()">
|
||||
<button type="button" class="px-3 py-1.5 rounded bg-blue-600 text-white text-xs font-medium hover:bg-blue-700" @click="copy()">
|
||||
<span x-show="!copied">Copy</span>
|
||||
<span x-show="copied">Copied!</span>
|
||||
</button>
|
||||
@@ -620,61 +540,53 @@
|
||||
</div>
|
||||
|
||||
<!-- Password Edit Modal -->
|
||||
<!-- Modal Backdrop -->
|
||||
<div x-cloak x-show="showPasswordEditModal"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
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-200"
|
||||
x-transition:leave="transition ease-in duration-150"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
@click="showPasswordEditModal = false; $wire.cancelEditingPassword()"
|
||||
@keydown.escape.window="showPasswordEditModal = false; $wire.cancelEditingPassword()"
|
||||
class="fixed inset-0 z-50 bg-black/50 backdrop-blur-sm"
|
||||
class="fixed inset-0 z-50 bg-gray-900 bg-opacity-50"
|
||||
style="display: none;">
|
||||
</div>
|
||||
<!-- Modal -->
|
||||
<div x-cloak x-show="showPasswordEditModal"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0 scale-95"
|
||||
x-transition:enter-end="opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave="transition ease-in duration-150"
|
||||
x-transition:leave-start="opacity-100 scale-100"
|
||||
x-transition:leave-end="opacity-0 scale-95"
|
||||
@click.away="showPasswordEditModal = false; $wire.cancelEditingPassword()"
|
||||
class="fixed inset-0 z-50 flex items-center justify-center p-4"
|
||||
style="display: none;">
|
||||
<div class="relative bg-background-secondary border border-neutral rounded-lg shadow-xl w-full max-w-xl mx-4 p-5 space-y-4">
|
||||
<div class="relative bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-xl w-full max-w-md p-4 space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<h4 class="text-base font-semibold text-base/90">Edit Root Password</h4>
|
||||
<button type="button"
|
||||
class="bg-background border border-neutral p-1.5 rounded-md hover:bg-background/80"
|
||||
@click="showPasswordEditModal = false; $wire.cancelEditingPassword()"
|
||||
aria-label="Close password edit modal">
|
||||
<h4 class="text-sm font-semibold text-gray-800 dark:text-gray-100">Edit Root Password</h4>
|
||||
<button type="button" class="text-gray-400 hover:text-gray-600 p-1"
|
||||
@click="showPasswordEditModal = false; $wire.cancelEditingPassword()">
|
||||
<x-ri-close-line class="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="space-y-3">
|
||||
<div class="space-y-2">
|
||||
<div>
|
||||
<label class="text-xs font-semibold text-base/70">New Password</label>
|
||||
<input type="password"
|
||||
wire:model.defer="password"
|
||||
class="form-input w-full mt-1"
|
||||
placeholder="Enter new password" />
|
||||
<label class="text-xs font-medium text-gray-600 dark:text-gray-400">New Password</label>
|
||||
<input type="password" wire:model.defer="password" class="form-input w-full mt-1 text-sm" placeholder="Enter new password" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs font-semibold text-base/70">Confirm Password</label>
|
||||
<label class="text-xs font-medium text-gray-600 dark:text-gray-400">Confirm Password</label>
|
||||
<input type="password"
|
||||
wire:model.defer="password_confirmation"
|
||||
class="form-input w-full mt-1"
|
||||
class="form-input w-full mt-1 text-sm"
|
||||
placeholder="Confirm password" />
|
||||
</div>
|
||||
@if($passwordError)
|
||||
<div class="text-sm text-error">{{ $passwordError }}</div>
|
||||
<div class="text-xs text-red-600">{{ $passwordError }}</div>
|
||||
@endif
|
||||
<p class="text-xs text-base/60">
|
||||
<strong>Save:</strong> Updates the password in the database.<br>
|
||||
<strong>Save & Apply:</strong> Saves to database and applies the password to the VPS via cloud-init. <strong>The server must be rebooted for the password change to take effect.</strong>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||
<strong>Save:</strong> Database only. <strong>Save & Apply:</strong> + cloud-init (reboot required).
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex justify-end gap-2">
|
||||
@@ -694,16 +606,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col bg-error/10 border border-error/30 p-4 rounded-b-lg">
|
||||
<label class="text-lg font-semibold flex flex-row justify-between items-center gap-8" for="os">
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
Reinstall Server
|
||||
<p class="text-sm font-semibold text-base/60">The data on the server will be permanently
|
||||
deleted. This action is irreversible and cannot be undone.</p>
|
||||
</div>
|
||||
|
||||
<livewire:proxmox.reinstall :server="$server" />
|
||||
<div class="flex items-center justify-between bg-red-50 dark:bg-red-950 border-t border-x border-red-200 dark:border-red-800 px-3 py-2 rounded-b-lg">
|
||||
<div>
|
||||
<span class="text-sm font-semibold text-red-700 dark:text-red-300">Reinstall Server</span>
|
||||
<p class="text-xs text-red-600 dark:text-red-400">Data permanently deleted. Irreversible.</p>
|
||||
</div>
|
||||
<livewire:proxmox.reinstall :server="$server" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user