Toggle the pivot's grand-total row
The engine has no rollup mode that keeps subtotals and drops the grand total, so the row is hidden in the grid's style listener instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
6deb8e547c
commit
d9db2b59ab
@ -180,6 +180,16 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
|||||||
useEffect(() => { localStorage.setItem('pf_scale_plug_v2', scalePlug) }, [scalePlug])
|
useEffect(() => { localStorage.setItem('pf_scale_plug_v2', scalePlug) }, [scalePlug])
|
||||||
useEffect(() => { localStorage.setItem('pf_panel_open', panelOpen ? 'open' : 'closed') }, [panelOpen])
|
useEffect(() => { localStorage.setItem('pf_panel_open', panelOpen ? 'open' : 'closed') }, [panelOpen])
|
||||||
|
|
||||||
|
// Whether the grand-total row is drawn. Per-browser, like the panel state: it
|
||||||
|
// is how you like to read the grid, not a property of the layout.
|
||||||
|
const [showTotalRow, setShowTotalRow] = useState(() => localStorage.getItem('pf_total_row') !== 'hidden')
|
||||||
|
const showTotalRowRef = useRef(showTotalRow)
|
||||||
|
useEffect(() => {
|
||||||
|
localStorage.setItem('pf_total_row', showTotalRow ? 'shown' : 'hidden')
|
||||||
|
showTotalRowRef.current = showTotalRow
|
||||||
|
gridRef.current?.regular_table?.draw()
|
||||||
|
}, [showTotalRow])
|
||||||
|
|
||||||
// Esc closes the panel — the usual way out of the floating window
|
// Esc closes the panel — the usual way out of the floating window
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!panelOpen) return
|
if (!panelOpen) return
|
||||||
@ -1219,11 +1229,27 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
|||||||
style.textContent = `
|
style.textContent = `
|
||||||
td.pf-group-start { border-left: 2px solid currentColor; opacity: 1; }
|
td.pf-group-start { border-left: 2px solid currentColor; opacity: 1; }
|
||||||
td.pf-subtotal { font-weight: 600; background: color-mix(in srgb, currentColor 7%, transparent); }
|
td.pf-subtotal { font-weight: 600; background: color-mix(in srgb, currentColor 7%, transparent); }
|
||||||
|
tr.pf-total-row { display: none; }
|
||||||
`
|
`
|
||||||
;(root.head || root).appendChild(style)
|
;(root.head || root).appendChild(style)
|
||||||
}
|
}
|
||||||
|
|
||||||
table.addStyleListener(() => {
|
table.addStyleListener(() => {
|
||||||
|
// The grand-total row, hidden on request. The engine has no rollup mode
|
||||||
|
// for "subtotals but no grand total" -- rollup, flat and total are the
|
||||||
|
// three -- so it is dropped here instead. It is view row 0 with a row
|
||||||
|
// header blank at every level; y alone is not enough, since under flat
|
||||||
|
// rollup there is no total and row 0 is a leaf. Tagged per draw, because
|
||||||
|
// the grid recycles its tr elements as it scrolls.
|
||||||
|
for (const tr of table.querySelectorAll('tbody tr')) {
|
||||||
|
const th = tr.querySelector('th')
|
||||||
|
let meta
|
||||||
|
try { meta = th ? table.getMeta(th) : null } catch { meta = null }
|
||||||
|
const isTotal = meta?.y === 0 && Array.isArray(meta.row_header) &&
|
||||||
|
!meta.row_header.some(notBlank)
|
||||||
|
tr.classList.toggle('pf-total-row', isTotal && !showTotalRowRef.current)
|
||||||
|
}
|
||||||
|
|
||||||
const body = table.querySelectorAll('tbody td')
|
const body = table.querySelectorAll('tbody td')
|
||||||
// The deepest column path is a leaf; anything shorter is an aggregate of
|
// The deepest column path is a leaf; anything shorter is an aggregate of
|
||||||
// the levels below it, which is what makes a subtotal a subtotal.
|
// the levels below it, which is what makes a subtotal a subtotal.
|
||||||
@ -2120,6 +2146,12 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
|||||||
<div className="pf-group-rule" />
|
<div className="pf-group-rule" />
|
||||||
<DepthButtons label="Rows" levels={groupFull} depth={expandDepth}
|
<DepthButtons label="Rows" levels={groupFull} depth={expandDepth}
|
||||||
onPick={applyDepth} totalLabel="Total" />
|
onPick={applyDepth} totalLabel="Total" />
|
||||||
|
<label className="flex items-center gap-1 text-gray-600 cursor-pointer select-none"
|
||||||
|
title="Show the grand-total row at the top of the pivot">
|
||||||
|
<input type="checkbox" checked={showTotalRow}
|
||||||
|
onChange={e => setShowTotalRow(e.target.checked)} />
|
||||||
|
Total row
|
||||||
|
</label>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user