From 742d4b4cc47a2340a28a249a2372a57a289b28bd Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Sat, 25 Apr 2026 21:23:43 -0400 Subject: [PATCH] Revert "Dark theme for Forecast view controls and operation panel" This reverts commit cda3943515563e9054ab780fc059aab60e4a989a. --- ui/src/views/Forecast.jsx | 236 ++++++++++++++++++-------------------- 1 file changed, 110 insertions(+), 126 deletions(-) diff --git a/ui/src/views/Forecast.jsx b/ui/src/views/Forecast.jsx index 4d0b345..1ed44fb 100644 --- a/ui/src/views/Forecast.jsx +++ b/ui/src/views/Forecast.jsx @@ -118,11 +118,8 @@ export default function Forecast() { const unitsCol = colMetaRef.current.find(c => c.role === 'units')?.cname if (!valueCol && !unitsCol) return try { - const dimNames = new Set(colMetaRef.current.filter(c => c.role === 'dimension').map(c => c.cname)) const filters = [ - ...Object.entries(sliceObj) - .filter(([col]) => dimNames.has(col)) - .map(([col, val]) => [col, '==', val]), + ...Object.entries(sliceObj).map(([col, val]) => [col, '==', val]), ['pf_iter', '!=', 'reference'], ] const view = await tableRef.current.view({ filter: filters }) @@ -381,123 +378,110 @@ export default function Forecast() { const hasSlice = Object.keys(slice).length > 0 return ( -
+
{/* Source / version bar */} -
+
Source - setSourceId(e.target.value)} className="border border-gray-200 rounded px-2 py-1 text-sm bg-white"> {sources.map(s => )}
Version - setVersionId(e.target.value)} className="border border-gray-200 rounded px-2 py-1 text-sm bg-white" disabled={!versions.length}> {versions.length === 0 ? : versions.map(v => )} {selectedVersion && ( - + {selectedVersion.status} )}
-
- - {/* Toolbar bar */} -
- - {/* Layouts group */} -
- Layout - {layouts.map(l => ( -
applyLayout(l)} - className={`flex items-center gap-1 rounded px-2 py-0.5 cursor-pointer border transition-colors - ${activeLayoutId === l.id ? 'bg-blue-900 border-blue-600 text-blue-300' : 'bg-gray-800 border-gray-600 text-gray-400 hover:border-gray-400 hover:text-gray-200'}`}> - {l.name} - -
- ))} - {showSaveAs ? ( -
- setSaveAsName(e.target.value)} - onKeyDown={e => { if (e.key === 'Enter') handleSaveAs(); if (e.key === 'Escape') { setShowSaveAs(false); setSaveAsName('') } }} - placeholder="Layout name…" className="border border-gray-600 rounded px-2 py-0.5 w-32 bg-gray-800 text-gray-200 focus:outline-none focus:border-blue-500 placeholder:text-gray-600" /> - - -
- ) : ( - <> - {activeLayoutId !== null && ( - - )} - - {activeLayoutId !== null && ( - - )} - - )} -
- -
- - {/* Expand depth group */} -
- Expand - {[0, 1, 2, 3].map(d => ( - - ))} -
- -
- - {/* Data group */} -
- - -
- {msg && ( - + {msg.text} )} +
+ {/* Layout / depth bar */} +
+ Layouts + + {layouts.map(l => ( +
applyLayout(l)} + className={`flex items-center gap-1 text-xs rounded px-2 py-0.5 cursor-pointer border transition-colors + ${activeLayoutId === l.id ? 'bg-blue-50 border-blue-300 text-blue-700' : 'bg-white border-gray-200 text-gray-600 hover:border-gray-400'}`}> + {l.name} + +
+ ))} + + {activeLayoutId !== null && !showSaveAs && ( + + )} + + {showSaveAs ? ( +
+ setSaveAsName(e.target.value)} + onKeyDown={e => { if (e.key === 'Enter') handleSaveAs(); if (e.key === 'Escape') { setShowSaveAs(false); setSaveAsName('') } }} + placeholder="Layout name…" className="text-xs border border-gray-300 rounded px-2 py-0.5 w-32 focus:outline-none focus:border-blue-400" /> + + +
+ ) : ( + + )} + + {activeLayoutId !== null && ( + + )} + + + + {/* Depth controls */} +
+ depth + {[0, 1, 2, 3].map(d => ( + + ))} + +
{/* History modal */} {showLog && ( -
setShowLog(false)}> -
e.stopPropagation()}> -
- Change log - +
setShowLog(false)}> +
e.stopPropagation()}> +
+ Change History +
{logLoading ? ( -
Loading…
+
Loading…
) : logEntries.length === 0 ? ( -
No log entries yet.
+
No log entries yet.
) : ( - + @@ -509,15 +493,15 @@ export default function Forecast() { {logEntries.map(entry => ( - - + + - - + @@ -543,7 +527,7 @@ export default function Forecast() { @@ -562,40 +546,40 @@ export default function Forecast() { {/* Perspective viewer */}
{loading && ( -
- Loading… +
+ Loading…
)}
{/* Drag handle */} -
+
{/* Operation panel */} -
-
-
Slice
+
+
+
Slice
{!hasSlice ? ( -
Click a pivot row to select a slice
+
Click a pivot row to select a slice
) : (
{Object.entries(slice).map(([k, v]) => ( -
- {k} = {v} +
+ {k} = {v}
))} - +
)}
{hasSlice && ( <> -
+
{['scale', 'recode', 'clone'].map(op => ( ))} @@ -604,10 +588,10 @@ export default function Forecast() {
{activeOp === 'scale' && <> {/* Mode toggle */} -
+
{[['target','= Target'],['delta','Δ Increment']].map(([m, label]) => ( ))} @@ -616,9 +600,9 @@ export default function Forecast() { {/* Value row */} {currentTotals?.valueCol && (
-
+
{currentTotals.valueCol} - {currentTotals.value?.toLocaleString(undefined, {maximumFractionDigits:2})} + {currentTotals.value?.toLocaleString(undefined, {maximumFractionDigits:2})}
setScaleValue(e.target.value)} @@ -630,9 +614,9 @@ export default function Forecast() { {/* Units row */} {currentTotals?.unitsCol && (
-
+
{currentTotals.unitsCol} - {currentTotals.units?.toLocaleString(undefined, {maximumFractionDigits:2})} + {currentTotals.units?.toLocaleString(undefined, {maximumFractionDigits:2})}
setScaleUnits(e.target.value)} @@ -652,7 +636,7 @@ export default function Forecast() { } {activeOp === 'recode' && <> -

New values for dimensions to replace. Leave blank to keep.

+

New values for dimensions to replace. Leave blank to keep.

{dimCols.map(c => ( setRecodeSet(s => ({ ...s, [c.cname]: e.target.value }))} @@ -664,7 +648,7 @@ export default function Forecast() { } {activeOp === 'clone' && <> -

Override dimensions on cloned rows. Leave blank to keep.

+

Override dimensions on cloned rows. Leave blank to keep.

{dimCols.map(c => ( setCloneSet(s => ({ ...s, [c.cname]: e.target.value }))} @@ -684,7 +668,7 @@ export default function Forecast() { ) } -const inp = 'border border-gray-700 rounded px-2 py-1 text-xs flex-1 bg-gray-800 text-gray-200 placeholder:text-gray-600 min-w-0 focus:outline-none focus:border-blue-600' +const inp = 'border border-gray-200 rounded px-2 py-1 text-xs flex-1 bg-white min-w-0' function fmtStamp(stamp) { return new Date(stamp).toLocaleString(undefined, { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) @@ -696,18 +680,18 @@ function fmtSlice(slice) { } const OP_BADGE = { - baseline: 'bg-gray-700 text-gray-300', - reference: 'bg-blue-900 text-blue-300', - scale: 'bg-green-900 text-green-400', - recode: 'bg-amber-900 text-amber-400', - clone: 'bg-purple-900 text-purple-400', + baseline: 'bg-gray-100 text-gray-600', + reference: 'bg-blue-50 text-blue-600', + scale: 'bg-green-50 text-green-700', + recode: 'bg-amber-50 text-amber-700', + clone: 'bg-purple-50 text-purple-700', } -function opBadge(op) { return OP_BADGE[op] || 'bg-gray-700 text-gray-400' } +function opBadge(op) { return OP_BADGE[op] || 'bg-gray-100 text-gray-500' } function Row({ label, children }) { return (
- {label} + {label} {children}
) @@ -715,7 +699,7 @@ function Row({ label, children }) { function Submit({ onClick, children }) { return ( - )
Time Op
{fmtStamp(entry.stamp)}
{fmtStamp(entry.stamp)} {entry.operation} {fmtSlice(entry.slice)} + {fmtSlice(entry.slice)} {editingNote?.id === entry.id ? (
- - + className="border border-blue-300 rounded px-1.5 py-0.5 text-xs flex-1 focus:outline-none" /> + +
) : ( setEditingNote({ id: entry.id, text: entry.note || '' })} - className="cursor-text hover:bg-gray-700 rounded px-1 -mx-1 block truncate" + className="cursor-text hover:bg-blue-50 rounded px-1 -mx-1 block truncate" title={entry.note || 'Click to add note'}> - {entry.note || add note} + {entry.note || add note} )}