Move IPA/syllable toggles to vocabulary tab toolbar
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 49s
CI / test-go-edu-search (push) Successful in 43s
CI / test-python-klausur (push) Failing after 2m51s
CI / test-python-agent-core (push) Successful in 34s
CI / test-nodejs-website (push) Successful in 36s
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 49s
CI / test-go-edu-search (push) Successful in 43s
CI / test-python-klausur (push) Failing after 2m51s
CI / test-python-agent-core (push) Successful in 34s
CI / test-nodejs-website (push) Successful in 36s
Dropdowns are now in the vocabulary table header (after processing), not in the worksheet settings (before processing). Changing a mode automatically reprocesses all successful pages with the new settings. Same dropdown options as the OCR pipeline grid editor. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1620,7 +1620,90 @@ export default function VocabWorksheetPage() {
|
||||
<h2 className={`text-lg font-semibold ${isDark ? 'text-white' : 'text-slate-900'}`}>
|
||||
Vokabeln ({vocabulary.length})
|
||||
</h2>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
{/* IPA mode */}
|
||||
<select
|
||||
value={ipaMode}
|
||||
onChange={(e) => {
|
||||
setIpaMode(e.target.value as typeof ipaMode)
|
||||
// Reprocess pages with new mode
|
||||
if (session && successfulPages.length > 0) {
|
||||
const newIpa = e.target.value
|
||||
setIsExtracting(true)
|
||||
setExtractionStatus('Verarbeite mit neuen IPA-Einstellungen...')
|
||||
const pagesToReprocess = successfulPages.map(p => p - 1)
|
||||
const API_BASE = getApiBase()
|
||||
;(async () => {
|
||||
const allVocab: VocabularyEntry[] = []
|
||||
for (const pageIndex of pagesToReprocess) {
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}/api/v1/vocab/sessions/${session.id}/process-single-page/${pageIndex}?ipa_mode=${newIpa}&syllable_mode=${syllableMode}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ ocr_prompts: ocrPrompts }),
|
||||
})
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
if (data.vocabulary) allVocab.push(...data.vocabulary)
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
setVocabulary(allVocab)
|
||||
setIsExtracting(false)
|
||||
setExtractionStatus(`${allVocab.length} Vokabeln mit neuen Einstellungen`)
|
||||
})()
|
||||
}
|
||||
}}
|
||||
className={`px-2 py-1.5 text-xs rounded-md border ${isDark ? 'border-white/20 bg-white/10 text-white' : 'border-gray-200 bg-white text-gray-600'}`}
|
||||
title="Lautschrift (IPA)"
|
||||
>
|
||||
<option value="none">IPA: Aus</option>
|
||||
<option value="auto">IPA: Auto</option>
|
||||
<option value="en">IPA: nur EN</option>
|
||||
<option value="de">IPA: nur DE</option>
|
||||
<option value="all">IPA: Alle</option>
|
||||
</select>
|
||||
{/* Syllable mode */}
|
||||
<select
|
||||
value={syllableMode}
|
||||
onChange={(e) => {
|
||||
setSyllableMode(e.target.value as typeof syllableMode)
|
||||
if (session && successfulPages.length > 0) {
|
||||
const newSyl = e.target.value
|
||||
setIsExtracting(true)
|
||||
setExtractionStatus('Verarbeite mit neuen Silben-Einstellungen...')
|
||||
const pagesToReprocess = successfulPages.map(p => p - 1)
|
||||
const API_BASE = getApiBase()
|
||||
;(async () => {
|
||||
const allVocab: VocabularyEntry[] = []
|
||||
for (const pageIndex of pagesToReprocess) {
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}/api/v1/vocab/sessions/${session.id}/process-single-page/${pageIndex}?ipa_mode=${ipaMode}&syllable_mode=${newSyl}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ ocr_prompts: ocrPrompts }),
|
||||
})
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
if (data.vocabulary) allVocab.push(...data.vocabulary)
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
setVocabulary(allVocab)
|
||||
setIsExtracting(false)
|
||||
setExtractionStatus(`${allVocab.length} Vokabeln mit neuen Einstellungen`)
|
||||
})()
|
||||
}
|
||||
}}
|
||||
className={`px-2 py-1.5 text-xs rounded-md border ${isDark ? 'border-white/20 bg-white/10 text-white' : 'border-gray-200 bg-white text-gray-600'}`}
|
||||
title="Silbentrennung"
|
||||
>
|
||||
<option value="none">Silben: Aus</option>
|
||||
<option value="auto">Silben: Original</option>
|
||||
<option value="en">Silben: nur EN</option>
|
||||
<option value="de">Silben: nur DE</option>
|
||||
<option value="all">Silben: Alle</option>
|
||||
</select>
|
||||
<button onClick={saveVocabulary} className={`px-4 py-2 rounded-xl text-sm font-medium transition-colors ${isDark ? 'bg-white/10 hover:bg-white/20 text-white' : 'bg-slate-100 hover:bg-slate-200 text-slate-900'}`}>
|
||||
Speichern
|
||||
</button>
|
||||
@@ -1960,40 +2043,7 @@ export default function VocabWorksheetPage() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* OCR display options */}
|
||||
<div className={`p-4 rounded-xl border ${isDark ? 'bg-white/5 border-white/10' : 'bg-gray-50 border-gray-200'} space-y-3`}>
|
||||
<h4 className={`text-sm font-medium ${isDark ? 'text-white/70' : 'text-slate-600'}`}>Anzeigeoptionen</h4>
|
||||
<div className="flex flex-col gap-3">
|
||||
<div>
|
||||
<label className={`block text-sm mb-1 ${isDark ? 'text-white/60' : 'text-slate-500'}`}>Lautschrift (IPA)</label>
|
||||
<select
|
||||
value={ipaMode}
|
||||
onChange={(e) => setIpaMode(e.target.value as typeof ipaMode)}
|
||||
className={`w-full px-3 py-2 rounded-lg border text-sm ${isDark ? 'bg-white/10 border-white/20 text-white' : 'bg-white border-gray-200 text-slate-900'}`}
|
||||
>
|
||||
<option value="none">Aus</option>
|
||||
<option value="auto">Auto (erkannte EN-Woerter)</option>
|
||||
<option value="en">Nur Englisch</option>
|
||||
<option value="de">Nur Deutsch</option>
|
||||
<option value="all">Alle (EN + DE)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className={`block text-sm mb-1 ${isDark ? 'text-white/60' : 'text-slate-500'}`}>Silbentrennung</label>
|
||||
<select
|
||||
value={syllableMode}
|
||||
onChange={(e) => setSyllableMode(e.target.value as typeof syllableMode)}
|
||||
className={`w-full px-3 py-2 rounded-lg border text-sm ${isDark ? 'bg-white/10 border-white/20 text-white' : 'bg-white border-gray-200 text-slate-900'}`}
|
||||
>
|
||||
<option value="none">Aus</option>
|
||||
<option value="auto">Original (nur wo im Scan vorhanden)</option>
|
||||
<option value="en">Nur Englisch</option>
|
||||
<option value="de">Nur Deutsch</option>
|
||||
<option value="all">Alle</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* IPA/Syllable options moved to vocabulary tab toolbar */}
|
||||
|
||||
<button
|
||||
onClick={generateWorksheet}
|
||||
|
||||
Reference in New Issue
Block a user