From 93975f40c7b0390e23377455c2f120c375d8f6f2 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 28 May 2026 22:08:47 +0200 Subject: [PATCH] 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 --- src/pages/ContentCreation.jsx | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/pages/ContentCreation.jsx b/src/pages/ContentCreation.jsx index dbe640e..885f160 100644 --- a/src/pages/ContentCreation.jsx +++ b/src/pages/ContentCreation.jsx @@ -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);