feat(person-mention): add @mention discoverability hint to transcription block placeholder #379

Merged
marcel merged 3 commits from feat/issue-370-at-mention-placeholder-hint into main 2026-05-04 15:35:08 +02:00
6 changed files with 26 additions and 9 deletions

View File

@@ -60,6 +60,8 @@ public interface TranscriptionBlockRepository extends JpaRepository<Transcriptio
""")
List<TranscriptionBlock> findSegmentationBlocks();
// Uses 'KURRENT_RECOGNITION' MEMBER OF d.trainingLabels — aligned with findEligibleKurrentBlocks()
// which already used this form (changed from d.scriptType = 'KURRENT' in the original queries).
@Query("""
SELECT COUNT(b) FROM TranscriptionBlock b
JOIN Document d ON d.id = b.documentId
@@ -69,6 +71,8 @@ public interface TranscriptionBlockRepository extends JpaRepository<Transcriptio
""")
long countManualKurrentBlocksByPerson(@Param("personId") UUID personId);
// Uses 'KURRENT_RECOGNITION' MEMBER OF d.trainingLabels — aligned with findEligibleKurrentBlocks()
// which already used this form (changed from d.scriptType = 'KURRENT' in the original queries).
@Query("""
SELECT b FROM TranscriptionBlock b
JOIN Document d ON d.id = b.documentId

View File

@@ -5,7 +5,6 @@ import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.PostgresContainerConfig;
import org.raddatz.familienarchiv.config.FlywayConfig;
import org.raddatz.familienarchiv.model.*;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureTestDatabase;
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
@@ -13,6 +12,7 @@ import org.springframework.context.annotation.Import;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
@@ -38,7 +38,7 @@ class TrainingBlockQueryTest {
.title("Kurrent Brief")
.originalFilename("kurrent.pdf")
.status(DocumentStatus.UPLOADED)
.trainingLabels(new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION)))
.trainingLabels(kurrentLabels())
.build());
kurrentDocId = kurrentDoc.getId();
@@ -123,7 +123,7 @@ class TrainingBlockQueryTest {
.originalFilename("karl.pdf")
.status(DocumentStatus.UPLOADED)
.sender(sender)
.trainingLabels(new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION)))
.trainingLabels(kurrentLabels())
.build());
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
blockRepository.save(block(doc.getId(), annId, BlockSource.MANUAL, false));
@@ -158,7 +158,7 @@ class TrainingBlockQueryTest {
.originalFilename("karl.pdf")
.status(DocumentStatus.UPLOADED)
.sender(sender)
.trainingLabels(new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION)))
.trainingLabels(kurrentLabels())
.build());
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
blockRepository.save(block(doc.getId(), annId, BlockSource.OCR, false));
@@ -177,7 +177,7 @@ class TrainingBlockQueryTest {
.originalFilename("karl.pdf")
.status(DocumentStatus.UPLOADED)
.sender(karl)
.trainingLabels(new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION)))
.trainingLabels(kurrentLabels())
.build());
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
blockRepository.save(block(doc.getId(), annId, BlockSource.MANUAL, false));
@@ -195,7 +195,7 @@ class TrainingBlockQueryTest {
.originalFilename("karl.pdf")
.status(DocumentStatus.UPLOADED)
.sender(sender)
.trainingLabels(new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION)))
.trainingLabels(kurrentLabels())
.build());
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
blockRepository.save(block(doc.getId(), annId, BlockSource.MANUAL, false));
@@ -218,6 +218,10 @@ class TrainingBlockQueryTest {
// ─── helpers ─────────────────────────────────────────────────────────────
private static Set<TrainingLabel> kurrentLabels() {
return new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION));
}
private DocumentAnnotation annotation(UUID docId) {
return DocumentAnnotation.builder()
.documentId(docId)

View File

@@ -503,7 +503,7 @@
"doc_details_more_receivers": "+{count} weitere",
"transcription_mode_label": "Transkribieren",
"transcription_mode_stop": "Fertig",
"transcription_block_placeholder": "Text hier eingeben...",
"transcription_block_placeholder": "Text eingeben — mit @Name eine Person aus dem Archiv verknüpfen",
"transcription_block_save_saving": "Speichere...",
"transcription_block_save_saved": "Gespeichert",
"transcription_block_save_error": "Nicht gespeichert",

View File

@@ -503,7 +503,7 @@
"doc_details_more_receivers": "+{count} more",
"transcription_mode_label": "Transcribe",
"transcription_mode_stop": "Done",
"transcription_block_placeholder": "Type text here...",
"transcription_block_placeholder": "Type text — use @name to link a person from the archive",
"transcription_block_save_saving": "Saving...",
"transcription_block_save_saved": "Saved",
"transcription_block_save_error": "Not saved",

View File

@@ -503,7 +503,7 @@
"doc_details_more_receivers": "+{count} más",
"transcription_mode_label": "Transcribir",
"transcription_mode_stop": "Listo",
"transcription_block_placeholder": "Escriba el texto aquí...",
"transcription_block_placeholder": "Escriba el texto — use @nombre para vincular a una persona del archivo",
"transcription_block_save_saving": "Guardando...",
"transcription_block_save_saved": "Guardado",
"transcription_block_save_error": "No guardado",

View File

@@ -10,6 +10,7 @@ import { cleanup, render } from 'vitest-browser-svelte';
import { page, userEvent } from 'vitest/browser';
import PersonMentionEditorHost from './PersonMentionEditor.test-host.svelte';
import type { components } from '$lib/generated/api';
import { m } from '$lib/paraglide/messages.js';
type Person = components['schemas']['Person'];
type PersonMention = components['schemas']['PersonMention'];
@@ -395,6 +396,14 @@ describe('PersonMentionEditor — placeholder behavior', () => {
});
});
// ─── i18n message content ─────────────────────────────────────────────────────
describe('PersonMentionEditor — i18n message content', () => {
it('transcription_block_placeholder contains @ mention trigger for discoverability', () => {
expect(m.transcription_block_placeholder()).toContain('@');
});
});
// ─── Touch target (WCAG 2.2 AA) ──────────────────────────────────────────────
describe('PersonMentionEditor — touch target', () => {