diff --git a/extensions/Servers/Proxmox/Livewire/Overview.php b/extensions/Servers/Proxmox/Livewire/Overview.php index 8460a938a..ff4514dfa 100644 --- a/extensions/Servers/Proxmox/Livewire/Overview.php +++ b/extensions/Servers/Proxmox/Livewire/Overview.php @@ -60,6 +60,64 @@ class Overview extends Component } catch (\Exception $e) { $this->notes = ''; } + + // Preload Statistics telemetry data in background to warm the cache + // This ensures when user navigates to Statistics page, data is already available + $this->preloadStatisticsData(); + } + + /** + * Preload statistics data to warm the cache for faster Statistics page loading. + * Runs as a non-blocking background operation using dispatch_async if available, + * otherwise falls back to synchronous cache warming. + */ + protected function preloadStatisticsData(): void + { + // Only preload if cache is empty (don't waste resources if already cached) + $graphTypes = ['cpu', 'memory', 'network', 'disk']; + $timeRange = 'hour'; + $aggregation = 'average'; + + foreach ($graphTypes as $graphType) { + $cacheKey = 'proxmox-stats-' . $this->server->id . '-' . $graphType . '-' . $timeRange . '-' . $aggregation; + + // Skip if already cached + if (Cache::has($cacheKey)) { + continue; + } + + // Warm the cache in background + try { + Cache::remember($cacheKey, 30, function () use ($timeRange, $aggregation) { + $proxmox = new Proxmox; + $stats = $proxmox->request('/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/rrddata', data: [ + 'timeframe' => $timeRange, + 'cf' => $aggregation === 'maximum' ? 'MAX' : 'AVERAGE', + ]); + + $rawData = $stats->json()['data'] ?? []; + + // Limit data points to prevent memory issues (same logic as Statistics) + $maxPoints = 40; + if (count($rawData) > $maxPoints) { + $step = ceil(count($rawData) / $maxPoints); + $sampledData = []; + for ($i = 0; $i < count($rawData); $i += $step) { + $sampledData[] = $rawData[$i]; + } + if (end($rawData) !== end($sampledData)) { + $sampledData[] = end($rawData); + } + return $sampledData; + } + + return $rawData; + }); + } catch (\Throwable $e) { + // Silently fail - this is just a preload optimization + \Log::debug('Overview: Stats preload failed for ' . $graphType, ['error' => $e->getMessage()]); + } + } } public function checkStatus() diff --git a/extensions/Servers/Proxmox/views/backups.blade.php b/extensions/Servers/Proxmox/views/backups.blade.php index 8f3712062..88f0e6e96 100644 --- a/extensions/Servers/Proxmox/views/backups.blade.php +++ b/extensions/Servers/Proxmox/views/backups.blade.php @@ -33,7 +33,7 @@ @keydown.escape.window="open = false" class="fixed inset-0 z-50 flex items-center justify-center p-4" style="display: none;"> -
+
@@ -73,7 +73,7 @@
-
+
diff --git a/extensions/Servers/Proxmox/views/boot-order.blade.php b/extensions/Servers/Proxmox/views/boot-order.blade.php index 8118c8448..1b1597dc5 100644 --- a/extensions/Servers/Proxmox/views/boot-order.blade.php +++ b/extensions/Servers/Proxmox/views/boot-order.blade.php @@ -49,21 +49,21 @@

Cloud-init Configuration Notice

-
-

+

Hostname, password, and networking settings are configured automatically via cloud-init. This applies to standard operating system installations that support cloud-init. However, if you are:

-
    +
    • Installing from an ISO image
    • Configuring the operating system manually during installation
    • Using Windows (which does not support cloud-init)
    -

    +

    You will need to manually configure networking, security settings, and hostname within the operating system, as cloud-init will not be available in these scenarios.

@@ -75,7 +75,7 @@

Boot Order

- @@ -103,7 +103,7 @@ @keydown.escape.window="open = false" class="fixed inset-0 z-50 flex items-center justify-center p-4" style="display: none;"> -
+
@@ -118,7 +118,7 @@

Determines the sequence in which the virtual machine attempts to boot from available devices. The system will try each device in the specified order until it finds a bootable medium.

-
+

Note: If no explicit boot order is configured, QEMU uses the default platform boot sequence. Changes take effect on the next power event (start, reboot, or reset). The boot order is populated directly from the QEMU configuration via the QEMU API.

@@ -127,7 +127,7 @@
-

+

Control the sequence used when attempting to boot this virtual machine. The list below is populated directly from the QEMU configuration via the API.

@@ -142,13 +142,13 @@
@if(count($cdDrives) < 2) -
+

Create CD/DVD-ROM Drive

- @@ -176,7 +176,7 @@ @keydown.escape.window="open = false" class="fixed inset-0 z-50 flex items-center justify-center p-4" style="display: none;"> -
+
@@ -191,7 +191,7 @@

Adds a virtual optical drive to your VM using the next available IDE or SATA slot. The system automatically selects an unused slot (IDE0-IDE4 or SATA0-SATA5).

-
+

Limitations: Cloud-init media devices are automatically ignored. Maximum of 2 CD/DVD-ROM drives per virtual machine.

@@ -203,11 +203,11 @@
-

+

Use the next available IDE or SATA slot to add a virtual optical drive. Cloud-init media is ignored. Maximum of 2 drives allowed.

- + {{ count($cdDrives) === 0 ? 'No drive configured' : count($cdDrives) . ' of 2 drives' }}
@@ -224,13 +224,13 @@ @endif @foreach($cdDrives as $index => $drive) -
+

Mount ISO Image - {{ strtoupper($drive) }}

- @@ -258,7 +258,7 @@ @keydown.escape.window="open = false" class="fixed inset-0 z-50 flex items-center justify-center p-4" style="display: none;"> -
+
@@ -273,7 +273,7 @@

