refactor: improve layout and styling for DNS and Windows server sections
This commit is contained in:
@@ -617,9 +617,8 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div style="background-image: url('https://billing.virtnet.bond/assets/images/dns.jpeg'); background-size: 100%; height: 4vh;" class="flex flex-col p-3 rounded-t-lg border-t border-x border-neutral"></div>
|
||||
<div class="flex flex-col gap-3 bg-background-secondary hover:bg-background-secondary border-x border-neutral p-3">
|
||||
<div class="flex flex-col gap-1">
|
||||
<div style="background-image: url('https://billing.virtnet.bond/assets/images/dns.jpeg'); background-size: cover; background-position: center; height: 3rem;" class="rounded-t-lg border-t border-x border-gray-200 dark:border-gray-700"></div>
|
||||
<div class="bg-white dark:bg-gray-800 border-x border-gray-200 dark:border-gray-700 p-3 space-y-3">
|
||||
<div class="flex items-center gap-2 min-w-0">
|
||||
<h2 class="text-base font-semibold">DNS</h2>
|
||||
<div class="relative" x-data="{ open: false }" x-cloak>
|
||||
@@ -627,10 +626,10 @@
|
||||
<x-ri-question-line class="size-4" />
|
||||
</button>
|
||||
<div x-show="open" @click="open = false" @keydown.escape.window="open = false"
|
||||
class="fixed inset-0 z-[60] bg-gray-900 bg-opacity-50 backdrop-blur-sm" style="display: none;"></div>
|
||||
class="fixed inset-0 z-[60] bg-gray-900 bg-opacity-50" style="display: none;"></div>
|
||||
<div x-show="open" @click.away="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-background-secondary rounded-lg border border-gray-200 dark:border-gray-700 shadow-xl p-4">
|
||||
<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-4">
|
||||
<button @click="open = false" class="absolute top-3 right-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
|
||||
<x-ri-close-line class="size-4" />
|
||||
</button>
|
||||
@@ -691,48 +690,41 @@
|
||||
<span>{{ str_replace(':', '-', $server->primaryIpv6->ip) . '.sslip.io' }} <small class="text-gray-500">(<a href="https://sslip.io" target="_blank" class="underline">sslip.io</a>)</small></span>
|
||||
<div x-data="{
|
||||
copied: false,
|
||||
copyText: '{{ str_replace(':', '-', $server->primaryIpv6->ip) . '.sslip.io' }}',
|
||||
copyToClipboard() {
|
||||
navigator.clipboard.writeText(this.copyText);
|
||||
this.copied = true;
|
||||
setTimeout(() => this.copied = false, 3000);
|
||||
}
|
||||
}" class="flex items-center">
|
||||
<button @click="copyToClipboard()" type="button" class="text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 relative inline-flex items-center justify-center ml-1">
|
||||
<span x-show="copied" x-transition class="absolute"><x-ri-check-fill class="size-3 text-success" /></span>
|
||||
<span x-show="!copied" x-transition class="absolute"><x-ri-file-copy-fill class="size-3" /></span>
|
||||
</button>
|
||||
</div>
|
||||
copyText: '{{ str_replace(':', '-', $server->primaryIpv6->ip) . '.sslip.io' }}',
|
||||
copyToClipboard() { navigator.clipboard.writeText(this.copyText); this.copied = true; setTimeout(() => this.copied = false, 2000); }
|
||||
}">
|
||||
<button @click="copyToClipboard()" type="button" class="text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 relative inline-flex items-center justify-center">
|
||||
<span x-show="copied" x-transition class="absolute"><x-ri-check-fill class="size-3 text-success" /></span>
|
||||
<span x-show="!copied" x-transition class="absolute"><x-ri-file-copy-fill class="size-3" /></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- backname.io -->
|
||||
<div class="flex items-center gap-1 ml-4 text-xs">
|
||||
<span>{{ str_replace(':', '-', $server->primaryIpv6->ip) . '.backname.io' }} <small class="text-gray-500">(<a href="https://backname.io" target="_blank" class="underline">backname.io</a>)</small></span>
|
||||
<div x-data="{
|
||||
copied: false,
|
||||
copyText: '{{ str_replace(':', '-', $server->primaryIpv6->ip) . '.backname.io' }}',
|
||||
copyToClipboard() { navigator.clipboard.writeText(this.copyText); this.copied = true; setTimeout(() => this.copied = false, 2000); }
|
||||
}">
|
||||
<button @click="copyToClipboard()" type="button" class="text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 relative inline-flex items-center justify-center">
|
||||
<span x-show="copied" x-transition class="absolute"><x-ri-check-fill class="size-3 text-success" /></span>
|
||||
<span x-show="!copied" x-transition class="absolute"><x-ri-file-copy-fill class="size-3" /></span>
|
||||
</button>
|
||||
</div>
|
||||
<!-- backname.io -->
|
||||
<div class="flex items-center gap-1 ml-4 text-xs">
|
||||
<span>{{ str_replace(':', '-', $server->primaryIpv6->ip) . '.backname.io' }} <small class="text-gray-500">(<a href="https://backname.io" target="_blank" class="underline">backname.io</a>)</small></span>
|
||||
<div x-data="{
|
||||
copied: false,
|
||||
copyText: '{{ str_replace(':', '-', $server->primaryIpv6->ip) . '.backname.io' }}',
|
||||
copyToClipboard() { navigator.clipboard.writeText(this.copyText); this.copied = true; setTimeout(() => this.copied = false, 2000); }
|
||||
}">
|
||||
<button @click="copyToClipboard()" type="button" class="text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 relative inline-flex items-center justify-center">
|
||||
<span x-show="copied" x-transition class="absolute"><x-ri-check-fill class="size-3 text-success" /></span>
|
||||
<span x-show="!copied" x-transition class="absolute"><x-ri-file-copy-fill class="size-3" /></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-blue-50 dark:bg-blue-950 border border-blue-200 dark:border-blue-800 p-3 rounded-b-lg text-xs text-gray-600 dark:text-gray-400">
|
||||
<p class="font-semibold"><code>@</code> = root domain → {{ $server->primaryIpv6->ip }} | <code>*.@</code> = wildcard subdomains → same IP</p>
|
||||
<p class="mt-1 text-gray-500 dark:text-gray-500">rDNS PTR: No PTR records via RIR systems except direct contract customers.</p>
|
||||
</div>
|
||||
<div class="bg-blue-50 dark:bg-blue-950 border border-blue-200 dark:border-blue-800 p-3 rounded-b-lg text-xs text-gray-600 dark:text-gray-400">
|
||||
<p class="font-semibold"><code>@</code> = root domain → {{ $server->primaryIpv6->ip }} | <code>*.@</code> = wildcard subdomains → same IP</p>
|
||||
<p class="mt-1 text-gray-500 dark:text-gray-500">rDNS PTR: No PTR records via RIR systems except direct contract customers.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if(stripos($server->os->name, 'Windows') !== false)
|
||||
<div>
|
||||
<div style="background-image: url('https://billing.virtnet.bond/assets/images/windows.jpg'); background-size: 100%; height: 4vh;" class="flex flex-col p-3 rounded-t-lg border border-neutral"></div>
|
||||
<div style="background-image: url('https://billing.virtnet.bond/assets/images/windows.jpg'); background-size: cover; background-position: center; height: 3rem;" class="rounded-t-lg border-t border-x border-gray-200 dark:border-gray-700"></div>
|
||||
<div class="bg-blue-50 dark:bg-blue-950 border border-blue-200 dark:border-blue-800 p-3 rounded-b-lg">
|
||||
<div class="flex items-center gap-2">
|
||||
<h2 class="text-base font-semibold">Windows Server</h2>
|
||||
@@ -744,7 +736,7 @@
|
||||
class="fixed inset-0 z-[60] bg-gray-900 bg-opacity-50 backdrop-blur-sm" style="display: none;"></div>
|
||||
<div x-show="open" @click.away="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-background-secondary rounded-lg border border-gray-200 dark:border-gray-700 shadow-xl p-4">
|
||||
<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-4">
|
||||
<button @click="open = false" class="absolute top-3 right-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
|
||||
<x-ri-close-line class="size-4" />
|
||||
</button>
|
||||
@@ -784,7 +776,7 @@
|
||||
@endif
|
||||
|
||||
<!-- Live Network Traffic -->
|
||||
<div wire:ignore class="bg-background-secondary border border-neutral rounded-lg p-4 h-full w-full mt-0">
|
||||
<div wire:ignore class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-4 h-full w-full mt-0">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="text-base font-semibold flex items-center gap-2">
|
||||
@@ -805,7 +797,7 @@
|
||||
<!-- Modal -->
|
||||
<div x-show="open" @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-background-secondary rounded-lg border border-gray-200 dark:border-gray-700 shadow-xl p-4">
|
||||
<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-4">
|
||||
<button @click="open = false" class="absolute top-3 right-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
|
||||
<x-ri-close-line class="size-4" />
|
||||
</button>
|
||||
@@ -834,7 +826,7 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<button type="button" @click="exportLiveNetworkTrafficToCSV()"
|
||||
class="bg-background border border-neutral px-2 py-1 rounded text-xs font-semibold hover:bg-gray-100 dark:hover:bg-gray-800 flex items-center gap-1"
|
||||
class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 px-2 py-1 rounded text-xs font-semibold hover:bg-gray-100 dark:hover:bg-gray-800 flex items-center gap-1"
|
||||
title="Export to CSV">
|
||||
<x-ri-download-line class="size-3" />
|
||||
Export
|
||||
@@ -844,14 +836,23 @@
|
||||
|
||||
<!-- Network Traffic Sections -->
|
||||
<div id="network-traffic-container" data-live-traffic-endpoint="{{ route('proxmox.server.live-traffic', $server) }}">
|
||||
<div class="border border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-4 text-center">
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400">Loading live network statistics…</p>
|
||||
<div class="bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-4">
|
||||
<div class="flex items-center gap-2 mb-3">
|
||||
<div class="w-4 h-4 bg-gray-200 dark:bg-gray-700 rounded animate-pulse"></div>
|
||||
<div class="w-24 h-4 bg-gray-200 dark:bg-gray-700 rounded animate-pulse"></div>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<div class="h-3 bg-gray-200 dark:bg-gray-700 rounded animate-pulse w-3/4"></div>
|
||||
<div class="h-2 bg-gray-200 dark:bg-gray-700 rounded animate-pulse w-full"></div>
|
||||
<div class="h-3 bg-gray-200 dark:bg-gray-700 rounded animate-pulse w-2/3"></div>
|
||||
<div class="h-2 bg-gray-200 dark:bg-gray-700 rounded animate-pulse w-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notes Section -->
|
||||
<div id="notes-section" class="bg-background-secondary border border-neutral rounded-lg p-4 h-full flex flex-col mt-0" x-data="{ showExportErrorModal: false }" x-cloak>
|
||||
<div id="notes-section" class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-4 h-full flex flex-col mt-0" x-data="{ showExportErrorModal: false }" x-cloak>
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<h2 class="text-base font-semibold">Notes</h2>
|
||||
@@ -863,7 +864,7 @@
|
||||
class="fixed inset-0 z-[60] bg-gray-900 bg-opacity-50 backdrop-blur-sm" style="display: none;"></div>
|
||||
<div x-show="open" @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-background-secondary rounded-lg border border-gray-200 dark:border-gray-700 shadow-xl p-4">
|
||||
<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-4">
|
||||
<button @click="open = false" class="absolute top-3 right-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
|
||||
<x-ri-close-line class="size-4" />
|
||||
</button>
|
||||
@@ -886,7 +887,7 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<button type="button" @click="exportNotesToCSV()"
|
||||
class="bg-background border border-neutral px-2 py-1 rounded text-xs font-semibold hover:bg-gray-100 dark:hover:bg-gray-800 flex items-center gap-1"
|
||||
class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 px-2 py-1 rounded text-xs font-semibold hover:bg-gray-100 dark:hover:bg-gray-800 flex items-center gap-1"
|
||||
title="Export notes">
|
||||
<x-ri-download-line class="size-3" />
|
||||
Export
|
||||
@@ -909,7 +910,7 @@
|
||||
</div>
|
||||
<div x-show="showExportErrorModal" @click.away="showExportErrorModal = false"
|
||||
class="fixed inset-0 z-[60] flex items-center justify-center p-4" style="display: none;">
|
||||
<div class="relative w-full max-w-sm bg-background-secondary rounded-lg border border-gray-200 dark:border-gray-700 shadow-xl p-4">
|
||||
<div class="relative w-full max-w-sm bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 shadow-xl p-4">
|
||||
<button @click="showExportErrorModal = false" class="absolute top-3 right-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
|
||||
<x-ri-close-line class="size-4" />
|
||||
</button>
|
||||
@@ -930,7 +931,7 @@
|
||||
@if($isEditingNotes)
|
||||
<div class="space-y-2 flex-1 flex flex-col">
|
||||
<textarea wire:model="notes"
|
||||
class="bg-background border border-neutral rounded px-2 py-1 text-sm w-full resize-y flex-1 focus:outline-none focus:ring-2 focus:ring-secondary"
|
||||
class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded px-2 py-1 text-sm w-full resize-y flex-1 focus:outline-none focus:ring-2 focus:ring-secondary"
|
||||
placeholder="Enter notes..."></textarea>
|
||||
@if($notesError)
|
||||
<div class="text-xs text-error">{{ $notesError }}</div>
|
||||
@@ -946,7 +947,7 @@
|
||||
</div>
|
||||
@else
|
||||
<div class="space-y-2 flex-1 flex flex-col">
|
||||
<div class="bg-background border border-neutral rounded px-2 py-1 text-sm flex-1 overflow-auto prose prose-sm dark:prose-invert max-w-none text-gray-700 dark:text-gray-300">
|
||||
<div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded px-2 py-1 text-sm flex-1 overflow-auto prose prose-sm dark:prose-invert max-w-none text-gray-700 dark:text-gray-300">
|
||||
@if($notes)
|
||||
{!! \Illuminate\Support\Str::markdown(e($notes), [
|
||||
'allow_unsafe_links' => false,
|
||||
@@ -1003,7 +1004,7 @@
|
||||
const createInterfaceCard = (interfaceData) => {
|
||||
const interfaceId = interfaceData.id.replace(/[^a-z0-9]/gi, '-');
|
||||
return `
|
||||
<div class="bg-background-secondary border border-neutral rounded-lg p-3 w-full">
|
||||
<div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-3 w-full">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="text-sm font-semibold flex items-center gap-1">
|
||||
@@ -1211,7 +1212,7 @@
|
||||
|
||||
if (networkData.interfaces.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="bg-background-secondary border border-neutral rounded-lg p-6 text-center">
|
||||
<div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-6 text-center">
|
||||
<svg class="w-10 h-10 mx-auto text-gray-300 dark:text-gray-600 mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
@@ -1610,9 +1611,9 @@
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch live traffic data:', error);
|
||||
const container = document.getElementById('network-traffic-container');
|
||||
if (container && !container.querySelector('.bg-background-secondary')) {
|
||||
if (container && !container.querySelector('.bg-white dark:bg-gray-800')) {
|
||||
container.innerHTML = `
|
||||
<div class="bg-background-secondary border border-neutral rounded-lg p-6 text-center">
|
||||
<div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-6 text-center">
|
||||
<svg class="w-10 h-10 mx-auto text-red-400 mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
|
||||
Reference in New Issue
Block a user