From 89026e344047db545ae697469e9e694e3e4241e6 Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Thu, 17 Sep 2026 00:40:27 -0400 Subject: [PATCH] Replace sibling attributes on a key change, and say when none were found Autofill filled only empty boxes, so it appeared to work exactly once. Type a part, get its nine attributes; type a different part, and every box is already full, so nothing updates and the form still describes the previous part. That is worse than blank -- the recode would have been submitted with one part's code and another's attributes. These columns describe the key that was just entered, so they are replaced outright now. A lookup that finds nothing also said nothing, which is indistinguishable from a lookup that did not run. It warns, and names the value it could not find, so an unknown part reads differently from a broken autofill. Co-Authored-By: Claude Opus 5 (1M context) --- ui/src/views/Forecast.jsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ui/src/views/Forecast.jsx b/ui/src/views/Forecast.jsx index 6b726e1..d8f3745 100644 --- a/ui/src/views/Forecast.jsx +++ b/ui/src/views/Forecast.jsx @@ -1098,12 +1098,18 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio if (!res.ok) return derived = await res.json() } - if (!derived) return + if (!derived) { + flash(`No attributes found for ${col} "${value.trim()}" — the other fields are unchanged`, 'warn') + return + } + + // Overwrite rather than only filling blanks. These columns describe the key + // that was just entered, so whatever a previous key left behind is wrong, not + // worth preserving -- and leaving it made a second lookup look like it had + // done nothing at all, since every box was already full. setter(prev => { const next = { ...prev } - for (const [k, v] of Object.entries(derived)) { - if (!prev[k] || prev[k] === '') next[k] = String(v ?? '') - } + for (const [k, v] of Object.entries(derived)) next[k] = String(v ?? '') return next }) }