Attach or detach ISO files from cephfs storage to the virtual CD/DVD-ROM drive. Select an ISO from the dropdown to mount it, or choose "None" to leave the drive empty.

-
+

Apply: Commits your selection and immediately mounts the ISO to the drive.

@@ -288,7 +288,7 @@
-

+

Attach or detach an ISO from cephfs storage for the drive on {{ strtoupper($drive) }}.

@@ -314,7 +314,7 @@
- +
@@ -343,7 +343,7 @@

@if(isset($currentIsos[$drive]) && $currentIsos[$drive] !== 'none') -
+
Currently mounted: {{ $this->formatIsoLabel($currentIsos[$drive]) }}
@endif @@ -351,13 +351,13 @@ @endforeach @if(count($cdDrives) > 0) -
+

Request ISO

- @@ -385,7 +385,7 @@ @keydown.escape.window="open = false" class="fixed inset-0 z-50 flex items-center justify-center p-4" style="display: none;"> -
+
@@ -400,7 +400,7 @@

Opens a support ticket form where you can request that a specific ISO image be added to the cephfs storage.

-
+

When submitting a request, include:

@@ -417,7 +417,7 @@
-

+

Submit a support ticket to request an ISO image be added to cephfs storage.

@@ -434,15 +434,15 @@
-

+

When requesting an ISO, please ensure your ticket includes:

-
    +
    • An active public URL of the image in .iso format
    • A project page of the distribution
    • Name and version of the distribution
    -

    +

    Please submit your request under the "ISO Request" department.

@@ -453,13 +453,13 @@ @endif
-
+

Boot priority

- @@ -487,7 +487,7 @@ @keydown.escape.window="open = false" class="fixed inset-0 z-50 flex items-center justify-center p-4" style="display: none;"> -
+
@@ -502,7 +502,7 @@

Shows the current boot sequence for your virtual machine. Devices are listed in order from highest to lowest priority. The VM will attempt to boot from each device in sequence until it finds a bootable medium.

-
+

Move up/down: Reorder devices to adjust boot priority.

@@ -517,7 +517,7 @@
-

Move devices up or down to adjust the order.

+

Move devices up or down to adjust the order.

{{ $this->hasChanges ? 'Unsaved changes' : 'Synced' }} @@ -534,7 +534,7 @@ {{ $index + 1 }}. {{ $availableDevices[$device]['label'] ?? strtoupper($device) }}

@if ($availableDevices[$device]['details'] ?? false) -

+

{{ $availableDevices[$device]['details'] }}

@endif @@ -559,7 +559,7 @@
@empty -
+
Select devices from the list on the right to build a boot order.
@endforelse @@ -570,13 +570,13 @@ $remainingDevices = array_values(array_diff(array_keys($availableDevices), $order)); @endphp -
+

Available devices

- @@ -604,7 +604,7 @@ @keydown.escape.window="open = false" class="fixed inset-0 z-50 flex items-center justify-center p-4" style="display: none;"> -
+
@@ -619,7 +619,7 @@

Lists all bootable devices detected in your VM configuration that are not currently part of the boot sequence.

-
+

Device Types: Disk drives (VirtIO, SCSI, SATA, IDE, NVMe), network adapters, and CD/DVD-ROM drives. Each device shows its type, identifier, and configuration details.

@@ -631,9 +631,9 @@
-

These devices can be part of the boot sequence.

+

These devices can be part of the boot sequence.

- {{ count($remainingDevices) }} available + {{ count($remainingDevices) }} available
@@ -644,7 +644,7 @@

{{ $availableDevices[$device]['label'] ?? strtoupper($device) }}

@if ($availableDevices[$device]['details'] ?? false) -

{{ $availableDevices[$device]['details'] }}

+

{{ $availableDevices[$device]['details'] }}

@endif
@empty -
+
All detected devices are already part of the boot priority list.
@endforelse @@ -676,7 +676,7 @@ Reset to current
- @@ -704,7 +704,7 @@ @keydown.escape.window="open = false" class="fixed inset-0 z-50 flex items-center justify-center p-4" style="display: none;"> -
+
@@ -719,7 +719,7 @@

Discards any unsaved changes to the boot order and restores it to match the last saved configuration.

-
+

This button is only enabled when there are unsaved changes. Use this if you want to undo modifications without refreshing the entire configuration from the server.

@@ -735,7 +735,7 @@ Save boot order
- @@ -763,7 +763,7 @@ @keydown.escape.window="open = false" class="fixed inset-0 z-50 flex items-center justify-center p-4" style="display: none;"> -
+
@@ -778,7 +778,7 @@

Commits your boot order changes to the QEMU server configuration. The new boot sequence will be applied to the virtual machine and will take effect on the next power event (start, reboot, or reset).

-
+

If the boot order is empty, the system will reset to the default platform boot sequence.

diff --git a/extensions/Servers/Proxmox/views/cloud-init.blade.php b/extensions/Servers/Proxmox/views/cloud-init.blade.php index f20f15f02..baf2b6f05 100644 --- a/extensions/Servers/Proxmox/views/cloud-init.blade.php +++ b/extensions/Servers/Proxmox/views/cloud-init.blade.php @@ -31,12 +31,12 @@

Cloud-init Configuration Notice

-
-

+

Cloud-init controls the metadata injected into your VM on first boot and whenever you regenerate the cloud-init drive. Use Apply to save and regenerate the ISO, Refresh to pull fresh values, and Reset to discard local edits. Manual installs (ISO workflows, Windows, or images without cloud-init) still require in-guest configuration. @@ -50,12 +50,12 @@

Cloud-init Settings

-
-
-

+

These values map directly to the QEMU configuration (`ciuser`, `nameserver`, `ipconfigX`, etc.). Changes take effect on the next cloud-init run or boot.

-

Access & Credentials

-
-
-

Defaults used by cloud-init to create accounts and authorize SSH.

+

Defaults used by cloud-init to create accounts and authorize SSH.

