CI / changes (push) Successful in 10s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 25s
CI / web (push) Successful in 36s
CI / go (push) Successful in 49s
CI / bird2 (push) Successful in 17s
CI / release (push) Successful in 3m59s
- Merged birdSettingsSchema and revisionSettingsSchema into settingsKnownSchema, marking the previous schema as deprecated. - Updated emptySettingsKnownForm to utilize emptyBirdSettingsForm and emptyRevisionSettingsForm. - Refactored layout and page components to streamline theme management and improve tab synchronization in network and operations pages. - Introduced new system settings tab in operations and updated settings page to manage theme preferences.
213 lines
5.8 KiB
Svelte
213 lines
5.8 KiB
Svelte
<script lang="ts">
|
|
import { onMount } from 'svelte';
|
|
import { defaults, superForm } from 'sveltekit-superforms';
|
|
import { zod4 } from 'sveltekit-superforms/adapters';
|
|
import {
|
|
birdSettingsSchema,
|
|
emptyBirdSettingsForm,
|
|
type BirdSettingsForm
|
|
} from '$lib/settings/bird-settings.schema.js';
|
|
import {
|
|
buildPayloadFromFormFields,
|
|
loadSettings,
|
|
partitionSettings,
|
|
patchSettings
|
|
} from '$lib/settings/settings-api.js';
|
|
import { BIRD_SETTING_KEYS } from '$lib/settings/settings-known-keys.js';
|
|
import { Button } from '$lib/ui/core/button/index.js';
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle
|
|
} from '$lib/ui/core/card/index.js';
|
|
import { Input } from '$lib/ui/core/input/index.js';
|
|
import { Alert, AlertDescription, AlertTitle } from '$lib/ui/core/alert/index.js';
|
|
import FormField from '$lib/ui/patterns/form/form-field.svelte';
|
|
import { notify, notifyApiError } from '$lib/ui/app/toast.js';
|
|
import Save from '@lucide/svelte/icons/save';
|
|
import Info from '@lucide/svelte/icons/info';
|
|
|
|
let loading = $state(false);
|
|
let saving = $state(false);
|
|
let loaded = $state(false);
|
|
|
|
const { form, errors, reset, validateForm } = superForm(
|
|
defaults(emptyBirdSettingsForm(), zod4(birdSettingsSchema)),
|
|
{
|
|
validators: zod4(birdSettingsSchema),
|
|
SPA: true,
|
|
dataType: 'json'
|
|
}
|
|
);
|
|
|
|
let hasValidationErrors = $derived(
|
|
BIRD_SETTING_KEYS.some((key) => Boolean($errors[key as keyof BirdSettingsForm]?.length))
|
|
);
|
|
|
|
let canSave = $derived.by(() => {
|
|
if (loading || saving || hasValidationErrors || !loaded) return false;
|
|
return BIRD_SETTING_KEYS.some((key) => {
|
|
const value = String($form[key as keyof BirdSettingsForm] ?? '').trim();
|
|
return value !== '' && !$errors[key as keyof BirdSettingsForm]?.length;
|
|
});
|
|
});
|
|
|
|
async function load() {
|
|
loading = true;
|
|
try {
|
|
const settings = await loadSettings();
|
|
const { partitioned } = partitionSettings(settings);
|
|
reset({ data: partitioned.bird });
|
|
loaded = true;
|
|
} catch (e) {
|
|
notifyApiError(e);
|
|
} finally {
|
|
loading = false;
|
|
}
|
|
}
|
|
|
|
async function save() {
|
|
const validation = await validateForm({ update: true });
|
|
if (!validation.valid) {
|
|
notify.error('Исправьте ошибки в полях настроек');
|
|
return;
|
|
}
|
|
if (!canSave) {
|
|
notify.error('Нечего сохранять или есть ошибки в полях');
|
|
return;
|
|
}
|
|
|
|
const payload = buildPayloadFromFormFields(
|
|
BIRD_SETTING_KEYS,
|
|
$form as Record<string, string>,
|
|
$errors as Partial<Record<string, string[]>>
|
|
);
|
|
|
|
saving = true;
|
|
try {
|
|
await patchSettings(payload);
|
|
notify.success('Параметры BIRD сохранены');
|
|
await load();
|
|
} catch (e) {
|
|
notifyApiError(e);
|
|
} finally {
|
|
saving = false;
|
|
}
|
|
}
|
|
|
|
onMount(() => {
|
|
void load();
|
|
});
|
|
</script>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Control plane</CardTitle>
|
|
<CardDescription>
|
|
Глобальные параметры BIRD для pipeline refresh/apply. Сохранение через
|
|
<code class="text-xs">PATCH /v1/settings</code> (роль operator).
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent class="space-y-5">
|
|
<Alert class="border-info/30 bg-info/5">
|
|
<Info class="text-info" />
|
|
<AlertTitle>Подстановка в конфиг</AlertTitle>
|
|
<AlertDescription>
|
|
Значения используются при генерации BIRD-конфигурации в pipeline (router id, local AS,
|
|
адреса). Пиры и спикеры настраиваются на соседних вкладках.
|
|
</AlertDescription>
|
|
</Alert>
|
|
|
|
{#if loading && !loaded}
|
|
<p class="text-sm text-muted-foreground">Загрузка…</p>
|
|
{:else if !loaded}
|
|
<Button variant="outline" onclick={load}>Загрузить параметры</Button>
|
|
{:else}
|
|
<div class="space-y-3">
|
|
<FormField
|
|
id="bird-router-id"
|
|
label="Router ID (bird_router_id)"
|
|
error={$errors.bird_router_id?.[0]}
|
|
>
|
|
<Input id="bird-router-id" bind:value={$form.bird_router_id} placeholder="203.0.113.1" />
|
|
</FormField>
|
|
|
|
<FormField
|
|
id="bird-local-ipv4"
|
|
label="Локальный IPv4 (bird_local_ipv4)"
|
|
error={$errors.bird_local_ipv4?.[0]}
|
|
>
|
|
<Input
|
|
id="bird-local-ipv4"
|
|
bind:value={$form.bird_local_ipv4}
|
|
placeholder="198.51.100.10"
|
|
/>
|
|
</FormField>
|
|
|
|
<FormField
|
|
id="bird-local-ipv6"
|
|
label="Локальный IPv6 (bird_local_ipv6)"
|
|
error={$errors.bird_local_ipv6?.[0]}
|
|
>
|
|
<Input
|
|
id="bird-local-ipv6"
|
|
bind:value={$form.bird_local_ipv6}
|
|
placeholder="2001:db8::10"
|
|
/>
|
|
</FormField>
|
|
|
|
<FormField
|
|
id="bird-local-asn"
|
|
label="Локальный ASN (bird_local_asn)"
|
|
error={$errors.bird_local_asn?.[0]}
|
|
>
|
|
<Input
|
|
id="bird-local-asn"
|
|
type="number"
|
|
min="1"
|
|
bind:value={$form.bird_local_asn}
|
|
placeholder="65001"
|
|
/>
|
|
</FormField>
|
|
|
|
<FormField
|
|
id="bird-bgp-source-ipv4"
|
|
label="BGP source IPv4 (bird_bgp_source_ipv4)"
|
|
error={$errors.bird_bgp_source_ipv4?.[0]}
|
|
>
|
|
<Input
|
|
id="bird-bgp-source-ipv4"
|
|
bind:value={$form.bird_bgp_source_ipv4}
|
|
placeholder="198.51.100.11"
|
|
/>
|
|
</FormField>
|
|
|
|
<FormField
|
|
id="bird-bgp-source-ipv6"
|
|
label="BGP source IPv6 (bird_bgp_source_ipv6)"
|
|
error={$errors.bird_bgp_source_ipv6?.[0]}
|
|
>
|
|
<Input
|
|
id="bird-bgp-source-ipv6"
|
|
bind:value={$form.bird_bgp_source_ipv6}
|
|
placeholder="2001:db8::11"
|
|
/>
|
|
</FormField>
|
|
</div>
|
|
|
|
{#if hasValidationErrors}
|
|
<p class="text-sm text-destructive">
|
|
Есть ошибки в полях. Исправьте их, чтобы сохранить изменения.
|
|
</p>
|
|
{/if}
|
|
|
|
<Button onclick={save} disabled={!canSave}>
|
|
<Save />
|
|
{saving ? 'Сохранение…' : 'Применить параметры'}
|
|
</Button>
|
|
{/if}
|
|
</CardContent>
|
|
</Card>
|