Files
GitLite/src/lib/components/ComparePanel.svelte
T
2026-06-27 23:08:19 +02:00

122 lines
3.8 KiB
Svelte

<script lang="ts">
import { ArrowRight, GitCompare, LoaderCircle } from "@lucide/svelte";
import type { GitCommit, GitCommitComparison } from "../types";
interface Props {
commits: GitCommit[];
hasRepository: boolean;
isBusy: boolean;
compareFrom: string;
compareTo: string;
canCompare: boolean;
comparison: GitCommitComparison | null;
operation: string;
onCompareFromChange: (val: string) => void;
onCompareToChange: (val: string) => void;
onCompare: () => void;
onOpenDialog: () => void;
}
let {
commits = [],
hasRepository = false,
isBusy = false,
compareFrom = "",
compareTo = "",
canCompare = false,
comparison = null,
operation = "",
onCompareFromChange = () => {},
onCompareToChange = () => {},
onCompare = () => {},
onOpenDialog = () => {},
}: Props = $props();
function commitOptionLabel(item: GitCommit): string {
return `${item.short_hash} - ${item.summary}`;
}
function handleSubmit(event: SubmitEvent) {
event.preventDefault();
onCompare();
}
</script>
<section class="compare-panel panel" aria-label="Compare commits">
<div class="section-head">
<div>
<span class="eyebrow">Compare</span>
<h2 class="mt-0.5 text-ink text-base font-bold leading-tight">Commits</h2>
</div>
{#if comparison}
<span class="pill pill-count">{comparison.files.length} files</span>
{/if}
</div>
{#if !hasRepository}
<div class="blank-state">No repository loaded.</div>
{:else if commits.length < 2}
<div class="blank-state">At least two commits are needed to compare.</div>
{:else}
<form class="compare-form" onsubmit={handleSubmit}>
<label class="compare-field">
<span>From (older)</span>
<select
value={compareFrom}
onchange={(e) => onCompareFromChange((e.target as HTMLSelectElement).value)}
disabled={isBusy}
>
<option value="" disabled>Select a commit</option>
{#each commits as item (item.hash)}
<option value={item.hash}>{commitOptionLabel(item)}</option>
{/each}
</select>
</label>
<ArrowRight class="compare-arrow" size={18} aria-hidden="true" />
<label class="compare-field">
<span>To (newer)</span>
<select
value={compareTo}
onchange={(e) => onCompareToChange((e.target as HTMLSelectElement).value)}
disabled={isBusy}
>
<option value="" disabled>Select a commit</option>
{#each commits as item (item.hash)}
<option value={item.hash}>{commitOptionLabel(item)}</option>
{/each}
</select>
</label>
<button class="btn-primary" type="submit" disabled={!canCompare}>
{#if operation === "Comparing commits"}
<LoaderCircle class="spin" size={16} aria-hidden="true" />
{:else}
<GitCompare size={16} aria-hidden="true" />
{/if}
Compare
</button>
</form>
{#if compareFrom && compareTo && compareFrom === compareTo}
<div class="blank-state">Select two different commits to compare.</div>
{:else if comparison}
<div class="compare-summary">
<div class="compare-range">
<span class="hash">{comparison.from_short}</span>
<ArrowRight size={15} aria-hidden="true" />
<span class="hash">{comparison.to_short}</span>
<span class="compare-count">{comparison.files.length} changed files</span>
</div>
<button type="button" onclick={onOpenDialog} disabled={isBusy}>
<GitCompare size={15} aria-hidden="true" />
View comparison
</button>
</div>
{:else}
<div class="blank-state">Pick two commits and run a comparison.</div>
{/if}
{/if}
</section>