diff --git a/ui/src/views/Forecast.jsx b/ui/src/views/Forecast.jsx index 0d2c1ab..2eb268b 100644 --- a/ui/src/views/Forecast.jsx +++ b/ui/src/views/Forecast.jsx @@ -48,7 +48,18 @@ function cleanLayout(cfg, validCols) { // double quotes, string literals in single, if/else with braces. The ordered // label is emitted as a literal rather than built with concat() — fewer moving // parts, and the mapping is known here anyway. -const ORDER_EXPR_NAMES = { bucket: 'Bucket', segment: 'Segment' } +// pf_ prefixed like every other column the server synthesises, so they sort +// beside pf_bucket and pf_segment in the column list and cannot be mistaken for +// source data. "Bucket" and "Segment" were the first choice and are too close to +// the real thing -- segment_new is an actual column on this source -- and an +// expression named after an existing column would shadow or reject rather than +// merely confuse. +const ORDER_EXPR_NAMES = { bucket: 'pf_bucket_ord', segment: 'pf_segment_ord' } + +// Removed from any config that still carries them. They are no longer managed +// names, so without this they would sit in saved layouts forever, ordering by a +// rule nothing updates. +const LEGACY_ORDER_EXPR_NAMES = ['Bucket', 'Segment'] // ASCII only, and " - " specifically because the source data already reads // "07 - Dec". A middle dot was the first choice and ExprTK rejects it: its string @@ -972,7 +983,7 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio const { table: _t, ...cfg } = await viewer.save() dbgOrder('saved config read', { existing: Object.keys(cfg.expressions || {}) }) const current = cfg.expressions || {} - const managed = Object.values(ORDER_EXPR_NAMES) + const managed = [...Object.values(ORDER_EXPR_NAMES), ...LEGACY_ORDER_EXPR_NAMES] const next = { ...current } for (const name of managed) delete next[name]