refactor: enhance Cloud-init configuration section with improved layout and styling for better usability
This commit is contained in:
@@ -41,112 +41,117 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="lte-callout lte-callout-info lte-fade-in"
|
||||
x-data="{
|
||||
isCollapsed: localStorage.getItem('overview-notice-collapsed') === 'true',
|
||||
isAdvancedView: localStorage.getItem('proxmox-view-mode') === 'advanced',
|
||||
toggle() {
|
||||
this.isCollapsed = !this.isCollapsed;
|
||||
localStorage.setItem('overview-notice-collapsed', this.isCollapsed);
|
||||
}
|
||||
}"
|
||||
x-init="
|
||||
isAdvancedView = localStorage.getItem('proxmox-view-mode') === 'advanced';
|
||||
window.addEventListener('proxmox-view-mode-changed', (e) => {
|
||||
isAdvancedView = e.detail.isAdvancedView;
|
||||
});
|
||||
"
|
||||
x-show="isAdvancedView"
|
||||
x-transition
|
||||
style="margin-bottom: 1.5rem;">
|
||||
<div style="display: flex; align-items: flex-start; gap: 0.75rem;">
|
||||
<x-ri-information-line class="size-5 lte-text-info" style="flex-shrink: 0; margin-top: 0.125rem;" />
|
||||
<div style="flex: 1; min-width: 0;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.5rem;">
|
||||
<h5 style="font-size: 1.1rem; font-weight: 600; margin: 0;">Cloud-init Configuration</h5>
|
||||
<button @click="toggle()" type="button" class="lte-btn lte-btn-sm lte-btn-outline-secondary" style="padding: 0.25rem 0.5rem;">
|
||||
<x-ri-arrow-down-s-line class="size-4" x-bind:class="isCollapsed ? 'rotate-180' : ''" />
|
||||
</button>
|
||||
</div>
|
||||
<div x-show="!isCollapsed" x-transition>
|
||||
<p style="font-size: 0.875rem; margin-bottom: 0.75rem;">
|
||||
<strong>Hostname, password, and networking</strong> are configured via <strong>cloud-init</strong>. Manual configuration required for:
|
||||
</p>
|
||||
<ul style="font-size: 0.875rem; margin-left: 1.5rem; margin-bottom: 0.75rem; list-style: disc;">
|
||||
<li>ISO installations</li>
|
||||
<li>Manual OS configuration</li>
|
||||
<li>Windows systems (no cloud-init support)</li>
|
||||
</ul>
|
||||
<p style="font-size: 0.875rem; margin: 0;">
|
||||
You will need to <strong>manually configure networking, security settings, and hostname</strong> within the operating system in these scenarios.
|
||||
</p>
|
||||
<div class="space-y-4 lg:space-y-6">
|
||||
<div class="bg-info/10 border border-info/30 rounded-lg p-3 lg:p-4"
|
||||
x-data="{
|
||||
isCollapsed: localStorage.getItem('overview-notice-collapsed') === 'true',
|
||||
isAdvancedView: localStorage.getItem('proxmox-view-mode') === 'advanced',
|
||||
toggle() {
|
||||
this.isCollapsed = !this.isCollapsed;
|
||||
localStorage.setItem('overview-notice-collapsed', this.isCollapsed);
|
||||
}
|
||||
}"
|
||||
x-init="
|
||||
isAdvancedView = localStorage.getItem('proxmox-view-mode') === 'advanced';
|
||||
window.addEventListener('proxmox-view-mode-changed', (e) => {
|
||||
isAdvancedView = e.detail.isAdvancedView;
|
||||
});
|
||||
"
|
||||
x-show="isAdvancedView"
|
||||
x-transition>
|
||||
<div class="flex items-start gap-3">
|
||||
<x-ri-information-line class="size-5 text-info flex-shrink-0 mt-0.5" />
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<h3 class="text-sm font-semibold text-base">Cloud-init Configuration Notice</h3>
|
||||
<button @click="toggle()" type="button" class="text-gray-500 dark:text-gray-400 hover:text-base transition-colors">
|
||||
<x-ri-arrow-down-s-line x-bind:class="isCollapsed ? 'size-4 transition-transform rotate-180' : 'size-4 transition-transform'" />
|
||||
</button>
|
||||
</div>
|
||||
<div x-show="!isCollapsed" x-transition>
|
||||
<p class="text-xs text-gray-600 dark:text-gray-400 leading-relaxed">
|
||||
<strong>Hostname, password, and networking settings</strong> are configured automatically via <strong>cloud-init</strong>.
|
||||
This applies to standard operating system installations that support cloud-init. However, if you are:
|
||||
</p>
|
||||
<ul class="text-xs text-gray-600 dark:text-gray-400 leading-relaxed mt-2 ml-4 list-disc space-y-1">
|
||||
<li>Installing from an ISO image</li>
|
||||
<li>Configuring the operating system manually during installation</li>
|
||||
<li>Using Windows (which does not support cloud-init)</li>
|
||||
</ul>
|
||||
<p class="text-xs text-gray-600 dark:text-gray-400 leading-relaxed mt-2">
|
||||
You will need to <strong>manually configure networking, security settings, and hostname</strong> within the operating system, as cloud-init will not be available in these scenarios.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.5rem;" wire:poll.{{ $fastPolling ? '2s' : '30s' }}="checkStatus"
|
||||
wire:key="{{ $fastPolling ? 'fast' : 'slow' }}">
|
||||
<div style="display: flex; align-items: center; gap: 0.75rem;">
|
||||
<div style="display: flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; border-radius: 0.5rem;" class="lte-bg-primary" style="background: linear-gradient(135deg, var(--lte-primary), var(--lte-info));">
|
||||
<x-ri-server-line class="size-5" style="color: white;" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 style="font-size: 1.5rem; font-weight: 700; margin: 0;">Server Overview</h2>
|
||||
<p class="lte-text-muted" style="font-size: 0.875rem; margin: 0;">Real-time resource monitoring and server details</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative" x-data="{ open: false }" x-cloak>
|
||||
<button type="button" @click="open = true" class="lte-btn lte-btn-sm lte-btn-outline-secondary">
|
||||
<x-ri-question-line class="size-4" />
|
||||
<span>Help</span>
|
||||
</button>
|
||||
<div class="flex flex-col gap-2" wire:poll.{{ $fastPolling ? '2s' : '30s' }}="checkStatus"
|
||||
wire:key="{{ $fastPolling ? 'fast' : 'slow' }}">
|
||||
<div class="flex items-center gap-2 min-w-0">
|
||||
<h2 class="text-lg sm:text-xl font-semibold break-words">Server Overview</h2>
|
||||
<div class="relative" x-data="{ open: false }" x-cloak>
|
||||
<button type="button" @click="open = true" class="text-base/50 hover:text-gray-600 dark:text-gray-400 transition-colors">
|
||||
<x-ri-question-line class="size-4" />
|
||||
</button>
|
||||
<!-- Modal Backdrop -->
|
||||
<div x-show="open"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition ease-in duration-150"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
@click="open = false"
|
||||
@keydown.escape.window="open = false"
|
||||
class="fixed inset-0 z-[60] bg-gray-900 bg-opacity-50"
|
||||
class="fixed inset-0 z-[60] bg-black/50 backdrop-blur-sm"
|
||||
style="display: none;">
|
||||
</div>
|
||||
<!-- Modal -->
|
||||
<div x-show="open"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0 scale-95"
|
||||
x-transition:enter-end="opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-150"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100 scale-100"
|
||||
x-transition:leave-end="opacity-0 scale-95"
|
||||
@click.away="open = false"
|
||||
@keydown.escape.window="open = false"
|
||||
class="fixed inset-0 z-[60] flex items-center justify-center p-4"
|
||||
style="display: none;">
|
||||
<div class="relative w-full max-w-xl max-h-[90vh] overflow-y-auto bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 shadow-xl p-5">
|
||||
<button @click="open = false" class="absolute top-3 right-3 text-gray-400 hover:text-gray-600 dark:text-gray-500">
|
||||
<div class="relative w-full max-w-2xl max-h-[90vh] overflow-y-auto bg-background-secondary rounded-xl border border-gray-200 dark:border-gray-800 shadow-2xl p-6">
|
||||
<button @click="open = 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-center gap-2 mb-3 pr-6">
|
||||
<div class="flex items-center justify-center w-8 h-8 rounded bg-blue-100 dark:bg-blue-900">
|
||||
<x-ri-server-line class="size-4 text-blue-600 dark:text-blue-400" />
|
||||
<div class="flex items-center gap-3 mb-4 pr-8">
|
||||
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-primary/10">
|
||||
<x-ri-server-line class="size-5 text-primary" />
|
||||
</div>
|
||||
<h6 class="text-base font-semibold text-gray-800 dark:text-gray-100">Server Details</h6>
|
||||
<h6 class="font-sans text-lg font-semibold leading-tight text-base">
|
||||
Server Overview
|
||||
</h6>
|
||||
</div>
|
||||
<p class="text-sm text-gray-700 dark:text-gray-300 mb-3">
|
||||
VM information: status, resources, network config.
|
||||
<p class="block font-sans text-sm font-normal leading-relaxed text-base/90 mb-4">
|
||||
Complete overview of your virtual machine including real-time resource usage, server status, network configuration, and DNS information.
|
||||
</p>
|
||||
<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">Status:</span> Power state with real-time updates.</p>
|
||||
<p><span class="font-semibold text-gray-700 dark:text-gray-300">Resources:</span> CPU, memory, disk, network stats.</p>
|
||||
<p><span class="font-semibold text-gray-700 dark:text-gray-300">Network:</span> IP addresses and interface info.</p>
|
||||
<div class="pt-4 mt-4 border-t border-gray-200 dark:border-gray-800 space-y-2.5">
|
||||
<p class="block font-sans text-xs font-normal leading-relaxed text-base/75">
|
||||
<span class="font-semibold text-base/90">Status:</span> Power state with real-time updates every 2-30 seconds.
|
||||
</p>
|
||||
<p class="block font-sans text-xs font-normal leading-relaxed text-base/75">
|
||||
<span class="font-semibold text-base/90">Resources:</span> CPU, memory usage, and uptime statistics from the hypervisor.
|
||||
</p>
|
||||
<p class="block font-sans text-xs font-normal leading-relaxed text-base/75">
|
||||
<span class="font-semibold text-base/90">Network:</span> IPv4/IPv6 addresses and DNS configuration for your VM.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">
|
||||
Real-time resource monitoring and server configuration details.
|
||||
</p>
|
||||
</div>
|
||||
<style>
|
||||
/* TailAdmin Progress Bar Styles */
|
||||
@@ -311,90 +316,88 @@
|
||||
$lastSampleTimestamp = now()->toIso8601String();
|
||||
@endphp
|
||||
|
||||
<!-- Resource Stats Grid -->
|
||||
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; margin-bottom: 1.5rem;">
|
||||
@foreach($resourceAllocations as $resource)
|
||||
<div class="lte-card" style="margin-bottom: 0;">
|
||||
<div class="lte-card-body" style="padding: 1.25rem;">
|
||||
<div style="display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 0.75rem;">
|
||||
<div>
|
||||
<h6 style="font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin: 0 0 0.5rem 0;" class="lte-text-muted">{{ $resource['label'] }}</h6>
|
||||
<div style="font-size: 1.5rem; font-weight: 700; line-height: 1;">{{ $resource['usage_summary'] }}</div>
|
||||
</div>
|
||||
<!-- Resource Stats Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-3 lg:gap-4">
|
||||
@foreach($resourceAllocations as $resource)
|
||||
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-2xl shadow-theme-sm p-3 lg:p-4">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<h3 class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">{{ $resource['label'] }}</h3>
|
||||
@if(isset($resource['badge']))
|
||||
<span class="lte-badge lte-badge-{{ $resource['badge']['label'] === 'Healthy' ? 'success' : ($resource['badge']['label'] === 'Watchlist' ? 'warning' : 'danger') }}" style="font-size: 0.65rem;">
|
||||
<span class="text-xs font-semibold px-2 py-1 rounded {{ $resource['badge']['label'] === 'Healthy' ? 'bg-success/10 text-success' : ($resource['badge']['label'] === 'Watchlist' ? 'bg-warning/10 text-warning' : 'bg-error/10 text-error') }}">
|
||||
{{ $resource['badge']['label'] }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="text-2xl font-bold mb-2">{{ $resource['usage_summary'] }}</div>
|
||||
@if($resource['used_percent'] !== null)
|
||||
<div class="lte-progress" style="height: 6px; margin-bottom: 0.5rem;">
|
||||
<div class="lte-progress-bar" style="width: {{ min(100, $resource['used_percent']) }}%; background: {{ $resource['gradient'] }};" role="progressbar"></div>
|
||||
<div class="relative w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden mb-2">
|
||||
<div class="absolute inset-y-0 left-0 rounded-full"
|
||||
style="width: {{ min(100, $resource['used_percent']) }}%; background: {{ $resource['gradient'] }};"></div>
|
||||
</div>
|
||||
<div style="font-size: 0.75rem;" class="lte-text-muted">{{ number_format($resource['used_percent'], 1) }}% of {{ $resource['entitlement_label'] }}</div>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ number_format($resource['used_percent'], 1) }}% of {{ $resource['entitlement_label'] }}
|
||||
</p>
|
||||
@else
|
||||
<div style="font-size: 0.75rem; margin-top: 0.5rem;" class="lte-text-muted">{{ $resource['entitlement_label'] }}</div>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mt-2">
|
||||
{{ $resource['entitlement_label'] }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<!-- Main Grid Layout -->
|
||||
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.25rem;">
|
||||
<!-- Server Information Card -->
|
||||
<div class="lte-card">
|
||||
<div class="lte-card-header lte-bg-primary" style="color: white;">
|
||||
<h5 class="lte-card-title" style="margin: 0; color: white; display: flex; align-items: center; gap: 0.5rem;">
|
||||
<x-ri-server-fill class="size-4" />
|
||||
Server Information
|
||||
</h5>
|
||||
</div>
|
||||
<div class="lte-card-body" style="padding: 0;">
|
||||
<table class="lte-table" style="margin-bottom: 0;">
|
||||
<tbody>
|
||||
<!-- Main Grid Layout -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-3 lg:gap-4">
|
||||
<!-- Server Information Card -->
|
||||
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-2xl shadow-theme-sm overflow-hidden">
|
||||
<div class="flex items-center justify-between p-3 lg:p-4 bg-primary/5 border-b border-gray-200 dark:border-gray-800">
|
||||
<div class="flex items-center gap-2">
|
||||
<x-ri-server-fill class="size-5 text-primary" />
|
||||
<h3 class="text-base sm:text-lg font-semibold">Server Information</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-3 lg:p-4">
|
||||
<div class="space-y-3">
|
||||
<!-- Status -->
|
||||
<tr>
|
||||
<td style="width: 40%; font-weight: 600; font-size: 0.875rem; padding: 0.75rem 1rem;">
|
||||
<x-ri-pulse-line class="size-4" style="display: inline-block; vertical-align: middle; margin-right: 0.375rem;" />
|
||||
Status
|
||||
</td>
|
||||
<td style="padding: 0.75rem 1rem;">
|
||||
<div class="flex items-center justify-between py-2 border-b border-gray-200 dark:border-gray-800">
|
||||
<div class="flex items-center gap-2 text-sm font-semibold text-gray-600 dark:text-gray-400">
|
||||
<x-ri-pulse-line class="size-4" />
|
||||
<span>Status</span>
|
||||
</div>
|
||||
<div>
|
||||
@if ($status && $status->status === 'running')
|
||||
<span class="lte-badge lte-badge-success">
|
||||
<x-ri-checkbox-circle-fill class="size-3" style="display: inline-block; vertical-align: middle; margin-right: 0.25rem;" />
|
||||
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-semibold bg-success/10 text-success rounded-full">
|
||||
<span class="w-1.5 h-1.5 bg-success rounded-full animate-pulse"></span>
|
||||
Running
|
||||
</span>
|
||||
@else
|
||||
<span class="lte-badge lte-badge-warning">
|
||||
<x-ri-stop-circle-line class="size-3" style="display: inline-block; vertical-align: middle; margin-right: 0.25rem;" />
|
||||
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-semibold bg-warning/10 text-warning rounded-full">
|
||||
<x-ri-stop-circle-line class="size-3" />
|
||||
Stopped
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Operating System -->
|
||||
<tr>
|
||||
<td style="font-weight: 600; font-size: 0.875rem; padding: 0.75rem 1rem;">
|
||||
<x-ri-ubuntu-line class="size-4" style="display: inline-block; vertical-align: middle; margin-right: 0.375rem;" />
|
||||
Operating System
|
||||
</td>
|
||||
<td style="padding: 0.75rem 1rem;">{{ $server->os->name }}</td>
|
||||
</tr>
|
||||
<div class="flex items-center justify-between py-2 border-b border-gray-200 dark:border-gray-800">
|
||||
<div class="flex items-center gap-2 text-sm font-semibold text-gray-600 dark:text-gray-400">
|
||||
<x-ri-ubuntu-line class="size-4" />
|
||||
<span>Operating System</span>
|
||||
</div>
|
||||
<span class="text-sm">{{ $server->os->name }}</span>
|
||||
</div>
|
||||
<!-- Hostname -->
|
||||
<tr x-data="{ showHostnameEditModal: @entangle('isEditingHostname') }">
|
||||
<td style="font-weight: 600; font-size: 0.875rem; padding: 0.75rem 1rem;">
|
||||
<x-ri-computer-line class="size-4" style="display: inline-block; vertical-align: middle; margin-right: 0.375rem;" />
|
||||
Hostname
|
||||
</td>
|
||||
<td style="padding: 0.75rem 1rem;">
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;">
|
||||
<code style="font-size: 0.875rem;">{{ $server->hostname ?? $status->name ?? 'N/A' }}</code>
|
||||
<button wire:click="startEditingHostname" type="button" class="lte-btn lte-btn-xs lte-btn-outline-primary">
|
||||
<x-ri-edit-line class="size-3" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center justify-between py-2 border-b border-gray-200 dark:border-gray-800" x-data="{ showHostnameEditModal: @entangle('isEditingHostname') }">
|
||||
<div class="flex items-center gap-2 text-sm font-semibold text-gray-600 dark:text-gray-400">
|
||||
<x-ri-computer-line class="size-4" />
|
||||
<span>Hostname</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<code class="text-sm">{{ $server->hostname ?? $status->name ?? 'N/A' }}</code>
|
||||
<button wire:click="startEditingHostname" type="button" class="text-primary hover:text-primary/80 transition-colors">
|
||||
<x-ri-edit-line class="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Hostname Edit Modal (unchanged for brevity) -->
|
||||
<div x-cloak x-show="showHostnameEditModal"
|
||||
@@ -459,68 +462,61 @@
|
||||
|
||||
<!-- Primary IPv4 Address -->
|
||||
@if($server->primaryIpv4)
|
||||
<tr x-data="{ copied: false, copyText: '{{ $server->primaryIpv4->ip }}', copy() { navigator.clipboard.writeText(this.copyText); this.copied = true; setTimeout(() => this.copied = false, 2000); } }">
|
||||
<td style="font-weight: 600; font-size: 0.875rem; padding: 0.75rem 1rem;">
|
||||
<x-ri-global-line class="size-4" style="display: inline-block; vertical-align: middle; margin-right: 0.375rem;" />
|
||||
IPv4 Address
|
||||
</td>
|
||||
<td style="padding: 0.75rem 1rem;">
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;">
|
||||
<code style="font-size: 0.875rem;">{{ $server->primaryIpv4->ip }}</code>
|
||||
<button @click="copy()" type="button" class="lte-btn lte-btn-xs lte-btn-outline-success">
|
||||
<x-ri-check-fill x-show="copied" class="size-3" />
|
||||
<x-ri-file-copy-line x-show="!copied" class="size-3" />
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<div class="flex items-center justify-between py-2 border-b border-gray-200 dark:border-gray-800" x-data="{ copied: false, copyText: '{{ $server->primaryIpv4->ip }}', copy() { navigator.clipboard.writeText(this.copyText); this.copied = true; setTimeout(() => this.copied = false, 2000); } }">
|
||||
<div class="flex items-center gap-2 text-sm font-semibold text-gray-600 dark:text-gray-400">
|
||||
<x-ri-global-line class="size-4" />
|
||||
<span>IPv4 Address</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<code class="text-sm">{{ $server->primaryIpv4->ip }}</code>
|
||||
<button @click="copy()" type="button" class="text-success hover:text-success/80 transition-colors">
|
||||
<x-ri-check-fill x-show="copied" class="size-4" />
|
||||
<x-ri-file-copy-line x-show="!copied" class="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Primary IPv6 Address -->
|
||||
@if($server->primaryIpv6)
|
||||
<tr x-data="{ copied: false, copyText: '{{ $server->primaryIpv6->ip }}', copy() { navigator.clipboard.writeText(this.copyText); this.copied = true; setTimeout(() => this.copied = false, 2000); } }">
|
||||
<td style="font-weight: 600; font-size: 0.875rem; padding: 0.75rem 1rem;">
|
||||
<x-ri-global-line class="size-4" style="display: inline-block; vertical-align: middle; margin-right: 0.375rem;" />
|
||||
IPv6 Address
|
||||
</td>
|
||||
<td style="padding: 0.75rem 1rem;">
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;">
|
||||
<code style="font-size: 0.75rem; max-width: 180px; overflow: hidden; text-overflow: ellipsis; display: block;">{{ $server->primaryIpv6->ip }}</code>
|
||||
<button @click="copy()" type="button" class="lte-btn lte-btn-xs lte-btn-outline-success">
|
||||
<x-ri-check-fill x-show="copied" class="size-3" />
|
||||
<x-ri-file-copy-line x-show="!copied" class="size-3" />
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<div class="flex items-center justify-between py-2 border-b border-gray-200 dark:border-gray-800" x-data="{ copied: false, copyText: '{{ $server->primaryIpv6->ip }}', copy() { navigator.clipboard.writeText(this.copyText); this.copied = true; setTimeout(() => this.copied = false, 2000); } }">
|
||||
<div class="flex items-center gap-2 text-sm font-semibold text-gray-600 dark:text-gray-400">
|
||||
<x-ri-global-line class="size-4" />
|
||||
<span>IPv6 Address</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<code class="text-xs truncate max-w-[200px]">{{ $server->primaryIpv6->ip }}</code>
|
||||
<button @click="copy()" type="button" class="text-success hover:text-success/80 transition-colors flex-shrink-0">
|
||||
<x-ri-check-fill x-show="copied" class="size-4" />
|
||||
<x-ri-file-copy-line x-show="!copied" class="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Root Password -->
|
||||
<tr x-data="{ showPasswordViewModal: false, showPasswordEditModal: @entangle('isEditingPassword') }">
|
||||
<td style="font-weight: 600; font-size: 0.875rem; padding: 0.75rem 1rem;">
|
||||
<x-ri-lock-password-line class="size-4" style="display: inline-block; vertical-align: middle; margin-right: 0.375rem;" />
|
||||
Root Password
|
||||
</td>
|
||||
<td style="padding: 0.75rem 1rem;">
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem; justify-content: space-between;">
|
||||
<span>
|
||||
@if(isset($server->password) && $server->password)
|
||||
••••••••
|
||||
@else
|
||||
<span class="lte-badge lte-badge-info">Emailed</span>
|
||||
@endif
|
||||
</span>
|
||||
<div style="display: flex; gap: 0.25rem;">
|
||||
@if(isset($server->password) && $server->password)
|
||||
<button type="button" class="lte-btn lte-btn-xs lte-btn-outline-secondary" @click="showPasswordViewModal = true">
|
||||
<x-ri-eye-line class="size-3" />
|
||||
</button>
|
||||
@endif
|
||||
<button type="button" class="lte-btn lte-btn-xs lte-btn-outline-primary" wire:click="startEditingPassword">
|
||||
<x-ri-edit-line class="size-3" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between py-2" x-data="{ showPasswordViewModal: false, showPasswordEditModal: @entangle('isEditingPassword') }">
|
||||
<div class="flex items-center gap-2 text-sm font-semibold text-gray-600 dark:text-gray-400">
|
||||
<x-ri-lock-password-line class="size-4" />
|
||||
<span>Root Password</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-sm">
|
||||
@if(isset($server->password) && $server->password)
|
||||
••••••••
|
||||
@else
|
||||
<span class="inline-flex items-center px-2.5 py-1 text-xs font-semibold bg-info/10 text-info rounded-full">Emailed</span>
|
||||
@endif
|
||||
</span>
|
||||
@if(isset($server->password) && $server->password)
|
||||
<button type="button" class="text-gray-500 hover:text-base transition-colors" @click="showPasswordViewModal = true">
|
||||
<x-ri-eye-line class="size-4" />
|
||||
</button>
|
||||
@endif
|
||||
<button type="button" class="text-primary hover:text-primary/80 transition-colors" wire:click="startEditingPassword">
|
||||
<x-ri-edit-line class="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Password View Modal -->
|
||||
<div x-cloak x-show="showPasswordViewModal"
|
||||
|
||||
Reference in New Issue
Block a user