154 lines
9.8 KiB
PHP
154 lines
9.8 KiB
PHP
<div class="space-y-6">
|
|
{{-- Kopf wie auf der Einstellungsseite: Augenbraue, Titel, ein Satz
|
|
darunter. Die Seite hatte vorher einen Zurück-Link an dieser Stelle und
|
|
darunter eine sechsteilige Anleitung — der Auftrag der Seite, vier
|
|
Felder auszufüllen, ging darin unter. --}}
|
|
<header class="animate-rise">
|
|
<p class="lbl">{{ __('hosts.takeover.eyebrow') }}</p>
|
|
<h1 class="mt-[7px] text-[23px] font-bold leading-[1.12] tracking-[-0.03em] text-ink min-[901px]:text-[30px]">
|
|
@if ($command === null)
|
|
{{ __('hosts.create_title') }}
|
|
@else
|
|
{{ __('hosts.takeover.title', ['name' => $createdName]) }}
|
|
@endif
|
|
</h1>
|
|
<p class="mt-2 max-w-[76ch] text-sm leading-relaxed text-muted">
|
|
{{ $command === null ? __('hosts.create_sub') : __('hosts.takeover.subtitle') }}
|
|
</p>
|
|
</header>
|
|
|
|
<div class="flex flex-col gap-6 lg:flex-row lg:items-start lg:gap-8">
|
|
{{-- Der Ablauf als Schiene, nicht als Wand. Sie beantwortet „wo stehe
|
|
ich" auf einen Blick und überlässt dem Hauptteil die Arbeit. --}}
|
|
<x-admin.takeover-rail :current="$command === null ? 3 : 4"
|
|
class="animate-rise [animation-delay:40ms]" />
|
|
|
|
<div class="min-w-0 flex-1 space-y-8 lg:max-w-[820px]">
|
|
@if ($command === null)
|
|
@if ($missingSettings)
|
|
<x-ui.alert variant="warning" class="animate-rise [animation-delay:60ms]">
|
|
<p class="font-medium">{{ __('hosts.takeover.missing_title') }}</p>
|
|
<p class="mt-1">{{ __('hosts.takeover.missing_body', ['settings' => implode(', ', $missingSettings)]) }}</p>
|
|
</x-ui.alert>
|
|
@endif
|
|
|
|
{{-- Die zwei Schritte beim Anbieter. Sie stehen VOR dem
|
|
Formular, weil sie vorher erledigt sein müssen: der
|
|
Einmal-Code beginnt mit dem Speichern abzulaufen. --}}
|
|
<section class="animate-rise [animation-delay:60ms]">
|
|
<h2 class="text-md font-bold tracking-[-0.01em] text-ink">{{ __('hosts.takeover.requirements_title') }}</h2>
|
|
<p class="mt-1 max-w-[70ch] text-sm leading-relaxed text-muted">{{ __('hosts.takeover.requirements_sub') }}</p>
|
|
|
|
<x-ui.panel class="mt-4">
|
|
<x-ui.row :label="__('hosts.takeover.s1_title')">
|
|
<p class="text-sm leading-relaxed text-muted">{{ __('hosts.takeover.s1_body') }}</p>
|
|
</x-ui.row>
|
|
<x-ui.row :label="__('hosts.takeover.s2_title')">
|
|
<p class="text-sm leading-relaxed text-muted">{{ __('hosts.takeover.s2_body') }}</p>
|
|
</x-ui.row>
|
|
</x-ui.panel>
|
|
</section>
|
|
|
|
<form wire:submit="save" class="animate-rise [animation-delay:80ms]">
|
|
<h2 class="text-md font-bold tracking-[-0.01em] text-ink">{{ __('hosts.takeover.form_title') }}</h2>
|
|
<p class="mt-1 max-w-[70ch] text-sm leading-relaxed text-muted">{{ __('hosts.takeover.form_sub') }}</p>
|
|
|
|
<x-ui.panel class="mt-4">
|
|
<x-ui.row :label="__('hosts.field.name')" :hint="__('hosts.field.name_hint')" for="name">
|
|
<x-ui.input name="name" wire:model="name" autofocus />
|
|
</x-ui.row>
|
|
|
|
<x-ui.row :label="__('hosts.field.datacenter')" for="datacenter">
|
|
<select id="datacenter" wire:model="datacenter"
|
|
class="block w-full rounded border border-line bg-surface px-3 py-2 text-sm text-ink transition">
|
|
{{-- The building too, where it is known: two
|
|
entries both reading "Falkenstein (fsn)" are
|
|
not a choice anybody can make, and placing a
|
|
second machine for redundancy is exactly when
|
|
it matters which hall it lands in. --}}
|
|
@foreach ($datacenters as $dc)
|
|
<option value="{{ $dc->code }}">{{ $dc->name }} ({{ $dc->code }})@if ($dc->facility) · {{ $dc->facility }}@endif</option>
|
|
@endforeach
|
|
</select>
|
|
@error('datacenter') <p class="mt-1 text-xs text-danger">{{ $message }}</p> @enderror
|
|
</x-ui.row>
|
|
|
|
<x-ui.row :label="__('hosts.field.public_ip')" for="public_ip">
|
|
<x-ui.input name="public_ip" wire:model="public_ip" inputmode="numeric" placeholder="203.0.113.10" />
|
|
</x-ui.row>
|
|
|
|
<x-ui.row :label="__('hosts.field.root_password')" :hint="__('hosts.field.root_password_hint')" for="root_password">
|
|
<x-ui.input name="root_password" wire:model="root_password" type="password" autocomplete="off" />
|
|
</x-ui.row>
|
|
</x-ui.panel>
|
|
|
|
<div class="mt-4 flex items-center justify-end gap-3">
|
|
<a href="{{ route('admin.hosts') }}" wire:navigate>
|
|
<x-ui.button variant="secondary" type="button">{{ __('hosts.cancel') }}</x-ui.button>
|
|
</a>
|
|
<x-ui.button variant="primary" type="submit" wire:loading.attr="disabled">
|
|
<span wire:loading.remove wire:target="save">{{ __('hosts.save') }}</span>
|
|
<span wire:loading wire:target="save">{{ __('hosts.save') }}…</span>
|
|
</x-ui.button>
|
|
</div>
|
|
</form>
|
|
@else
|
|
{{-- Ab hier ist die Befehlszeile die Hauptsache. Sie bekommt die
|
|
volle Breite und steht ganz oben; alles andere ordnet sich
|
|
unter. --}}
|
|
<section class="animate-rise [animation-delay:60ms]">
|
|
<h2 class="text-md font-bold tracking-[-0.01em] text-ink">{{ __('hosts.takeover.command_title') }}</h2>
|
|
<p class="mt-1 max-w-[70ch] text-sm leading-relaxed text-muted">{{ __('hosts.takeover.command_sub') }}</p>
|
|
|
|
<div x-data="{ copied: false }" class="mt-4 overflow-hidden rounded-lg border border-accent-border bg-surface shadow-xs">
|
|
<div class="flex items-center justify-between gap-3 border-b border-line bg-accent-subtle px-4 py-2.5">
|
|
<p class="min-w-0 text-xs font-medium text-accent-text">{{ __('hosts.takeover.once_title') }}</p>
|
|
<button type="button"
|
|
class="inline-flex shrink-0 items-center gap-1.5 rounded border border-line bg-surface px-2.5 py-1 text-xs font-medium text-body transition hover:text-ink"
|
|
x-on:click="navigator.clipboard.writeText($refs.command.textContent.trim()); copied = true; setTimeout(() => copied = false, 2000)">
|
|
<x-ui.icon name="copy" class="size-4" x-show="!copied" />
|
|
<x-ui.icon name="check" class="size-4" x-show="copied" x-cloak />
|
|
<span x-text="copied ? @js(__('hosts.takeover.copied')) : @js(__('hosts.takeover.copy'))">{{ __('hosts.takeover.copy') }}</span>
|
|
</button>
|
|
</div>
|
|
|
|
{{-- Umbrechen statt waagerecht rollen: aus einem Kasten
|
|
mit Rollbalken markiert jemand die Hälfte und merkt
|
|
es erst auf der Maschine. --}}
|
|
<pre class="max-h-64 overflow-y-auto px-4 py-3.5 font-mono text-xs leading-relaxed text-ink break-all whitespace-pre-wrap"
|
|
x-ref="command">{{ $command }}</pre>
|
|
</div>
|
|
|
|
<p class="mt-2 text-xs leading-relaxed text-muted">{{ __('hosts.takeover.once_body') }}</p>
|
|
</section>
|
|
|
|
<section class="animate-rise [animation-delay:80ms]">
|
|
<h2 class="text-md font-bold tracking-[-0.01em] text-ink">{{ __('hosts.takeover.after_title') }}</h2>
|
|
|
|
<x-ui.panel class="mt-4">
|
|
<x-ui.row :label="__('hosts.takeover.s5_title')">
|
|
<p class="text-sm leading-relaxed text-muted">{{ __('hosts.takeover.s5_body') }}</p>
|
|
<p class="mt-1 text-xs leading-relaxed text-muted">{{ __('hosts.takeover.s5_hint', ['url' => $archiveUrl]) }}</p>
|
|
</x-ui.row>
|
|
<x-ui.row :label="__('hosts.takeover.s6_title')">
|
|
<p class="text-sm leading-relaxed text-muted">{{ __('hosts.takeover.s6_body') }}</p>
|
|
<div class="mt-3">
|
|
<a href="{{ route('admin.hosts.show', ['host' => $createdUuid]) }}" wire:navigate>
|
|
<x-ui.button variant="primary" size="sm">
|
|
<x-slot:icon><x-ui.icon name="activity" class="size-4" /></x-slot:icon>
|
|
{{ __('hosts.takeover.watch') }}
|
|
</x-ui.button>
|
|
</a>
|
|
</div>
|
|
</x-ui.row>
|
|
</x-ui.panel>
|
|
</section>
|
|
@endif
|
|
|
|
<p class="max-w-[76ch] text-xs leading-relaxed text-muted animate-rise [animation-delay:100ms]">
|
|
{{ __('hosts.takeover.footnote') }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|