From 569a13e1b16400eea16a8fe8f8661664726e381e Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 5 Apr 2026 21:39:11 +0200 Subject: [PATCH] feat(transcription): show block numbers on PDF annotation overlays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add blockNumbers prop through AnnotationLayer → PdfViewer → DocumentViewer. Each turquoise annotation rectangle now shows a numbered badge (top-left, matching the block card number in the right panel). Block numbers are derived from sorted transcriptionBlocks, mapped by annotationId, creating a visual link between PDF regions and block cards. Co-Authored-By: Claude Sonnet 4.6 --- .../src/lib/components/AnnotationLayer.svelte | 29 ++++++++++++++++++- .../src/lib/components/DocumentViewer.svelte | 3 ++ frontend/src/lib/components/PdfViewer.svelte | 3 ++ .../src/routes/documents/[id]/+page.svelte | 9 ++++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/frontend/src/lib/components/AnnotationLayer.svelte b/frontend/src/lib/components/AnnotationLayer.svelte index 2db06063..ed8ce6d7 100644 --- a/frontend/src/lib/components/AnnotationLayer.svelte +++ b/frontend/src/lib/components/AnnotationLayer.svelte @@ -12,12 +12,14 @@ let { annotations = [], canDraw, color, + blockNumbers = {}, onDraw, onAnnotationClick }: { annotations: Annotation[]; canDraw: boolean; color: string; + blockNumbers?: Record; onDraw: (rect: DrawRect) => void; onAnnotationClick?: (id: string) => void; } = $props(); @@ -125,7 +127,32 @@ const containerStyle = $derived( cursor: pointer; transition: background-color 0.15s ease, box-shadow 0.15s ease; " - > + > + {#if blockNumbers[annotation.id]} +
+ {blockNumbers[annotation.id]} +
+ {/if} + {/each} {#if drawRect && drawRect.width > 0} diff --git a/frontend/src/lib/components/DocumentViewer.svelte b/frontend/src/lib/components/DocumentViewer.svelte index 2f330010..275a27d4 100644 --- a/frontend/src/lib/components/DocumentViewer.svelte +++ b/frontend/src/lib/components/DocumentViewer.svelte @@ -17,6 +17,7 @@ type Props = { isLoading: boolean; error: string; transcribeMode?: boolean; + blockNumbers?: Record; activeAnnotationId: string | null; onAnnotationClick: (id: string) => void; onTranscriptionDraw?: (rect: DrawRect) => void; @@ -28,6 +29,7 @@ let { isLoading, error, transcribeMode = false, + blockNumbers = {}, activeAnnotationId = $bindable(), onAnnotationClick, onTranscriptionDraw @@ -83,6 +85,7 @@ let { url={fileUrl} documentId={doc.id} transcribeMode={transcribeMode} + blockNumbers={blockNumbers} bind:activeAnnotationId={activeAnnotationId} onAnnotationClick={onAnnotationClick} onTranscriptionDraw={onTranscriptionDraw} diff --git a/frontend/src/lib/components/PdfViewer.svelte b/frontend/src/lib/components/PdfViewer.svelte index 96658b15..f47dd422 100644 --- a/frontend/src/lib/components/PdfViewer.svelte +++ b/frontend/src/lib/components/PdfViewer.svelte @@ -11,6 +11,7 @@ let { url, documentId = '', transcribeMode = false, + blockNumbers = {}, activeAnnotationId = $bindable(null), onAnnotationClick, onTranscriptionDraw, @@ -19,6 +20,7 @@ let { url: string; documentId?: string; transcribeMode?: boolean; + blockNumbers?: Record; activeAnnotationId?: string | null; onAnnotationClick?: (id: string) => void; onTranscriptionDraw?: (rect: DrawRect) => void; @@ -424,6 +426,7 @@ function zoomOut() { annotations={visibleAnnotations.filter((a) => a.pageNumber === currentPage)} canDraw={transcribeMode} color={TRANSCRIPTION_COLOR} + blockNumbers={blockNumbers} onDraw={handleDraw} onAnnotationClick={handleAnnotationClick} /> diff --git a/frontend/src/routes/documents/[id]/+page.svelte b/frontend/src/routes/documents/[id]/+page.svelte index 88082ceb..7864ce00 100644 --- a/frontend/src/routes/documents/[id]/+page.svelte +++ b/frontend/src/routes/documents/[id]/+page.svelte @@ -55,6 +55,14 @@ let activeAnnotationId = $state(null); let transcriptionBlocks = $state([]); +const blockNumbers = $derived( + Object.fromEntries( + [...transcriptionBlocks] + .sort((a, b) => a.sortOrder - b.sortOrder) + .map((b, i) => [b.annotationId, i + 1]) + ) +); + async function loadTranscriptionBlocks() { if (!doc?.id) return; try { @@ -197,6 +205,7 @@ onMount(() => { isLoading={isLoading} error={fileError} transcribeMode={transcribeMode} + blockNumbers={blockNumbers} bind:activeAnnotationId={activeAnnotationId} onAnnotationClick={handleAnnotationClick} onTranscriptionDraw={createBlockFromDraw}