Files
EvoBGP/web/src/lib/components/operations/OperationsQuickActions.svelte
T
Denozordec 53fd527a6d
CI / changes (push) Successful in 6s
CI / openapi (push) Has been skipped
CI / go (push) Successful in 43s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, , evobgp-web) (push) Successful in 1m8s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, evobgp-all, evobgp-web-all) (push) Successful in 1m9s
CI / docker-bird (push) Has been skipped
CI / bird2 (push) Successful in 17s
CI / docker-go-prime (push) Successful in 23s
CI / docker-go (deploy/docker/evobgp-agent/Dockerfile, , evobgp-agent) (push) Successful in 1m5s
CI / docker-go (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, , evobgp-all) (push) Successful in 2m29s
CI / docker-go (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, , evobgp-api) (push) Successful in 1m31s
CI / docker-go (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, , evobgp-deploy) (push) Successful in 1m27s
CI / docker-go (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, , evobgp-ingest) (push) Successful in 1m27s
CI / docker-go (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, , evobgp-node) (push) Successful in 1m15s
CI / docker-go (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, , evobgp-render) (push) Successful in 1m28s
CI / docker-go (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, , evobgp-scheduler) (push) Successful in 1m30s
feat: enhance community label handling and improve UI localization across operations pages. Introduce community label mapping for better readability in job logs and update various components to reflect Russian translations, enhancing user experience and consistency in the interface.
2026-04-07 00:58:15 +07:00

158 lines
5.4 KiB
Svelte

<script lang="ts">
import type { BirdStatus } from '$lib/api/types.js';
import { Badge } from '$lib/components/ui/badge/index.js';
import { Button } from '$lib/components/ui/button/index.js';
import { Card } from '$lib/components/ui/card/index.js';
import RefreshCw from '@lucide/svelte/icons/refresh-cw';
import Play from '@lucide/svelte/icons/play';
import RotateCcw from '@lucide/svelte/icons/rotate-ccw';
import Bird from '@lucide/svelte/icons/bird';
import { cn } from '$lib/utils.js';
type Props = {
applying: boolean;
reloading: boolean;
birdLoading: boolean;
birdStatus: BirdStatus | null;
onApply: () => void;
onReload: () => void;
onRefreshBirdStatus: () => void;
onOpenBirdProtocols: () => void;
birdHealthyBadgeVariant: (h: boolean | null | undefined) => 'default' | 'secondary' | 'outline' | 'destructive';
birdHealthyShortLabel: (h: boolean | null | undefined) => string;
};
let {
applying,
reloading,
birdLoading,
birdStatus,
onApply,
onReload,
onRefreshBirdStatus,
onOpenBirdProtocols,
birdHealthyBadgeVariant,
birdHealthyShortLabel
}: Props = $props();
</script>
<div class="grid grid-cols-1 items-stretch gap-3 sm:grid-cols-2 xl:grid-cols-3">
<Card
class={cn(
'min-w-0 overflow-hidden border-l-4 border-l-chart-1 bg-chart-1/5 p-4 shadow-sm'
)}
>
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div class="flex min-w-0 flex-1 gap-3">
<div
class="bg-chart-1/20 flex size-11 shrink-0 items-center justify-center rounded-xl"
aria-hidden="true"
>
<Play class="text-chart-1 size-5" />
</div>
<div class="min-w-0 flex-1 space-y-1">
<p class="font-semibold">Применить ко всем спикерам</p>
<p class="text-muted-foreground max-w-[42ch] text-sm">Применить текущую конфигурацию на всех BIRD-спикерах</p>
</div>
</div>
<Button class="w-full shrink-0 self-start sm:w-auto sm:self-auto" onclick={onApply} disabled={applying}>
<Play class="size-4" aria-hidden="true" />
Применить
</Button>
</div>
</Card>
<Card
class={cn(
'min-w-0 overflow-hidden border-l-4 border-l-chart-4 bg-chart-4/5 p-4 shadow-sm'
)}
>
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div class="flex min-w-0 flex-1 gap-3">
<div
class="bg-chart-4/20 flex size-11 shrink-0 items-center justify-center rounded-xl"
aria-hidden="true"
>
<RotateCcw class="text-chart-4 size-5" />
</div>
<div class="min-w-0 flex-1 space-y-1">
<p class="font-semibold">Перезагрузка BIRD</p>
<p class="text-muted-foreground max-w-[42ch] text-sm">Перезагрузить конфигурацию BIRD на всех спикерах</p>
</div>
</div>
<Button
variant="outline"
class="w-full shrink-0 self-start sm:w-auto sm:self-auto"
onclick={onReload}
disabled={reloading}
>
<RotateCcw class="size-4" aria-hidden="true" />
Перезагрузить
</Button>
</div>
</Card>
<Card
class={cn(
'min-w-0 overflow-hidden border-l-4 border-l-info bg-info/10 p-4 shadow-sm sm:col-span-2 xl:col-span-1'
)}
>
<div class="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
<div class="min-w-0 flex-1 space-y-1">
<div class="flex flex-wrap items-center gap-2">
<div
class="bg-info/15 mr-0.5 flex size-9 items-center justify-center rounded-lg"
aria-hidden="true"
>
<Bird class="text-info size-5 shrink-0" />
</div>
<p class="font-semibold">Состояние BIRD</p>
{#if birdStatus}
<Badge variant={birdHealthyBadgeVariant(birdStatus.healthy)}>{birdHealthyShortLabel(birdStatus.healthy)}</Badge>
{/if}
</div>
<p class="text-foreground/80 max-w-[56ch] text-sm">
Локально на хосте API: <code class="bg-muted rounded px-1 text-xs">birdc show protocols</code>. Не заменяет мониторинг спикеров.
</p>
{#if birdLoading}
<p class="text-foreground/80 text-sm">Загрузка…</p>
{:else if birdStatus}
{#if !birdStatus.birdc_configured}
<p class="text-foreground/80 text-sm">{birdStatus.message ?? 'birdc не настроен на API.'}</p>
{:else if birdStatus.error}
<p class="text-destructive text-sm">{birdStatus.error}</p>
{:else}
<p class="text-sm">
<span class="text-muted-foreground">BGP сессий:</span>
<span class="font-medium">{birdStatus.bgp_established}</span>
<span class="text-muted-foreground">/</span>
<span class="font-medium">{birdStatus.bgp_sessions_total}</span>
<span class="text-muted-foreground"> установлено / всего</span>
</p>
{/if}
{:else}
<p class="text-foreground/80 text-sm">Статус не загружен</p>
{/if}
</div>
<div class="flex w-full shrink-0 flex-wrap gap-2 sm:w-auto sm:flex-col sm:items-stretch">
<Button
variant="outline"
size="sm"
class="w-full sm:w-auto"
onclick={onRefreshBirdStatus}
disabled={birdLoading}
>
<RefreshCw class={birdLoading ? 'size-3.5 animate-spin' : 'size-3.5'} />
Обновить
</Button>
{#if birdStatus?.birdc_configured && birdStatus.protocols_excerpt}
<Button variant="ghost" size="sm" class="w-full sm:w-auto" onclick={onOpenBirdProtocols}>
Вывод birdc
</Button>
{/if}
</div>
</div>
</Card>
</div>