Files
nadir-webui/src/routes/dashboard/[machineId]/system/hostname/+page.svelte
T
2026-06-25 14:46:48 +02:00

82 lines
2.6 KiB
Svelte

<script lang="ts">
import { page } from '$app/state';
import PageMeta from '$lib/components/seo/page-meta.svelte';
import { Button } from '$lib/components/ui/button';
import * as Card from '$lib/components/ui/card';
import { Input } from '$lib/components/ui/input';
import { Label } from '$lib/components/ui/label';
import { m } from '$lib/paraglide/messages';
import { setHostname, systemHostname } from '$lib/remotes/system.remote';
import { extractErrorMessage } from '$lib/utils';
import { toast } from 'svelte-sonner';
const machineId = $derived(page.params.machineId!);
const host = $derived(systemHostname(machineId));
const formId = $props.id();
let saving = $state(false);
// ponytail: hostname syntax is RFC1123 — letters, digits, hyphen, max 63 chars per label.
const HOSTNAME_RE =
/^(?=.{1,253}$)([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
</script>
<PageMeta title={m.seo_title_system_hostname()} description={m.seo_desc_system_hostname()} />
<div class="mx-auto flex w-full max-w-3xl flex-col gap-4 p-4">
<h1 class="text-2xl font-semibold tracking-tight">{m.nav_system_hostname()}</h1>
<svelte:boundary>
{#snippet failed(err)}
<Card.Root>
<Card.Content class="text-destructive py-6">{(err as Error).message}</Card.Content>
</Card.Root>
{/snippet}
{@const h = await host}
<Card.Root>
<Card.Header>
<Card.Title>{m.system_hostname_current()}</Card.Title>
<Card.Description>{h.hostname}</Card.Description>
</Card.Header>
<Card.Content>
<form
class="flex flex-col gap-2 sm:flex-row sm:items-end"
onsubmit={async (e) => {
e.preventDefault();
const fd = new FormData(e.currentTarget);
const v = String(fd.get('hostname') ?? '').trim();
if (!HOSTNAME_RE.test(v)) {
toast.error(m.system_hostname_invalid());
return;
}
if (v === h.hostname) return;
saving = true;
try {
await setHostname({ hostname: v, machineId });
toast.success(m.saved());
} catch (err) {
console.log(err);
toast.error(extractErrorMessage(err) ?? m.errors_generic());
} finally {
saving = false;
}
}}
>
<div class="flex grow flex-col gap-1.5">
<Label for={formId + 'hn'}>{m.nav_system_hostname()}</Label>
<Input
id={formId + 'hn'}
name="hostname"
value={h.hostname}
required
pattern="[A-Za-z0-9.\-]+"
maxlength={253}
/>
</div>
<Button type="submit" disabled={saving}>{m.save()}</Button>
</form>
</Card.Content>
</Card.Root>
</svelte:boundary>
</div>