Enhance Proxmox views with improved loading states and UI updates
- Updated serverplaceholder.blade.php to enhance loading skeletons for server details. - Added navigation breadcrumbs to statistics, subdomain, and system views for better user experience. - Improved loading indicators for CPU, network, memory, and disk charts in statistics.blade.php. - Refined storage.blade.php layout with section dividers and improved drive display, including bus type indicators and quota usage. - Enhanced VNC and Xterm popups with a new header design, loading animations, and reconnect functionality. - Added error handling for VNC and Xterm connections to inform users when unable to connect.
This commit is contained in:
@@ -85,6 +85,7 @@
|
||||
activeSection: null,
|
||||
pendingSection: null,
|
||||
transitionDelay: 220,
|
||||
osSearch: '',
|
||||
toggleSection(key) {
|
||||
if (this.activeSection === key) {
|
||||
this.activeSection = null;
|
||||
@@ -105,6 +106,15 @@
|
||||
}
|
||||
|
||||
this.activeSection = key;
|
||||
},
|
||||
matchesSearch(name) {
|
||||
if (!this.osSearch.trim()) return true;
|
||||
return name.toLowerCase().includes(this.osSearch.trim().toLowerCase());
|
||||
},
|
||||
categoryHasMatch(categoryEl) {
|
||||
if (!this.osSearch.trim()) return true;
|
||||
const labels = categoryEl.querySelectorAll('[data-os-name]');
|
||||
return Array.from(labels).some(el => this.matchesSearch(el.dataset.osName));
|
||||
}
|
||||
}">
|
||||
@if($isProtected)
|
||||
@@ -122,7 +132,7 @@
|
||||
|
||||
<template x-if="open">
|
||||
<div class="fixed inset-0 z-[9999] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4 overflow-y-auto">
|
||||
<div class="bg-background-secondary rounded-2xl p-6 w-full max-w-4xl shadow-2xl border border-neutral/30 my-8">
|
||||
<div class="relative bg-background-secondary rounded-2xl p-6 w-full max-w-4xl shadow-2xl border border-neutral/30 my-8">
|
||||
<div class="flex flex-col gap-2 mb-6">
|
||||
<h2 class="text-2xl font-semibold text-base">Reinstall Server</h2>
|
||||
@if($isProtected)
|
||||
@@ -136,12 +146,32 @@
|
||||
<p class="text-sm text-base/70">Choose a new operating system. The selected template will be installed from scratch.</p>
|
||||
</div>
|
||||
|
||||
<!-- OS Search Filter -->
|
||||
<div class="relative mb-4">
|
||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<x-ri-search-line class="size-4 text-base/40" />
|
||||
</div>
|
||||
<input type="text"
|
||||
x-model="osSearch"
|
||||
placeholder="Search operating systems..."
|
||||
class="w-full pl-10 pr-4 py-2.5 text-sm rounded-lg border border-neutral bg-background focus:ring-2 focus:ring-primary/25 focus:border-primary transition-colors"
|
||||
@if($isProtected) disabled @endif />
|
||||
<div x-show="osSearch.length > 0" x-transition class="absolute inset-y-0 right-0 pr-3 flex items-center">
|
||||
<button @click="osSearch = ''" type="button" class="text-base/40 hover:text-base/60 transition-colors">
|
||||
<x-ri-close-line class="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-3 max-h-[460px] overflow-y-auto pr-1" @if($isProtected) style="pointer-events: none; opacity: 0.6;" @endif>
|
||||
@foreach($groupedOs as $categoryLabel => $templates)
|
||||
@php
|
||||
$categoryKey = \Illuminate\Support\Str::slug($categoryLabel);
|
||||
@endphp
|
||||
<div class="border border-neutral/40 rounded-xl overflow-hidden" wire:key="os-category-{{ $categoryKey }}">
|
||||
<div class="border border-neutral/40 rounded-xl overflow-hidden" wire:key="os-category-{{ $categoryKey }}"
|
||||
x-ref="category_{{ $categoryKey }}"
|
||||
x-show="categoryHasMatch($refs.category_{{ $categoryKey }})"
|
||||
x-init="$watch('osSearch', () => { if (osSearch.trim() && categoryHasMatch($refs.category_{{ $categoryKey }})) { activeSection = '{{ $categoryKey }}'; } })">
|
||||
<button type="button" class="w-full flex items-center justify-between px-4 py-3 bg-background-secondary/60 hover:bg-background-secondary transition"
|
||||
@click="toggleSection('{{ $categoryKey }}')">
|
||||
<div class="flex items-center gap-3">
|
||||
@@ -184,6 +214,9 @@
|
||||
$isSelected = (string) $template->id === (string) ($os ?? '');
|
||||
@endphp
|
||||
<label wire:key="os-card-{{ $template->id }}"
|
||||
data-os-name="{{ $template->name }}"
|
||||
x-show="matchesSearch('{{ addslashes($template->name) }}')"
|
||||
x-transition
|
||||
class="relative flex items-center gap-4 rounded-xl border p-4 cursor-pointer transition-all duration-150
|
||||
@if($isSelected) border-primary bg-primary/5 ring-2 ring-primary/40 shadow-lg @else border-neutral/60 hover:border-primary/60 @endif">
|
||||
<input type="radio" class="sr-only" wire:model.live="os" value="{{ $template->id }}">
|
||||
@@ -257,6 +290,17 @@
|
||||
</x-button.danger>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Reinstall Progress Overlay -->
|
||||
<div wire:loading wire:target="reinstall" class="absolute inset-0 bg-background-secondary/90 backdrop-blur-sm rounded-2xl z-10 flex flex-col items-center justify-center gap-4">
|
||||
<div class="flex items-center justify-center w-16 h-16 rounded-2xl bg-primary/10">
|
||||
<x-ri-loader-4-line class="size-8 text-primary animate-spin" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<h3 class="text-base font-semibold text-base/90">Installing Operating System</h3>
|
||||
<p class="text-sm text-base/60 mt-1">This may take a few minutes. Please do not close this window.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user