diff --git a/database/sources.sql b/database/sources.sql index cf31cba..49c9083 100644 --- a/database/sources.sql +++ b/database/sources.sql @@ -65,6 +65,16 @@ RETURNS TABLE (key TEXT, origins TEXT[]) AS $$ SELECT jsonb_object_keys(data) AS key, 'raw' AS origin FROM dataflow.records WHERE source_name = p_source_name UNION ALL + -- transformed/overrides are read straight off the records so that keys with + -- no surviving rule or mapping (e.g. a manual override) still get listed + SELECT jsonb_object_keys(transformed) AS key, 'transformed' AS origin + FROM dataflow.records + WHERE source_name = p_source_name AND transformed IS NOT NULL + UNION ALL + SELECT jsonb_object_keys(overrides) AS key, 'override' AS origin + FROM dataflow.records + WHERE source_name = p_source_name AND overrides IS NOT NULL + UNION ALL SELECT output_field AS key, 'rule: ' || name AS origin FROM dataflow.rules WHERE source_name = p_source_name UNION ALL diff --git a/ui/src/pages/Records.jsx b/ui/src/pages/Records.jsx index 09d0940..c1be1f9 100644 --- a/ui/src/pages/Records.jsx +++ b/ui/src/pages/Records.jsx @@ -62,7 +62,16 @@ function AutocompleteInput({ value, onChange, onEnter, suggestions = [], classNa } const DATE_RE = /^\d{4}-\d{2}-\d{2}(T[\d:.Z+-]+)?$/ +// Hidden everywhere a field can be edited as an override — you can't override an id const HIDDEN_COLS = new Set(['id', '_overridden']) +// The grid and its filters keep id: it's the only handle on a specific row +const GRID_HIDDEN_COLS = new Set(['_overridden']) + +// id first, then the rest in view order +function gridCols(keys) { + const visible = keys.filter(c => !GRID_HIDDEN_COLS.has(c)) + return visible.includes('id') ? ['id', ...visible.filter(c => c !== 'id')] : visible +} function formatVal(val) { if (val === null || val === undefined) return null @@ -179,7 +188,8 @@ export default function Records({ source }) { } function addFilter() { - const visCols = cols.filter(c => !HIDDEN_COLS.has(c)) + // id is filterable but a poor default — start on the first data column + const visCols = gridCols(cols).filter(c => c !== 'id') setFilters(f => [...f, { col: visCols[0] || '', pattern: '' }]) } @@ -275,8 +285,8 @@ export default function Records({ source }) { if (!source) return