feat(person-mention): add @mention discoverability hint to transcription block placeholder #379
@@ -60,6 +60,8 @@ public interface TranscriptionBlockRepository extends JpaRepository<Transcriptio
|
|||||||
""")
|
""")
|
||||||
List<TranscriptionBlock> findSegmentationBlocks();
|
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("""
|
@Query("""
|
||||||
SELECT COUNT(b) FROM TranscriptionBlock b
|
SELECT COUNT(b) FROM TranscriptionBlock b
|
||||||
JOIN Document d ON d.id = b.documentId
|
JOIN Document d ON d.id = b.documentId
|
||||||
@@ -69,6 +71,8 @@ public interface TranscriptionBlockRepository extends JpaRepository<Transcriptio
|
|||||||
""")
|
""")
|
||||||
long countManualKurrentBlocksByPerson(@Param("personId") UUID personId);
|
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("""
|
@Query("""
|
||||||
SELECT b FROM TranscriptionBlock b
|
SELECT b FROM TranscriptionBlock b
|
||||||
JOIN Document d ON d.id = b.documentId
|
JOIN Document d ON d.id = b.documentId
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.raddatz.familienarchiv.PostgresContainerConfig;
|
import org.raddatz.familienarchiv.PostgresContainerConfig;
|
||||||
import org.raddatz.familienarchiv.config.FlywayConfig;
|
import org.raddatz.familienarchiv.config.FlywayConfig;
|
||||||
import org.raddatz.familienarchiv.model.*;
|
import org.raddatz.familienarchiv.model.*;
|
||||||
import java.util.Set;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureTestDatabase;
|
import org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureTestDatabase;
|
||||||
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
|
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.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@@ -38,7 +38,7 @@ class TrainingBlockQueryTest {
|
|||||||
.title("Kurrent Brief")
|
.title("Kurrent Brief")
|
||||||
.originalFilename("kurrent.pdf")
|
.originalFilename("kurrent.pdf")
|
||||||
.status(DocumentStatus.UPLOADED)
|
.status(DocumentStatus.UPLOADED)
|
||||||
.trainingLabels(new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION)))
|
.trainingLabels(kurrentLabels())
|
||||||
.build());
|
.build());
|
||||||
kurrentDocId = kurrentDoc.getId();
|
kurrentDocId = kurrentDoc.getId();
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ class TrainingBlockQueryTest {
|
|||||||
.originalFilename("karl.pdf")
|
.originalFilename("karl.pdf")
|
||||||
.status(DocumentStatus.UPLOADED)
|
.status(DocumentStatus.UPLOADED)
|
||||||
.sender(sender)
|
.sender(sender)
|
||||||
.trainingLabels(new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION)))
|
.trainingLabels(kurrentLabels())
|
||||||
.build());
|
.build());
|
||||||
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
|
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
|
||||||
blockRepository.save(block(doc.getId(), annId, BlockSource.MANUAL, false));
|
blockRepository.save(block(doc.getId(), annId, BlockSource.MANUAL, false));
|
||||||
@@ -158,7 +158,7 @@ class TrainingBlockQueryTest {
|
|||||||
.originalFilename("karl.pdf")
|
.originalFilename("karl.pdf")
|
||||||
.status(DocumentStatus.UPLOADED)
|
.status(DocumentStatus.UPLOADED)
|
||||||
.sender(sender)
|
.sender(sender)
|
||||||
.trainingLabels(new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION)))
|
.trainingLabels(kurrentLabels())
|
||||||
.build());
|
.build());
|
||||||
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
|
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
|
||||||
blockRepository.save(block(doc.getId(), annId, BlockSource.OCR, false));
|
blockRepository.save(block(doc.getId(), annId, BlockSource.OCR, false));
|
||||||
@@ -177,7 +177,7 @@ class TrainingBlockQueryTest {
|
|||||||
.originalFilename("karl.pdf")
|
.originalFilename("karl.pdf")
|
||||||
.status(DocumentStatus.UPLOADED)
|
.status(DocumentStatus.UPLOADED)
|
||||||
.sender(karl)
|
.sender(karl)
|
||||||
.trainingLabels(new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION)))
|
.trainingLabels(kurrentLabels())
|
||||||
.build());
|
.build());
|
||||||
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
|
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
|
||||||
blockRepository.save(block(doc.getId(), annId, BlockSource.MANUAL, false));
|
blockRepository.save(block(doc.getId(), annId, BlockSource.MANUAL, false));
|
||||||
@@ -195,7 +195,7 @@ class TrainingBlockQueryTest {
|
|||||||
.originalFilename("karl.pdf")
|
.originalFilename("karl.pdf")
|
||||||
.status(DocumentStatus.UPLOADED)
|
.status(DocumentStatus.UPLOADED)
|
||||||
.sender(sender)
|
.sender(sender)
|
||||||
.trainingLabels(new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION)))
|
.trainingLabels(kurrentLabels())
|
||||||
.build());
|
.build());
|
||||||
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
|
UUID annId = annotationRepository.save(annotation(doc.getId())).getId();
|
||||||
blockRepository.save(block(doc.getId(), annId, BlockSource.MANUAL, false));
|
blockRepository.save(block(doc.getId(), annId, BlockSource.MANUAL, false));
|
||||||
@@ -218,6 +218,10 @@ class TrainingBlockQueryTest {
|
|||||||
|
|
||||||
// ─── helpers ─────────────────────────────────────────────────────────────
|
// ─── helpers ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private static Set<TrainingLabel> kurrentLabels() {
|
||||||
|
return new HashSet<>(Set.of(TrainingLabel.KURRENT_RECOGNITION));
|
||||||
|
}
|
||||||
|
|
||||||
private DocumentAnnotation annotation(UUID docId) {
|
private DocumentAnnotation annotation(UUID docId) {
|
||||||
return DocumentAnnotation.builder()
|
return DocumentAnnotation.builder()
|
||||||
.documentId(docId)
|
.documentId(docId)
|
||||||
|
|||||||
@@ -503,7 +503,7 @@
|
|||||||
"doc_details_more_receivers": "+{count} weitere",
|
"doc_details_more_receivers": "+{count} weitere",
|
||||||
"transcription_mode_label": "Transkribieren",
|
"transcription_mode_label": "Transkribieren",
|
||||||
"transcription_mode_stop": "Fertig",
|
"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_saving": "Speichere...",
|
||||||
"transcription_block_save_saved": "Gespeichert",
|
"transcription_block_save_saved": "Gespeichert",
|
||||||
"transcription_block_save_error": "Nicht gespeichert",
|
"transcription_block_save_error": "Nicht gespeichert",
|
||||||
|
|||||||
@@ -503,7 +503,7 @@
|
|||||||
"doc_details_more_receivers": "+{count} more",
|
"doc_details_more_receivers": "+{count} more",
|
||||||
"transcription_mode_label": "Transcribe",
|
"transcription_mode_label": "Transcribe",
|
||||||
"transcription_mode_stop": "Done",
|
"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_saving": "Saving...",
|
||||||
"transcription_block_save_saved": "Saved",
|
"transcription_block_save_saved": "Saved",
|
||||||
"transcription_block_save_error": "Not saved",
|
"transcription_block_save_error": "Not saved",
|
||||||
|
|||||||
@@ -503,7 +503,7 @@
|
|||||||
"doc_details_more_receivers": "+{count} más",
|
"doc_details_more_receivers": "+{count} más",
|
||||||
"transcription_mode_label": "Transcribir",
|
"transcription_mode_label": "Transcribir",
|
||||||
"transcription_mode_stop": "Listo",
|
"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_saving": "Guardando...",
|
||||||
"transcription_block_save_saved": "Guardado",
|
"transcription_block_save_saved": "Guardado",
|
||||||
"transcription_block_save_error": "No guardado",
|
"transcription_block_save_error": "No guardado",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { cleanup, render } from 'vitest-browser-svelte';
|
|||||||
import { page, userEvent } from 'vitest/browser';
|
import { page, userEvent } from 'vitest/browser';
|
||||||
import PersonMentionEditorHost from './PersonMentionEditor.test-host.svelte';
|
import PersonMentionEditorHost from './PersonMentionEditor.test-host.svelte';
|
||||||
import type { components } from '$lib/generated/api';
|
import type { components } from '$lib/generated/api';
|
||||||
|
import { m } from '$lib/paraglide/messages.js';
|
||||||
|
|
||||||
type Person = components['schemas']['Person'];
|
type Person = components['schemas']['Person'];
|
||||||
type PersonMention = components['schemas']['PersonMention'];
|
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) ──────────────────────────────────────────────
|
// ─── Touch target (WCAG 2.2 AA) ──────────────────────────────────────────────
|
||||||
|
|
||||||
describe('PersonMentionEditor — touch target', () => {
|
describe('PersonMentionEditor — touch target', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user