fix: restore objectAssignments in EditPairForm on load

Extract {{label.o:objectId}} refs from raw sentence text before resolving
placeholders, then reconcile with wordMap once it's built so the object
assignment dropdown reflects the saved state on re-open.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-28 22:08:47 +02:00
parent 4d618bd5b3
commit 93975f40c7

View File

@@ -483,6 +483,9 @@ function EditPairForm({ pair, allObjects, onSaved, onCancel, onDeleted }) {
const [creatingWord, setCreatingWord] = useState(false);
const [confirmDelete, setConfirmDelete] = useState(false);
const [deleting, setDeleting] = useState(false);
// Stores label→objectId extracted from raw placeholder text during load,
// used to restore objectAssignments once wordMap is built.
const labelToObjectId = useRef({});
useEffect(() => { setWordInput(selection); }, [selection]);
@@ -496,16 +499,26 @@ function EditPairForm({ pair, allObjects, onSaved, onCancel, onDeleted }) {
}
useEffect(() => {
labelToObjectId.current = {};
function extractObjectRefs(rawText) {
const re = /\{\{([^.}]+)\.o:([0-9a-f-]{36})\}\}/gi;
let m;
while ((m = re.exec(rawText)) !== null) {
labelToObjectId.current[m[1].toLowerCase()] = m[2];
}
}
async function load() {
try {
if (pair.question_id) {
const q = await apiFetch(`/questions/${pair.question_id}`);
setQuestion(await resolvePlaceholders(q[`sentence_${lang}`] || q.sentence_de || '', allObjects));
const rawQ = q[`sentence_${lang}`] || q.sentence_de || '';
extractObjectRefs(rawQ);
setQuestion(await resolvePlaceholders(rawQ, allObjects));
}
if (pair.positive_statement_id) {
const s = await apiFetch(`/statements/${pair.positive_statement_id}`);
const raw = s[`positive_sentence_${lang}`] || s.positive_sentence_de || '';
if (raw) setPositive(await resolvePlaceholders(raw, allObjects));
if (raw) { extractObjectRefs(raw); setPositive(await resolvePlaceholders(raw, allObjects)); }
if (s.answer !== null && s.answer !== undefined) setYesNoAnswer(s.answer);
if (s.positive_word_ids?.length) {
const words = await Promise.all(s.positive_word_ids.map(id => apiFetch(`/words/${id}`).catch(() => null)));
@@ -515,7 +528,7 @@ function EditPairForm({ pair, allObjects, onSaved, onCancel, onDeleted }) {
if (pair.negative_statement_id) {
const s = await apiFetch(`/statements/${pair.negative_statement_id}`);
const raw = s[`negative_sentence_${lang}`] || s.negative_sentence_de || '';
if (raw) setNegative(await resolvePlaceholders(raw, allObjects));
if (raw) { extractObjectRefs(raw); setNegative(await resolvePlaceholders(raw, allObjects)); }
if (s.negative_word_ids?.length) {
const words = await Promise.all(s.negative_word_ids.map(id => apiFetch(`/words/${id}`).catch(() => null)));
setNegativeWords(words.filter(Boolean));
@@ -551,6 +564,17 @@ function EditPairForm({ pair, allObjects, onSaved, onCancel, onDeleted }) {
}
});
setWordMap(map);
// Restore objectAssignments from placeholders extracted during load
if (Object.keys(labelToObjectId.current).length) {
setObjectAssignments(prev => {
const restored = {};
Object.entries(map).forEach(([label, w]) => {
const objId = labelToObjectId.current[label.toLowerCase()];
if (objId) restored[w.id] = objId;
});
return Object.keys(restored).length ? { ...restored, ...prev } : prev;
});
}
} catch { /* ignore word detection errors */ }
}, 600);
return () => clearTimeout(t);