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.
CI / changes (push) Successful in 6s
CI / openapi (push) Has been skipped
CI / go (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, , evobgp-web) (push) Successful in 1m0s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, evobgp-all, evobgp-web-all) (push) Successful in 1m1s
CI / docker-bird (push) Has been skipped
CI / docker-go (deploy/docker/evobgp-agent/Dockerfile, , evobgp-agent) (push) Has been skipped
CI / docker-go (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, , evobgp-all) (push) Has been skipped
CI / docker-go (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, , evobgp-api) (push) Has been skipped
CI / docker-go (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, , evobgp-deploy) (push) Has been skipped
CI / docker-go (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, , evobgp-ingest) (push) Has been skipped
CI / docker-go (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, , evobgp-node) (push) Has been skipped
CI / docker-go (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, , evobgp-render) (push) Has been skipped
CI / docker-go (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, , evobgp-scheduler) (push) Has been skipped
CI / changes (push) Successful in 6s
CI / openapi (push) Has been skipped
CI / go (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, , evobgp-web) (push) Successful in 1m0s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, evobgp-all, evobgp-web-all) (push) Successful in 1m1s
CI / docker-bird (push) Has been skipped
CI / docker-go (deploy/docker/evobgp-agent/Dockerfile, , evobgp-agent) (push) Has been skipped
CI / docker-go (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, , evobgp-all) (push) Has been skipped
CI / docker-go (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, , evobgp-api) (push) Has been skipped
CI / docker-go (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, , evobgp-deploy) (push) Has been skipped
CI / docker-go (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, , evobgp-ingest) (push) Has been skipped
CI / docker-go (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, , evobgp-node) (push) Has been skipped
CI / docker-go (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, , evobgp-render) (push) Has been skipped
CI / docker-go (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, , evobgp-scheduler) (push) Has been skipped
This commit is contained in:
@@ -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<BgpPeerCreate>;
|
||||
|
||||
|
||||
@@ -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<BgpPeerCreate & { bgp_speaker_id?: string | null }>({
|
||||
neighbor: '',
|
||||
remote_asn: 0,
|
||||
bgp_speaker_id: null
|
||||
bgp_speaker_id: null,
|
||||
enabled: true
|
||||
});
|
||||
let peerSaving = $state(false);
|
||||
let peerToggleId = $state<string | null>(null);
|
||||
let peerDeleteTarget = $state<PeerRow | null>(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 @@
|
||||
<TableRow>
|
||||
<TableHead>Адрес</TableHead>
|
||||
<TableHead>Remote ASN</TableHead>
|
||||
<TableHead class="w-[4.5rem] text-center">Вкл.</TableHead>
|
||||
<TableHead>Состояние сессии</TableHead>
|
||||
<TableHead>Спикер</TableHead>
|
||||
<TableHead class="w-20"></TableHead>
|
||||
@@ -228,6 +251,14 @@
|
||||
<TableRow>
|
||||
<TableCell class="font-mono">{p.neighbor}</TableCell>
|
||||
<TableCell class="font-mono">{p.remote_asn ?? '—'}</TableCell>
|
||||
<TableCell class="text-center">
|
||||
<Switch
|
||||
size="sm"
|
||||
checked={p.enabled !== false}
|
||||
disabled={peersLoading || peerToggleId === p.id}
|
||||
onCheckedChange={(v) => setPeerEnabled(p, v)}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant={sessionBadge(p.session_state)}>{p.session_state || '—'}</Badge>
|
||||
</TableCell>
|
||||
@@ -241,7 +272,7 @@
|
||||
</TableRow>
|
||||
{:else}
|
||||
<TableRow>
|
||||
<TableCell colspan={5} class="text-muted-foreground text-center py-8">
|
||||
<TableCell colspan={6} class="text-muted-foreground text-center py-8">
|
||||
{peersLoading ? 'Загрузка…' : 'Нет пиров.'}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -328,6 +359,24 @@
|
||||
<Label for="p-speaker">Спикер (ID, опционально)</Label>
|
||||
<Input id="p-speaker" placeholder="speaker-id" bind:value={peerForm.bgp_speaker_id} />
|
||||
</div>
|
||||
<div
|
||||
class="border-border bg-muted/30 flex flex-row items-center justify-between gap-4 rounded-lg border p-3"
|
||||
>
|
||||
<div class="grid min-w-0 flex-1 gap-1 pr-2">
|
||||
<Label for="p-enabled" class="text-foreground leading-snug">Включён</Label>
|
||||
<p class="text-muted-foreground text-xs leading-snug">
|
||||
Выключенный пир не попадает в конфиг BIRD до следующей ревизии.
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
id="p-enabled"
|
||||
class="shrink-0"
|
||||
checked={peerForm.enabled !== false}
|
||||
onCheckedChange={(v) => {
|
||||
peerForm = { ...peerForm, enabled: v };
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onclick={() => (peerDialog = false)}>Отмена</Button>
|
||||
|
||||
Reference in New Issue
Block a user