@if($this->accessCredentialsSynced) Synced @@ -153,18 +153,18 @@ {{ $ciUser !== '' ? $ciUser : 'Template default (uses image-defined user)' }}
-

Use distro-friendly names. Leave blank to keep the template default.

+

Use distro-friendly names. Leave blank to keep the template default.

-

Edit Cloud-init User

@@ -176,12 +176,12 @@
- + -

Leave blank to retain the template default user.

+

Leave blank to retain the template default user.

@@ -208,26 +208,26 @@ @if(isset($server->password) && $server->password) @endif
-

Matches the Overview tab control. Use Save for database only, Save & Apply to push via cloud-init.

+

Matches the Overview tab control. Use Save for database only, Save & Apply to push via cloud-init.

@if(isset($server->password) && $server->password)
-
-

Edit Root Password

@@ -277,14 +277,14 @@
- +
- + {{ $passwordError }}
@endif -

+

Save writes the password to the database. Save & Apply also pushes it to the hypervisor; reboot for cloud-init to configure the guest OS.

@@ -316,7 +316,7 @@
@forelse($sshKeys as $keyIndex => $key) -
{{ $key }}
- + @@ -415,24 +415,24 @@
-

+

Runs apt/yum update && upgrade when cloud-init executes. Enable only if your template supports unattended upgrades.

-

Network Configuration

-
-
-

Each card corresponds to an ipconfigX. Configure IPv4 and IPv6 independently.

+

Each card corresponds to an ipconfigX. Configure IPv4 and IPv6 independently.

- {{ count($networks) }} interfaces + {{ count($networks) }} interfaces
@@ -474,12 +474,12 @@
{{ $network['key'] }} -

+

Network Device: NET{{ str_replace('ipconfig', '', $network['key']) }}

@@ -487,25 +487,25 @@
- +
{{ !empty($network['ip']) ? $network['ip'] : '—' }}
- +
{{ !empty($network['gw']) ? $network['gw'] : '—' }}
- +
{{ !empty($network['ip6']) ? $network['ip6'] : '—' }}
- +
{{ !empty($network['gw6']) ? $network['gw6'] : '—' }}
@@ -513,12 +513,12 @@
@if(($network['dhcp'] ?? false)) -
+
DHCP: Enabled
@endif -

+

Leave fields blank to remove static addressing. If both IPv4 fields are empty, cloud-init omits the IPv4 stanza.

@@ -527,7 +527,7 @@
-

Edit Network Configuration

@@ -542,27 +542,27 @@
- +
- +
- +
- +
-

+

Leave fields blank to remove static addressing. If both IPv4 fields are empty, cloud-init omits the IPv4 stanza.

@@ -580,18 +580,18 @@
-
+

DNS Settings

-
-
-

Configures searchdomain and nameserver values.

+

Configures searchdomain and nameserver values.

@if($this->dnsSettingsSynced) Synced @@ -640,18 +640,18 @@ {{ $dnsDomain !== '' ? $dnsDomain : 'Not configured (system default will be used)' }}
-

Appended to short hostnames for resolution.

+

Appended to short hostnames for resolution.

-

Edit DNS Domain

@@ -663,12 +663,12 @@
- + -

Leave blank to use system default. Appended to short hostnames for resolution.

+

Leave blank to use system default. Appended to short hostnames for resolution.

@@ -686,7 +686,7 @@
@forelse($dnsServers as $dnsIndex => $resolver) -
+
{{ $resolver }}
-

Entries are applied in order. Add one IPv4/IPv6 resolver per line.

+

Entries are applied in order. Add one IPv4/IPv6 resolver per line.

-

Add DNS Nameserver

@@ -719,12 +719,12 @@
- +
- +
-
+

OS Type

-
-
-

Controls the ostype option used when generating cloud-init media.

+

Controls the ostype option used when generating cloud-init media.

@if($this->osTypeSynced) Synced @@ -863,10 +863,10 @@ @endforeach
-

+

Determines whether the guest receives nocloud or config-drive metadata. Choose the entry that matches your template.

