chore(FEEDBACK-0001): linting
This commit is contained in:
@@ -49,79 +49,79 @@ Implement the main web interface for managing repositories. Built with SvelteKit
|
||||
```svelte
|
||||
<!-- src/lib/components/RepositoryCard.svelte -->
|
||||
<script lang="ts">
|
||||
import type { Repository } from '$lib/types';
|
||||
import type { Repository } from '$lib/types';
|
||||
|
||||
let { repo, onReindex, onDelete } = $props<{
|
||||
repo: Repository;
|
||||
onReindex: (id: string) => void;
|
||||
onDelete: (id: string) => void;
|
||||
}>();
|
||||
let { repo, onReindex, onDelete } = $props<{
|
||||
repo: Repository;
|
||||
onReindex: (id: string) => void;
|
||||
onDelete: (id: string) => void;
|
||||
}>();
|
||||
|
||||
const stateColors = {
|
||||
pending: 'bg-gray-100 text-gray-600',
|
||||
indexing: 'bg-blue-100 text-blue-700',
|
||||
indexed: 'bg-green-100 text-green-700',
|
||||
error: 'bg-red-100 text-red-700',
|
||||
};
|
||||
const stateColors = {
|
||||
pending: 'bg-gray-100 text-gray-600',
|
||||
indexing: 'bg-blue-100 text-blue-700',
|
||||
indexed: 'bg-green-100 text-green-700',
|
||||
error: 'bg-red-100 text-red-700'
|
||||
};
|
||||
|
||||
const stateLabels = {
|
||||
pending: 'Pending',
|
||||
indexing: 'Indexing...',
|
||||
indexed: 'Indexed',
|
||||
error: 'Error',
|
||||
};
|
||||
const stateLabels = {
|
||||
pending: 'Pending',
|
||||
indexing: 'Indexing...',
|
||||
indexed: 'Indexed',
|
||||
error: 'Error'
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="rounded-xl border border-gray-200 bg-white p-5 shadow-sm">
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900">{repo.title}</h3>
|
||||
<p class="mt-0.5 font-mono text-sm text-gray-500">{repo.id}</p>
|
||||
</div>
|
||||
<span class="rounded-full px-2.5 py-0.5 text-xs font-medium {stateColors[repo.state]}">
|
||||
{stateLabels[repo.state]}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900">{repo.title}</h3>
|
||||
<p class="mt-0.5 font-mono text-sm text-gray-500">{repo.id}</p>
|
||||
</div>
|
||||
<span class="rounded-full px-2.5 py-0.5 text-xs font-medium {stateColors[repo.state]}">
|
||||
{stateLabels[repo.state]}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{#if repo.description}
|
||||
<p class="mt-2 line-clamp-2 text-sm text-gray-600">{repo.description}</p>
|
||||
{/if}
|
||||
{#if repo.description}
|
||||
<p class="mt-2 line-clamp-2 text-sm text-gray-600">{repo.description}</p>
|
||||
{/if}
|
||||
|
||||
<div class="mt-4 flex gap-4 text-sm text-gray-500">
|
||||
<span>{repo.totalSnippets.toLocaleString()} snippets</span>
|
||||
<span>·</span>
|
||||
<span>Trust: {repo.trustScore.toFixed(1)}/10</span>
|
||||
{#if repo.stars}
|
||||
<span>·</span>
|
||||
<span>★ {repo.stars.toLocaleString()}</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="mt-4 flex gap-4 text-sm text-gray-500">
|
||||
<span>{repo.totalSnippets.toLocaleString()} snippets</span>
|
||||
<span>·</span>
|
||||
<span>Trust: {repo.trustScore.toFixed(1)}/10</span>
|
||||
{#if repo.stars}
|
||||
<span>·</span>
|
||||
<span>★ {repo.stars.toLocaleString()}</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if repo.state === 'error'}
|
||||
<p class="mt-2 text-xs text-red-600">Indexing failed. Check jobs for details.</p>
|
||||
{/if}
|
||||
{#if repo.state === 'error'}
|
||||
<p class="mt-2 text-xs text-red-600">Indexing failed. Check jobs for details.</p>
|
||||
{/if}
|
||||
|
||||
<div class="mt-4 flex gap-2">
|
||||
<button
|
||||
onclick={() => onReindex(repo.id)}
|
||||
class="rounded-lg bg-blue-600 px-3 py-1.5 text-sm text-white hover:bg-blue-700"
|
||||
disabled={repo.state === 'indexing'}
|
||||
>
|
||||
{repo.state === 'indexing' ? 'Indexing...' : 'Re-index'}
|
||||
</button>
|
||||
<a
|
||||
href="/repos/{encodeURIComponent(repo.id)}"
|
||||
class="rounded-lg border border-gray-200 px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-50"
|
||||
>
|
||||
Details
|
||||
</a>
|
||||
<button
|
||||
onclick={() => onDelete(repo.id)}
|
||||
class="ml-auto rounded-lg px-3 py-1.5 text-sm text-red-600 hover:bg-red-50"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-4 flex gap-2">
|
||||
<button
|
||||
onclick={() => onReindex(repo.id)}
|
||||
class="rounded-lg bg-blue-600 px-3 py-1.5 text-sm text-white hover:bg-blue-700"
|
||||
disabled={repo.state === 'indexing'}
|
||||
>
|
||||
{repo.state === 'indexing' ? 'Indexing...' : 'Re-index'}
|
||||
</button>
|
||||
<a
|
||||
href="/repos/{encodeURIComponent(repo.id)}"
|
||||
class="rounded-lg border border-gray-200 px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-50"
|
||||
>
|
||||
Details
|
||||
</a>
|
||||
<button
|
||||
onclick={() => onDelete(repo.id)}
|
||||
class="ml-auto rounded-lg px-3 py-1.5 text-sm text-red-600 hover:bg-red-50"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -132,98 +132,104 @@ Implement the main web interface for managing repositories. Built with SvelteKit
|
||||
```svelte
|
||||
<!-- src/lib/components/AddRepositoryModal.svelte -->
|
||||
<script lang="ts">
|
||||
let { onClose, onAdded } = $props<{
|
||||
onClose: () => void;
|
||||
onAdded: () => void;
|
||||
}>();
|
||||
let { onClose, onAdded } = $props<{
|
||||
onClose: () => void;
|
||||
onAdded: () => void;
|
||||
}>();
|
||||
|
||||
let source = $state<'github' | 'local'>('github');
|
||||
let sourceUrl = $state('');
|
||||
let githubToken = $state('');
|
||||
let loading = $state(false);
|
||||
let error = $state<string | null>(null);
|
||||
let source = $state<'github' | 'local'>('github');
|
||||
let sourceUrl = $state('');
|
||||
let githubToken = $state('');
|
||||
let loading = $state(false);
|
||||
let error = $state<string | null>(null);
|
||||
|
||||
async function handleSubmit() {
|
||||
loading = true;
|
||||
error = null;
|
||||
try {
|
||||
const res = await fetch('/api/v1/libs', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ source, sourceUrl, githubToken: githubToken || undefined }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const data = await res.json();
|
||||
throw new Error(data.error ?? 'Failed to add repository');
|
||||
}
|
||||
onAdded();
|
||||
onClose();
|
||||
} catch (e) {
|
||||
error = (e as Error).message;
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
async function handleSubmit() {
|
||||
loading = true;
|
||||
error = null;
|
||||
try {
|
||||
const res = await fetch('/api/v1/libs', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ source, sourceUrl, githubToken: githubToken || undefined })
|
||||
});
|
||||
if (!res.ok) {
|
||||
const data = await res.json();
|
||||
throw new Error(data.error ?? 'Failed to add repository');
|
||||
}
|
||||
onAdded();
|
||||
onClose();
|
||||
} catch (e) {
|
||||
error = (e as Error).message;
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<dialog class="modal" open>
|
||||
<div class="modal-box max-w-md">
|
||||
<h2 class="mb-4 text-lg font-semibold">Add Repository</h2>
|
||||
<div class="modal-box max-w-md">
|
||||
<h2 class="mb-4 text-lg font-semibold">Add Repository</h2>
|
||||
|
||||
<div class="mb-4 flex gap-2">
|
||||
<button
|
||||
class="flex-1 rounded-lg py-2 text-sm {source === 'github' ? 'bg-blue-600 text-white' : 'border border-gray-200 text-gray-700'}"
|
||||
onclick={() => source = 'github'}
|
||||
>GitHub</button>
|
||||
<button
|
||||
class="flex-1 rounded-lg py-2 text-sm {source === 'local' ? 'bg-blue-600 text-white' : 'border border-gray-200 text-gray-700'}"
|
||||
onclick={() => source = 'local'}
|
||||
>Local Path</button>
|
||||
</div>
|
||||
<div class="mb-4 flex gap-2">
|
||||
<button
|
||||
class="flex-1 rounded-lg py-2 text-sm {source === 'github'
|
||||
? 'bg-blue-600 text-white'
|
||||
: 'border border-gray-200 text-gray-700'}"
|
||||
onclick={() => (source = 'github')}>GitHub</button
|
||||
>
|
||||
<button
|
||||
class="flex-1 rounded-lg py-2 text-sm {source === 'local'
|
||||
? 'bg-blue-600 text-white'
|
||||
: 'border border-gray-200 text-gray-700'}"
|
||||
onclick={() => (source = 'local')}>Local Path</button
|
||||
>
|
||||
</div>
|
||||
|
||||
<label class="block">
|
||||
<span class="text-sm font-medium text-gray-700">
|
||||
{source === 'github' ? 'GitHub URL' : 'Absolute Path'}
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
bind:value={sourceUrl}
|
||||
placeholder={source === 'github'
|
||||
? 'https://github.com/facebook/react'
|
||||
: '/home/user/projects/my-sdk'}
|
||||
class="mt-1 w-full rounded-lg border border-gray-300 px-3 py-2 text-sm"
|
||||
/>
|
||||
</label>
|
||||
<label class="block">
|
||||
<span class="text-sm font-medium text-gray-700">
|
||||
{source === 'github' ? 'GitHub URL' : 'Absolute Path'}
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
bind:value={sourceUrl}
|
||||
placeholder={source === 'github'
|
||||
? 'https://github.com/facebook/react'
|
||||
: '/home/user/projects/my-sdk'}
|
||||
class="mt-1 w-full rounded-lg border border-gray-300 px-3 py-2 text-sm"
|
||||
/>
|
||||
</label>
|
||||
|
||||
{#if source === 'github'}
|
||||
<label class="mt-3 block">
|
||||
<span class="text-sm font-medium text-gray-700">GitHub Token (optional, for private repos)</span>
|
||||
<input
|
||||
type="password"
|
||||
bind:value={githubToken}
|
||||
placeholder="ghp_..."
|
||||
class="mt-1 w-full rounded-lg border border-gray-300 px-3 py-2 text-sm"
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
{#if source === 'github'}
|
||||
<label class="mt-3 block">
|
||||
<span class="text-sm font-medium text-gray-700"
|
||||
>GitHub Token (optional, for private repos)</span
|
||||
>
|
||||
<input
|
||||
type="password"
|
||||
bind:value={githubToken}
|
||||
placeholder="ghp_..."
|
||||
class="mt-1 w-full rounded-lg border border-gray-300 px-3 py-2 text-sm"
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
{#if error}
|
||||
<p class="mt-3 text-sm text-red-600">{error}</p>
|
||||
{/if}
|
||||
{#if error}
|
||||
<p class="mt-3 text-sm text-red-600">{error}</p>
|
||||
{/if}
|
||||
|
||||
<div class="mt-6 flex justify-end gap-3">
|
||||
<button onclick={onClose} class="rounded-lg border border-gray-200 px-4 py-2 text-sm">
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onclick={handleSubmit}
|
||||
disabled={loading || !sourceUrl}
|
||||
class="rounded-lg bg-blue-600 px-4 py-2 text-sm text-white disabled:opacity-50"
|
||||
>
|
||||
{loading ? 'Adding...' : 'Add & Index'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-6 flex justify-end gap-3">
|
||||
<button onclick={onClose} class="rounded-lg border border-gray-200 px-4 py-2 text-sm">
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onclick={handleSubmit}
|
||||
disabled={loading || !sourceUrl}
|
||||
class="rounded-lg bg-blue-600 px-4 py-2 text-sm text-white disabled:opacity-50"
|
||||
>
|
||||
{loading ? 'Adding...' : 'Add & Index'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
```
|
||||
|
||||
@@ -234,48 +240,48 @@ Implement the main web interface for managing repositories. Built with SvelteKit
|
||||
```svelte
|
||||
<!-- src/lib/components/IndexingProgress.svelte -->
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import type { IndexingJob } from '$lib/types';
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import type { IndexingJob } from '$lib/types';
|
||||
|
||||
let { jobId } = $props<{ jobId: string }>();
|
||||
let job = $state<IndexingJob | null>(null);
|
||||
let interval: ReturnType<typeof setInterval>;
|
||||
let { jobId } = $props<{ jobId: string }>();
|
||||
let job = $state<IndexingJob | null>(null);
|
||||
let interval: ReturnType<typeof setInterval>;
|
||||
|
||||
async function pollJob() {
|
||||
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') {
|
||||
clearInterval(interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
async function pollJob() {
|
||||
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') {
|
||||
clearInterval(interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
pollJob();
|
||||
interval = setInterval(pollJob, 2000);
|
||||
});
|
||||
onMount(() => {
|
||||
pollJob();
|
||||
interval = setInterval(pollJob, 2000);
|
||||
});
|
||||
|
||||
onDestroy(() => clearInterval(interval));
|
||||
onDestroy(() => clearInterval(interval));
|
||||
</script>
|
||||
|
||||
{#if job}
|
||||
<div class="mt-2">
|
||||
<div class="flex justify-between text-xs text-gray-500">
|
||||
<span>{job.processedFiles} / {job.totalFiles} files</span>
|
||||
<span>{job.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"
|
||||
style="width: {job.progress}%"
|
||||
></div>
|
||||
</div>
|
||||
{#if job.status === 'failed'}
|
||||
<p class="mt-1 text-xs text-red-600">{job.error}</p>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<div class="flex justify-between text-xs text-gray-500">
|
||||
<span>{job.processedFiles} / {job.totalFiles} files</span>
|
||||
<span>{job.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"
|
||||
style="width: {job.progress}%"
|
||||
></div>
|
||||
</div>
|
||||
{#if job.status === 'failed'}
|
||||
<p class="mt-1 text-xs text-red-600">{job.error}</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
```
|
||||
|
||||
@@ -288,9 +294,9 @@ Implement the main web interface for managing repositories. Built with SvelteKit
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ fetch }) => {
|
||||
const res = await fetch('/api/v1/libs');
|
||||
const data = await res.json();
|
||||
return { repositories: data.libraries };
|
||||
const res = await fetch('/api/v1/libs');
|
||||
const data = await res.json();
|
||||
return { repositories: data.libraries };
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user