feat(TRUEREF-0015): implement web UI repository dashboard
- Repository list with state badges, stats, and action buttons - Add repository modal for GitHub URLs and local paths - Live indexing progress bar polling every 2s - Confirm dialog for destructive actions - Repository detail page with versions and recent jobs - Settings page placeholder Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
62
src/lib/components/IndexingProgress.svelte
Normal file
62
src/lib/components/IndexingProgress.svelte
Normal file
@@ -0,0 +1,62 @@
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import type { IndexingJob } from '$lib/types';
|
||||
|
||||
let { jobId }: { jobId: string } = $props();
|
||||
|
||||
let job = $state<IndexingJob | null>(null);
|
||||
let interval: ReturnType<typeof setInterval> | undefined;
|
||||
|
||||
async function pollJob() {
|
||||
try {
|
||||
const res = await fetch(`/api/v1/jobs/${jobId}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
job = data.job;
|
||||
if (job?.status === 'done' || job?.status === 'failed') {
|
||||
if (interval !== undefined) {
|
||||
clearInterval(interval);
|
||||
interval = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// ignore polling errors
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
pollJob();
|
||||
interval = setInterval(pollJob, 2000);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (interval !== undefined) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
});
|
||||
|
||||
const progress = $derived(job?.progress ?? 0);
|
||||
const processedFiles = $derived(job?.processedFiles ?? 0);
|
||||
const totalFiles = $derived(job?.totalFiles ?? 0);
|
||||
</script>
|
||||
|
||||
{#if job}
|
||||
<div class="mt-2">
|
||||
<div class="flex justify-between text-xs text-gray-500">
|
||||
<span>{processedFiles} / {totalFiles} files</span>
|
||||
<span>{progress}%</span>
|
||||
</div>
|
||||
<div class="mt-1 h-1.5 w-full rounded-full bg-gray-200">
|
||||
<div
|
||||
class="h-1.5 rounded-full bg-blue-600 transition-all duration-300"
|
||||
style="width: {progress}%"
|
||||
></div>
|
||||
</div>
|
||||
{#if job.status === 'done'}
|
||||
<p class="mt-1 text-xs text-green-600">Indexing complete.</p>
|
||||
{:else if job.status === 'failed'}
|
||||
<p class="mt-1 text-xs text-red-600">{job.error ?? 'Indexing failed.'}</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
Reference in New Issue
Block a user