-
+
Tip: Pick a Windows option only for cloud-ready Windows images (cloudbase-init). Using a Windows entry on Linux templates prevents the nocloud ISO from mounting.
diff --git a/extensions/Servers/Proxmox/views/components/ui/action-button.blade.php b/extensions/Servers/Proxmox/views/components/ui/action-button.blade.php index 19442655e..d08f5398f 100644 --- a/extensions/Servers/Proxmox/views/components/ui/action-button.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/action-button.blade.php @@ -1,5 +1,5 @@ {{-- - Action Toolbar Button Component - TailAdmin style + Action Toolbar Button Component - AdminLTE style Individual button for VM control actions Usage: @@ -15,7 +15,7 @@ 'action' => null, 'icon' => null, 'label', - 'variant' => 'default', // default, danger, warning, success + 'variant' => 'default', // default, danger, warning, success, primary 'disabled' => false, 'loading' => false, 'confirm' => null, @@ -23,50 +23,152 @@ ]) @php - $variants = [ - 'default' => 'border border-gray-300 bg-white text-gray-700 shadow-theme-xs hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700', - 'primary' => 'border border-brand-200 bg-brand-50 text-brand-600 hover:bg-brand-100 dark:border-brand-800 dark:bg-brand-500/10 dark:text-brand-400 dark:hover:bg-brand-500/20', - 'success' => 'border border-success-200 bg-success-50 text-success-600 hover:bg-success-100 dark:border-success-800 dark:bg-success-500/10 dark:text-success-400 dark:hover:bg-success-500/20', - 'warning' => 'border border-warning-200 bg-warning-50 text-warning-600 hover:bg-warning-100 dark:border-warning-800 dark:bg-warning-500/10 dark:text-warning-400 dark:hover:bg-warning-500/20', - 'danger' => 'border border-error-200 bg-error-50 text-error-600 hover:bg-error-100 dark:border-error-800 dark:bg-error-500/10 dark:text-error-400 dark:hover:bg-error-500/20', - ]; - - $sizes = [ - 'sm' => 'h-9 px-3 text-theme-xs', - 'md' => 'h-10 px-4 text-theme-sm', - 'lg' => 'h-11 px-5 text-theme-sm', + $sizeStyles = [ + 'sm' => 'height: 2.25rem; padding: 0 0.75rem; font-size: 0.8125rem;', + 'md' => 'height: 2.5rem; padding: 0 1rem; font-size: 0.875rem;', + 'lg' => 'height: 2.75rem; padding: 0 1.25rem; font-size: 0.875rem;', ]; $iconSizes = [ - 'sm' => 'size-3.5', - 'md' => 'size-4', - 'lg' => 'size-4.5', + 'sm' => 'width: 0.875rem; height: 0.875rem;', + 'md' => 'width: 1rem; height: 1rem;', + 'lg' => 'width: 1.125rem; height: 1.125rem;', ]; @endphp + + diff --git a/extensions/Servers/Proxmox/views/components/ui/action-toolbar.blade.php b/extensions/Servers/Proxmox/views/components/ui/action-toolbar.blade.php index db12d0d99..7c1a4bb81 100644 --- a/extensions/Servers/Proxmox/views/components/ui/action-toolbar.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/action-toolbar.blade.php @@ -1,5 +1,5 @@ {{-- - Action Toolbar Component - TailAdmin style + Action Toolbar Component - AdminLTE style For VM control buttons (Start, Stop, Restart, etc.) Usage: @@ -16,10 +16,20 @@ 'centered' => false, ]) + +
class([ - 'flex flex-wrap gap-3', - 'justify-center' => $centered, - 'justify-start' => !$centered, + 'action-toolbar-lte', + 'action-toolbar-lte-centered' => $centered, ]) }}> {{ $slot }}
diff --git a/extensions/Servers/Proxmox/views/components/ui/alert.blade.php b/extensions/Servers/Proxmox/views/components/ui/alert.blade.php index c65d151b1..1ac43f868 100644 --- a/extensions/Servers/Proxmox/views/components/ui/alert.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/alert.blade.php @@ -1,10 +1,12 @@ {{-- - Alert Component - TailAdmin Theme + Alert Component - AdminLTE Theme + Based on AdminLTE v4 Alert & Callout styling patterns Usage: Default alert Operation completed Warning message + Callout style --}} @props([ @@ -14,45 +16,53 @@ 'dismissible' => false, 'collapsible' => false, 'collapsed' => false, + 'callout' => false, // Use callout style instead of alert ]) @php $variantConfig = [ 'default' => [ - 'class' => 'border-gray-200 bg-white dark:border-gray-800 dark:bg-white/[0.03] text-gray-800 dark:text-white/90', - 'iconClass' => 'fill-gray-500 dark:fill-gray-400', + 'alertClass' => 'lte-alert', + 'calloutClass' => 'lte-callout', 'icon' => $icon ?? 'ri-information-line', ], 'info' => [ - 'class' => 'border-blue-light-200 bg-blue-light-50 dark:border-blue-light-500/20 dark:bg-blue-light-500/10 text-blue-light-600 dark:text-blue-light-400', - 'iconClass' => 'fill-blue-light-500', + 'alertClass' => 'lte-alert lte-alert-info', + 'calloutClass' => 'lte-callout lte-callout-info', 'icon' => $icon ?? 'ri-information-line', ], 'success' => [ - 'class' => 'border-success-200 bg-success-50 dark:border-success-500/20 dark:bg-success-500/10 text-success-600 dark:text-success-400', - 'iconClass' => 'fill-success-500', + 'alertClass' => 'lte-alert lte-alert-success', + 'calloutClass' => 'lte-callout lte-callout-success', 'icon' => $icon ?? 'ri-checkbox-circle-line', ], 'warning' => [ - 'class' => 'border-warning-200 bg-warning-50 dark:border-warning-500/20 dark:bg-warning-500/10 text-warning-600 dark:text-orange-400', - 'iconClass' => 'fill-warning-500', + 'alertClass' => 'lte-alert lte-alert-warning', + 'calloutClass' => 'lte-callout lte-callout-warning', 'icon' => $icon ?? 'ri-error-warning-line', ], 'danger' => [ - 'class' => 'border-error-200 bg-error-50 dark:border-error-500/20 dark:bg-error-500/10 text-error-600 dark:text-error-400', - 'iconClass' => 'fill-error-500', + 'alertClass' => 'lte-alert lte-alert-danger', + 'calloutClass' => 'lte-callout lte-callout-danger', 'icon' => $icon ?? 'ri-error-warning-fill', ], + 'primary' => [ + 'alertClass' => 'lte-alert lte-alert-primary', + 'calloutClass' => 'lte-callout lte-callout-primary', + 'icon' => $icon ?? 'ri-information-line', + ], ]; $config = $variantConfig[$variant] ?? $variantConfig['default']; + $componentClass = $callout ? $config['calloutClass'] : $config['alertClass']; @endphp
class([ - 'relative w-full rounded-xl border p-4 flex gap-3 items-start', - $config['class'], + $componentClass, + 'lte-fade-in', + $dismissible ? 'lte-alert-dismissible' : '', ]) }} @if($dismissible || $collapsible) x-data="{ @@ -68,30 +78,32 @@ x-transition:leave-end="opacity-0" @endif > - -
- @if($title) -
{{ $title }}
- @endif -
+ +
+ @if($title) +
{{ $title }}
@endif - > - {{ $slot }} +
+ {{ $slot }} +
@if($dismissible || $collapsible) -
+
@if($collapsible) + class="lte-btn-close" + aria-label="Close" + > @endif
@endif diff --git a/extensions/Servers/Proxmox/views/components/ui/allocation-card.blade.php b/extensions/Servers/Proxmox/views/components/ui/allocation-card.blade.php index 55e638d01..6e8ad1c9e 100644 --- a/extensions/Servers/Proxmox/views/components/ui/allocation-card.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/allocation-card.blade.php @@ -1,5 +1,5 @@ {{-- - Resource Allocation Card Component - TailAdmin style + Resource Allocation Card Component - AdminLTE style For displaying CPU, Memory, and other resource allocation vs entitlement Usage: @@ -20,43 +20,185 @@ 'usageSummary', 'entitlementLabel', 'description' => null, - 'gradient' => 'linear-gradient(90deg, #465fff 0%, #8b5cf6 100%)', + 'gradient' => 'linear-gradient(90deg, #0d6efd 0%, #6f42c1 100%)', 'badge' => null, 'icon' => null, - 'iconColor' => 'text-brand-500', + 'iconColor' => 'primary', ]) -
class(['rounded-2xl border border-gray-200 bg-white p-5 transition-colors duration-150 hover:bg-gray-50 dark:border-gray-800 dark:bg-white/[0.03] dark:hover:bg-gray-800/50']) }}> -
-
-
+@php + $iconBgColors = [ + 'primary' => 'background-color: rgba(13, 110, 253, 0.1);', + 'success' => 'background-color: rgba(25, 135, 84, 0.1);', + 'warning' => 'background-color: rgba(255, 193, 7, 0.1);', + 'danger' => 'background-color: rgba(220, 53, 69, 0.1);', + 'info' => 'background-color: rgba(13, 202, 240, 0.1);', + ]; + $iconTextColors = [ + 'primary' => 'color: var(--lte-primary, #0d6efd);', + 'success' => 'color: var(--lte-success, #198754);', + 'warning' => 'color: var(--lte-warning, #ffc107);', + 'danger' => 'color: var(--lte-danger, #dc3545);', + 'info' => 'color: var(--lte-info, #0dcaf0);', + ]; +@endphp + + + +
class(['allocation-card-lte']) }}> +
+
+
@if($icon) -
- +
+
@endif -
-

