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
90 lines
3.3 KiB
Svelte
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>
|