From 194134ea5f22c29c1324d480952c909c0072bc3e Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Thu, 17 Sep 2026 14:10:55 -0400 Subject: [PATCH] Apply the ordering expressions after the layout, not before MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Bucket and Segment columns never appeared in the column list, and viewer.save() reported expressions: {}. syncOrderExpressions ran immediately after viewer.load() — and the saved layout was restored on the next line. restore() replaces `expressions` wholesale rather than merging, so the expressions were created and then wiped every single time, before anything could see them. Moved to after both restore branches. The effect on [logMeta, versions, versionId] then keeps them in step, as intended. Co-Authored-By: Claude Opus 5 (1M context) --- ui/src/views/Forecast.jsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ui/src/views/Forecast.jsx b/ui/src/views/Forecast.jsx index d59b030..382a3db 100644 --- a/ui/src/views/Forecast.jsx +++ b/ui/src/views/Forecast.jsx @@ -755,7 +755,6 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio await viewer.load(tableRef.current) viewer.setAttribute('theme', dark ? 'Pro Dark' : 'Pro Light') if (!hideSplitTotal()) setTimeout(hideSplitTotal, 400) - await syncOrderExpressions() // restore last-used layout or build default // Strip cfg.table — table is already loaded by reference above; a stale name @@ -793,6 +792,12 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio } // auto-persist viewer state (formatting, columns, etc.) to the last-used cache + // After the layout, not before: restoring a saved config replaces + // `expressions` wholesale, so expressions applied earlier were being wiped + // by the very next line and the ordering columns never appeared in the + // column list. + await syncOrderExpressions() + if (viewer._pspUpdate) viewer.removeEventListener('perspective-config-update', viewer._pspUpdate) viewer._pspUpdate = async () => { try {