{{ $label }}

-

{{ $usageSummary }}

-

{{ $entitlementLabel }}

+
+

{{ $label }}

+

{{ $usageSummary }}

+

{{ $entitlementLabel }}

@if($badge) - + {{ $badge['label'] ?? '' }} @endif
@if(!is_null($percent)) -
-
- Usage - {{ $percent }}% +
+
+ Usage + {{ $percent }}%
-
+
@@ -64,7 +206,7 @@ @endif @if($description) -

{{ $description }}

+

{{ $description }}

@endif
diff --git a/extensions/Servers/Proxmox/views/components/ui/badge.blade.php b/extensions/Servers/Proxmox/views/components/ui/badge.blade.php index 373a5f258..f6afb21a5 100644 --- a/extensions/Servers/Proxmox/views/components/ui/badge.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/badge.blade.php @@ -1,5 +1,6 @@ {{-- - Badge Component - TailAdmin Theme + Badge Component - AdminLTE Theme + Based on AdminLTE v4 Badge styling patterns Usage: Default @@ -14,28 +15,20 @@ 'icon' => null, 'dot' => false, 'pulse' => false, - 'outline' => false, ]) @php - $baseClasses = 'inline-flex items-center rounded-full font-medium transition-colors'; - $variantClasses = [ - 'default' => 'bg-brand-50 text-brand-500 dark:bg-brand-500/15 dark:text-brand-400', - 'secondary' => 'bg-gray-100 text-gray-700 dark:bg-white/5 dark:text-white/80', - 'success' => $outline ? 'ring-1 ring-success-500/40 text-success-600 bg-transparent dark:text-success-400' : 'bg-success-50 text-success-600 dark:bg-success-500/15 dark:text-success-400', - 'warning' => $outline ? 'ring-1 ring-warning-500/40 text-warning-600 bg-transparent dark:text-orange-400' : 'bg-warning-50 text-warning-600 dark:bg-warning-500/15 dark:text-orange-400', - 'danger' => $outline ? 'ring-1 ring-error-500/40 text-error-600 bg-transparent dark:text-error-400' : 'bg-error-50 text-error-600 dark:bg-error-500/15 dark:text-error-400', - 'info' => $outline ? 'ring-1 ring-blue-light-500/40 text-blue-light-600 bg-transparent dark:text-blue-light-400' : 'bg-blue-light-50 text-blue-light-500 dark:bg-blue-light-500/15 dark:text-blue-light-500', - 'outline' => 'text-gray-700 ring-1 ring-gray-300 dark:text-gray-400 dark:ring-gray-700', - 'muted' => 'bg-gray-500 text-white dark:bg-white/5 dark:text-white/80', - ]; - - $sizeClasses = [ - 'xs' => 'px-2 py-0.5 text-[10px]', - 'sm' => 'px-2 py-0.5 text-xs', - 'md' => 'px-2.5 py-0.5 text-sm', - 'lg' => 'px-3 py-1 text-sm', + 'default' => 'lte-badge-primary', + 'primary' => 'lte-badge-primary', + 'secondary' => 'lte-badge-secondary', + 'success' => 'lte-badge-success', + 'warning' => 'lte-badge-warning', + 'danger' => 'lte-badge-danger', + 'info' => 'lte-badge-info', + 'light' => 'lte-badge-light', + 'dark' => 'lte-badge-dark', + 'muted' => 'lte-badge-secondary', ]; $iconSizes = [ @@ -52,17 +45,15 @@ 'lg' => 'size-2', ]; - $classes = collect([ - $baseClasses, - $variantClasses[$variant] ?? $variantClasses['default'], - $sizeClasses[$size] ?? $sizeClasses['md'], - ])->filter()->join(' '); - $iconSize = $iconSizes[$size] ?? $iconSizes['md']; $dotSize = $dotSizes[$size] ?? $dotSizes['md']; @endphp -class([$classes, 'gap-1' => $icon || $dot]) }}> +class([ + 'lte-badge', + $variantClasses[$variant] ?? $variantClasses['default'], + 'gap-1' => $icon || $dot, +]) }} style="{{ $size === 'lg' ? 'font-size: 0.9em; padding: 0.5em 0.8em;' : '' }}"> @if($dot) @if($pulse) diff --git a/extensions/Servers/Proxmox/views/components/ui/button.blade.php b/extensions/Servers/Proxmox/views/components/ui/button.blade.php index 90a73c32a..9ca5b5617 100644 --- a/extensions/Servers/Proxmox/views/components/ui/button.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/button.blade.php @@ -1,5 +1,6 @@ {{-- - Button Component - TailAdmin Theme + Button Component - AdminLTE Theme + Based on AdminLTE v4 Button styling patterns Usage: Click me @@ -19,32 +20,31 @@ 'href' => null, 'type' => 'button', 'full' => false, + 'outline' => false, ]) @php $tag = $href ? 'a' : 'button'; - $baseClasses = 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg font-medium transition-colors focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-brand-500/10 disabled:pointer-events-none disabled:opacity-50'; - + // AdminLTE button classes $variantClasses = [ - 'primary' => 'bg-brand-500 text-white shadow-theme-xs hover:bg-brand-600', - 'secondary' => 'bg-white text-gray-700 shadow-theme-xs ring-1 ring-gray-300 hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-400 dark:ring-gray-700 dark:hover:bg-white/[0.03]', - 'outline' => 'border border-gray-300 bg-white shadow-theme-xs hover:bg-gray-50 hover:text-gray-800 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-white/[0.03] dark:hover:text-gray-200', - 'ghost' => 'hover:bg-gray-100 hover:text-gray-700 dark:hover:bg-white/5 dark:hover:text-gray-300', - 'danger' => 'bg-error-500 text-white shadow-theme-xs hover:bg-error-600', - 'success' => 'bg-success-500 text-white shadow-theme-xs hover:bg-success-600', - 'warning' => 'bg-warning-500 text-white shadow-theme-xs hover:bg-warning-600', - 'info' => 'bg-blue-light-500 text-white shadow-theme-xs hover:bg-blue-light-600', - 'link' => 'text-brand-500 hover:text-brand-600 hover:underline underline-offset-4', + 'primary' => $outline ? 'lte-btn-outline-primary' : 'lte-btn-primary', + 'secondary' => $outline ? 'lte-btn-outline-secondary' : 'lte-btn-secondary', + 'danger' => $outline ? 'lte-btn-outline-danger' : 'lte-btn-danger', + 'success' => $outline ? 'lte-btn-outline-success' : 'lte-btn-success', + 'warning' => 'lte-btn-warning', + 'info' => 'lte-btn-info', + 'ghost' => 'lte-btn-outline-secondary border-0', + 'link' => 'lte-text-primary', ]; $sizeClasses = [ - 'xs' => 'h-8 px-2.5 text-xs', - 'sm' => 'h-9 px-3 text-sm', - 'md' => 'h-10 px-4 text-sm', - 'lg' => 'h-11 px-5 text-sm', - 'xl' => 'h-12 px-6 text-base', - 'icon' => 'h-10 w-10', + 'xs' => 'lte-btn-sm', + 'sm' => 'lte-btn-sm', + 'md' => '', + 'lg' => 'lte-btn-lg', + 'xl' => 'lte-btn-lg', + 'icon' => 'lte-btn-sm', ]; $iconSizes = [ @@ -56,13 +56,6 @@ 'icon' => 'size-5', ]; - $classes = collect([ - $baseClasses, - $variantClasses[$variant] ?? $variantClasses['secondary'], - $sizeClasses[$size] ?? $sizeClasses['md'], - $full ? 'w-full' : '', - ])->filter()->join(' '); - $iconSize = $iconSizes[$size] ?? $iconSizes['md']; @endphp @@ -70,13 +63,15 @@ @if($href) href="{{ $href }}" @endif @if($tag === 'button') type="{{ $type }}" @endif @if($disabled || $loading) disabled @endif - {{ $attributes->class([$classes]) }} + {{ $attributes->class([ + 'lte-btn', + $variantClasses[$variant] ?? $variantClasses['secondary'], + $sizeClasses[$size] ?? '', + $full ? 'w-full' : '', + ]) }} > @if($loading) - - - - + {{ $loadingText ?? $slot }} @else @if($icon) diff --git a/extensions/Servers/Proxmox/views/components/ui/card.blade.php b/extensions/Servers/Proxmox/views/components/ui/card.blade.php index 5dfaa6821..58417214e 100644 --- a/extensions/Servers/Proxmox/views/components/ui/card.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/card.blade.php @@ -1,17 +1,19 @@ {{-- - Card Component - TailAdmin Theme + Card Component - AdminLTE Theme + Based on AdminLTE v4 Card styling patterns Usage: Content Content Content + Content with top accent --}} @props([ 'title' => null, 'subtitle' => null, 'icon' => null, - 'iconColor' => 'text-brand-500', + 'iconColor' => 'lte-text-primary', 'actions' => null, 'footer' => null, 'footerClass' => '', @@ -20,12 +22,25 @@ 'clickable' => false, 'collapsible' => false, 'collapsed' => false, + 'variant' => null, // primary, success, warning, danger, info + 'outline' => false, ]) +@php + $variantClasses = match($variant) { + 'primary' => $outline ? 'lte-card-outline-primary' : 'lte-card-primary', + 'success' => $outline ? 'lte-card-outline-success' : 'lte-card-success', + 'warning' => $outline ? 'lte-card-outline-warning' : 'lte-card-warning', + 'danger' => $outline ? 'lte-card-outline-danger' : 'lte-card-danger', + 'info' => $outline ? 'lte-card-outline-info' : 'lte-card-info', + default => '', + }; +@endphp +
class([ - 'rounded-2xl border border-gray-200 bg-white dark:border-gray-800 dark:bg-white/[0.03]', - 'hover:shadow-theme-md transition-shadow duration-200' => $hover || $clickable, + 'lte-card lte-slide-in-up', + $variantClasses, 'cursor-pointer' => $clickable, ]) }} @if($collapsible) @@ -33,24 +48,22 @@ @endif > @if($title || $actions) -
-
+
+

