82 lines
2.6 KiB
Svelte
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>
|