Files
EvoBGP/web/src/lib/components/operations/OperationsDiffTab.svelte
T
Denozordec 88226f6dd9
CI / changes (push) Successful in 6s
CI / openapi (push) Has been skipped
CI / go (push) Has been skipped
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, , evobgp-web) (push) Successful in 1m2s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, evobgp-all, evobgp-web-all) (push) Successful in 1m7s
CI / docker-bird (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / docker-go-prime (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
feat: refactor operations page to enhance UI and component structure. Remove unused card components and integrate OperationsQuickActions for improved quick action handling. Update tab layout for better responsiveness and user experience.
2026-04-06 22:29:32 +07:00

90 lines
3.3 KiB
Svelte

<script lang="ts">
import type { RevisionDiff, RevisionRow } from '$lib/api/types.js';
import { Button } from '$lib/components/ui/button/index.js';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '$lib/components/ui/card/index.js';
import { ScrollArea } from '$lib/components/ui/scroll-area/index.js';
type Props = {
revisions: RevisionRow[];
diffRevA: string;
diffRevB: string;
diffData: RevisionDiff | null;
diffLoading: boolean;
onDiffRevAChange: (value: string) => void;
onDiffRevBChange: (value: string) => void;
onLoadDiff: () => void;
formatDate: (d?: string | null) => string;
};
let {
revisions,
diffRevA,
diffRevB,
diffData,
diffLoading,
onDiffRevAChange,
onDiffRevBChange,
onLoadDiff,
formatDate
}: Props = $props();
</script>
<Card>
<CardHeader>
<CardTitle class="text-base">Сравнение ревизий</CardTitle>
<CardDescription>Выберите ID двух ревизий для сравнения</CardDescription>
</CardHeader>
<CardContent class="space-y-4">
<div class="flex flex-col gap-2 sm:flex-row">
<select
value={diffRevA}
onchange={(e) => onDiffRevAChange((e.currentTarget as HTMLSelectElement).value)}
class="border-border bg-background h-8 min-w-0 flex-1 rounded-md border px-2 text-sm"
>
<option value="">Ревизия A</option>
{#each revisions as rev (rev.id)}
<option value={rev.id}>{rev.id.slice(0, 8)} ({formatDate(rev.created_at)})</option>
{/each}
</select>
<select
value={diffRevB}
onchange={(e) => onDiffRevBChange((e.currentTarget as HTMLSelectElement).value)}
class="border-border bg-background h-8 min-w-0 flex-1 rounded-md border px-2 text-sm"
>
<option value="">Ревизия B</option>
{#each revisions as rev (rev.id)}
<option value={rev.id}>{rev.id.slice(0, 8)} ({formatDate(rev.created_at)})</option>
{/each}
</select>
<Button size="sm" class="shrink-0 self-start sm:self-auto" onclick={onLoadDiff} disabled={diffLoading}>
{diffLoading ? 'Загрузка…' : 'Сравнить'}
</Button>
</div>
{#if diffData}
<div class="grid gap-3 sm:grid-cols-2">
<div>
<p class="mb-2 text-sm font-medium text-green-600">+ Добавлено ({diffData.added?.length ?? 0})</p>
<ScrollArea class="max-h-64 rounded border p-2">
{#each diffData.added ?? [] as p, idx (`added-${idx}-${typeof p === 'string' ? p : (p as { prefix?: string }).prefix ?? 'item'}`)}
<p class="font-mono text-xs break-all">{typeof p === 'string' ? p : (p as { prefix?: string }).prefix ?? JSON.stringify(p)}</p>
{:else}
<p class="text-muted-foreground text-xs">Нет изменений</p>
{/each}
</ScrollArea>
</div>
<div>
<p class="mb-2 text-sm font-medium text-red-600">- Удалено ({diffData.removed?.length ?? 0})</p>
<ScrollArea class="max-h-64 rounded border p-2">
{#each diffData.removed ?? [] as p, idx (`removed-${idx}-${typeof p === 'string' ? p : (p as { prefix?: string }).prefix ?? 'item'}`)}
<p class="font-mono text-xs break-all">{typeof p === 'string' ? p : (p as { prefix?: string }).prefix ?? JSON.stringify(p)}</p>
{:else}
<p class="text-muted-foreground text-xs">Нет изменений</p>
{/each}
</ScrollArea>
</div>
</div>
{/if}
</CardContent>
</Card>