@if($icon) -
+ -
+ @endif -
- @if($title) -

{{ $title }}

- @endif + + {{ $title }} @if($subtitle) -

{{ $subtitle }}

+ {{ $subtitle }} @endif -
-

+ + @if($actions || $collapsible) -
+
@if($actions) {{ $actions }} @endif @@ -58,10 +71,11 @@ @@ -72,10 +86,7 @@ @endif
$title, - 'p-5 sm:p-6', - ]) + class="lte-card-body" @if($collapsible) x-show="!isCollapsed" x-transition:enter="transition ease-out duration-200" @@ -90,7 +101,7 @@
@if($footer) -
+ @endif diff --git a/extensions/Servers/Proxmox/views/components/ui/confirm-dialog.blade.php b/extensions/Servers/Proxmox/views/components/ui/confirm-dialog.blade.php index 713b53562..1827b2f23 100644 --- a/extensions/Servers/Proxmox/views/components/ui/confirm-dialog.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/confirm-dialog.blade.php @@ -1,5 +1,5 @@ {{-- - Confirm Dialog Component - TailAdmin style + Confirm Dialog Component - AdminLTE style For dangerous actions like delete, stop, etc. Usage: @@ -26,78 +26,192 @@ $variants = [ 'danger' => [ 'icon' => 'ri-error-warning-line', - 'iconBg' => 'bg-error-50 dark:bg-error-500/10', - 'iconColor' => 'text-error-500', - 'buttonClass' => 'bg-error-500 text-white shadow-theme-xs hover:bg-error-600', + 'iconBg' => 'background-color: rgba(220, 53, 69, 0.1);', + 'iconColor' => 'color: var(--lte-danger, #dc3545);', + 'buttonStyle' => 'background-color: var(--lte-danger, #dc3545); color: #fff;', + 'buttonHover' => 'background-color: #bb2d3b;', ], 'warning' => [ 'icon' => 'ri-alert-line', - 'iconBg' => 'bg-warning-50 dark:bg-warning-500/10', - 'iconColor' => 'text-warning-500', - 'buttonClass' => 'bg-warning-500 text-white shadow-theme-xs hover:bg-warning-600', + 'iconBg' => 'background-color: rgba(255, 193, 7, 0.15);', + 'iconColor' => 'color: #997404;', + 'buttonStyle' => 'background-color: var(--lte-warning, #ffc107); color: #000;', + 'buttonHover' => 'background-color: #ffca2c;', ], 'primary' => [ 'icon' => 'ri-question-line', - 'iconBg' => 'bg-brand-50 dark:bg-brand-500/10', - 'iconColor' => 'text-brand-500', - 'buttonClass' => 'bg-brand-500 text-white shadow-theme-xs hover:bg-brand-600', + 'iconBg' => 'background-color: rgba(13, 110, 253, 0.1);', + 'iconColor' => 'color: var(--lte-primary, #0d6efd);', + 'buttonStyle' => 'background-color: var(--lte-primary, #0d6efd); color: #fff;', + 'buttonHover' => 'background-color: #0b5ed7;', ], ]; $config = $variants[$variant] ?? $variants['danger']; @endphp + +
whereDoesntStartWith('wire:click') }} > -
- -
+ +
- + +
-
+
-
- +
+
-

