From 80965adc0c74ce2afe29a7498da68113335ed207 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Mon, 6 Apr 2026 01:35:13 +0700 Subject: [PATCH] feat: add enabled state to BGP peer types and UI. Implement peer enabling toggle in the network page, allowing users to enable or disable peers during creation and editing. Update relevant API calls and UI components to reflect the new functionality. --- web/src/lib/api/types.ts | 2 + web/src/routes/network/+page.svelte | 61 ++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/web/src/lib/api/types.ts b/web/src/lib/api/types.ts index 236f652..a6a5a35 100644 --- a/web/src/lib/api/types.ts +++ b/web/src/lib/api/types.ts @@ -123,6 +123,7 @@ export type PeerRow = { name?: string; neighbor: string; remote_asn?: number; + enabled?: boolean; session_state: string; bgp_speaker_id: string | null; }; @@ -131,6 +132,7 @@ export type BgpPeerCreate = { neighbor: string; remote_asn: number; bgp_speaker_id?: string | null; + enabled?: boolean; }; export type BgpPeerPatch = Partial; diff --git a/web/src/routes/network/+page.svelte b/web/src/routes/network/+page.svelte index 3ab4bc6..4198021 100644 --- a/web/src/routes/network/+page.svelte +++ b/web/src/routes/network/+page.svelte @@ -41,6 +41,7 @@ TableHeader, TableRow } from '$lib/components/ui/table/index.js'; + import { Switch } from '$lib/components/ui/switch/index.js'; import { toast } from 'svelte-sonner'; import Plus from '@lucide/svelte/icons/plus'; import Pencil from '@lucide/svelte/icons/pencil'; @@ -56,9 +57,11 @@ let peerForm = $state({ neighbor: '', remote_asn: 0, - bgp_speaker_id: null + bgp_speaker_id: null, + enabled: true }); let peerSaving = $state(false); + let peerToggleId = $state(null); let peerDeleteTarget = $state(null); // --- Speakers --- @@ -93,14 +96,31 @@ // --- Peer actions --- function openPeerCreate() { peerEdit = null; - peerForm = { neighbor: '', remote_asn: 0, bgp_speaker_id: null }; + peerForm = { neighbor: '', remote_asn: 0, bgp_speaker_id: null, enabled: true }; peerDialog = true; } function openPeerEdit(p: PeerRow) { peerEdit = p; - peerForm = { neighbor: p.neighbor, remote_asn: p.remote_asn ?? 0, bgp_speaker_id: p.bgp_speaker_id }; + peerForm = { + neighbor: p.neighbor, + remote_asn: p.remote_asn ?? 0, + bgp_speaker_id: p.bgp_speaker_id, + enabled: p.enabled !== false + }; peerDialog = true; } + async function setPeerEnabled(p: PeerRow, enabled: boolean) { + peerToggleId = p.id; + try { + await apiMutate(`/v1/peers/${p.id}`, 'PATCH', { enabled }); + toast.success(enabled ? 'Пир включён' : 'Пир отключён'); + await loadAll(); + } catch (e) { + toast.error(e instanceof Error ? e.message : String(e)); + } finally { + peerToggleId = null; + } + } async function savePeer() { if (!peerForm.neighbor || !peerForm.remote_asn) { toast.error('Укажите адрес и ASN'); @@ -112,8 +132,10 @@ await apiMutate(`/v1/peers/${peerEdit.id}`, 'PATCH', peerForm); toast.success('Пир обновлён'); } else { - // API: omitted "enabled" decodes as false in Go; default new peers to enabled. - await apiMutate('/v1/peers', 'POST', { ...peerForm, enabled: true }); + await apiMutate('/v1/peers', 'POST', { + ...peerForm, + enabled: peerForm.enabled !== false + }); toast.success('Пир создан'); } peerDialog = false; @@ -218,6 +240,7 @@ Адрес Remote ASN + Вкл. Состояние сессии Спикер @@ -228,6 +251,14 @@ {p.neighbor} {p.remote_asn ?? '—'} + + setPeerEnabled(p, v)} + /> + {p.session_state || '—'} @@ -241,7 +272,7 @@ {:else} - + {peersLoading ? 'Загрузка…' : 'Нет пиров.'} @@ -328,6 +359,24 @@ +
+
+ +

+ Выключенный пир не попадает в конфиг BIRD до следующей ревизии. +

+
+ { + peerForm = { ...peerForm, enabled: v }; + }} + /> +