{{ $title }}

+

{{ $title }}

-

{{ $message }}

+

{{ $message }}

-
+
@@ -105,7 +219,8 @@ type="button" @click="open = false" {{ $attributes->whereStartsWith('wire:click') }} - class="flex-1 inline-flex items-center justify-center whitespace-nowrap rounded-lg px-4 py-2.5 text-theme-sm font-medium transition-colors duration-150 {{ $config['buttonClass'] }}" + class="confirm-dialog-lte-btn confirm-dialog-lte-btn-confirm" + style="{{ $config['buttonStyle'] }}" > {{ $confirmLabel }} diff --git a/extensions/Servers/Proxmox/views/components/ui/copy-button.blade.php b/extensions/Servers/Proxmox/views/components/ui/copy-button.blade.php index 11fc58321..e2521f180 100644 --- a/extensions/Servers/Proxmox/views/components/ui/copy-button.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/copy-button.blade.php @@ -1,5 +1,5 @@ {{-- - Copy Button Component - TailAdmin style + Copy Button Component - AdminLTE style Small inline button to copy text to clipboard Usage: @@ -10,6 +10,40 @@ 'value', ]) + +
diff --git a/extensions/Servers/Proxmox/views/components/ui/copyable.blade.php b/extensions/Servers/Proxmox/views/components/ui/copyable.blade.php index c5b52107b..110f32edb 100644 --- a/extensions/Servers/Proxmox/views/components/ui/copyable.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/copyable.blade.php @@ -1,5 +1,5 @@ {{-- - Copyable Text Component - TailAdmin style + Copyable Text Component - AdminLTE style Text field with copy to clipboard functionality Usage: @@ -12,9 +12,84 @@ 'masked' => false, ]) -
+ + +
@if($label) - + @endif
@if($masked) - + @else - {{ $value }} + {{ $value }} @endif
diff --git a/extensions/Servers/Proxmox/views/components/ui/dropdown-divider.blade.php b/extensions/Servers/Proxmox/views/components/ui/dropdown-divider.blade.php index cf68742b5..3ce794f37 100644 --- a/extensions/Servers/Proxmox/views/components/ui/dropdown-divider.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/dropdown-divider.blade.php @@ -1,5 +1,17 @@ {{-- - Dropdown Divider Component - TailAdmin style + Dropdown Divider Component - AdminLTE style --}} -
+ + + diff --git a/extensions/Servers/Proxmox/views/components/ui/dropdown-item.blade.php b/extensions/Servers/Proxmox/views/components/ui/dropdown-item.blade.php index 4347db074..7f4103bd8 100644 --- a/extensions/Servers/Proxmox/views/components/ui/dropdown-item.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/dropdown-item.blade.php @@ -1,5 +1,5 @@ {{-- - Dropdown Item Component - TailAdmin style + Dropdown Item Component - AdminLTE style --}} @props([ @@ -11,28 +11,82 @@ @php $tag = $href ? 'a' : 'button'; - - $variantClasses = [ - 'default' => 'text-gray-700 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-300 dark:hover:bg-gray-800 dark:hover:text-white', - 'danger' => 'text-error-600 hover:bg-error-50 dark:text-error-400 dark:hover:bg-error-500/10', - 'success' => 'text-success-600 hover:bg-success-50 dark:text-success-400 dark:hover:bg-success-500/10', - ]; - - $variantClass = $variantClasses[$variant] ?? $variantClasses['default']; @endphp + + <{{ $tag }} @if($href) href="{{ $href }}" @endif @if($tag === 'button') type="button" @endif @if($disabled) disabled @endif {{ $attributes->class([ - 'relative flex w-full cursor-pointer select-none items-center gap-2.5 rounded-lg px-3 py-2 text-theme-sm outline-none transition-colors duration-150', - $variantClass, - 'pointer-events-none opacity-50' => $disabled, + 'dropdown-item-lte', + 'dropdown-item-lte-danger' => $variant === 'danger', + 'dropdown-item-lte-success' => $variant === 'success', + 'dropdown-item-lte-disabled' => $disabled, ]) }} > @if($icon) - + @endif - {{ $slot }} + {{ $slot }} diff --git a/extensions/Servers/Proxmox/views/components/ui/dropdown.blade.php b/extensions/Servers/Proxmox/views/components/ui/dropdown.blade.php index 1c7635dfe..6faab3a46 100644 --- a/extensions/Servers/Proxmox/views/components/ui/dropdown.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/dropdown.blade.php @@ -1,5 +1,5 @@ {{-- - Dropdown Component - TailAdmin style + Dropdown Component - AdminLTE style Usage: @@ -21,23 +21,50 @@ ]) @php - $alignClasses = [ - 'left' => 'ltr:origin-top-left rtl:origin-top-right start-0', - 'right' => 'ltr:origin-top-right rtl:origin-top-left end-0', - 'center' => 'origin-top left-1/2 -translate-x-1/2', + $alignStyles = [ + 'left' => 'left: 0; transform-origin: top left;', + 'right' => 'right: 0; transform-origin: top right;', + 'center' => 'left: 50%; transform: translateX(-50%); transform-origin: top center;', ]; - $widthClasses = [ - '32' => 'w-32', - '40' => 'w-40', - '48' => 'w-48', - '56' => 'w-56', - '64' => 'w-64', - '80' => 'w-80', + $widthStyles = [ + '32' => 'width: 8rem;', + '40' => 'width: 10rem;', + '48' => 'width: 12rem;', + '56' => 'width: 14rem;', + '64' => 'width: 16rem;', + '80' => 'width: 20rem;', ]; @endphp -
+ + +
diff --git a/extensions/Servers/Proxmox/views/components/ui/editable-field.blade.php b/extensions/Servers/Proxmox/views/components/ui/editable-field.blade.php index ac5c20212..a946ff16f 100644 --- a/extensions/Servers/Proxmox/views/components/ui/editable-field.blade.php +++ b/extensions/Servers/Proxmox/views/components/ui/editable-field.blade.php @@ -1,5 +1,5 @@ {{-- - Editable Field Component - TailAdmin style + Editable Field Component - AdminLTE style A field with display value and edit button that opens a modal Usage: @@ -31,18 +31,256 @@ 'error' => null, ]) -
- -
- {{ $value ?? 'Not set' }} + + +
+ +
+ {{ $value ?? 'Not set' }} @if($editClick) @endif
@@ -60,8 +298,7 @@ x-transition:leave-end="opacity-0" @click="showEditModal = false; @if($cancelClick) $wire.{{ $cancelClick }}() @endif" @keydown.escape.window="showEditModal = false; @if($cancelClick) $wire.{{ $cancelClick }}() @endif" - class="fixed inset-0 z-99999 bg-gray-900/50 backdrop-blur-sm dark:bg-gray-900/80" - style="display: none;" + class="editable-field-lte-backdrop" >
@@ -75,48 +312,47 @@ x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95" @click.away="showEditModal = false; @if($cancelClick) $wire.{{ $cancelClick }}() @endif" - class="fixed inset-0 z-99999 flex items-center justify-center p-4" - style="display: none;" + class="editable-field-lte-modal-container" > -
-
-

Edit {{ $label }}

+
+
+

Edit {{ $label }}

-
-
- +
+
+ whereStartsWith('wire:model') }} - class="mt-2 h-11 w-full rounded-lg border border-gray-300 bg-transparent px-4 text-theme-sm shadow-theme-xs placeholder:text-gray-400 focus:border-brand-300 focus:outline-none focus:ring-3 focus:ring-brand-500/10 dark:border-gray-700 dark:bg-gray-900 dark:text-white/90 dark:placeholder:text-gray-500 dark:focus:border-brand-600" + class="editable-field-lte-input" placeholder="{{ $placeholder ?? 'Enter ' . strtolower($label) }}" />
@if($error) -
{{ $error }}
+
{{ $error }}
@endif @if(isset($hint)) -
{{ $hint }}
+
{{ $hint }}
@endif
-
+