Merge branch 'row-label-wall'
Floor the last row-label column so the deepest level's labels are not squashed against the numbers when the tree is expanded. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
8ab6dd91e0
@ -1268,8 +1268,30 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
||||
// has to overflow its column, not the column grow to hold the text.
|
||||
const MIN_ROW_LABEL_CHARS = 3
|
||||
|
||||
// The wall: the last row-label column, which is where the deepest level's
|
||||
// labels land once the tree is expanded to full depth.
|
||||
//
|
||||
// Its index is group_by.length, and the geometry is worth writing down because
|
||||
// the comment on fitRowLabels had it wrong and cost a day. With four group_by
|
||||
// levels the grid lays out rt-col-0..4 for row labels and starts the data at
|
||||
// rt-col-5 (= tree_header_offset, group_by.length + 1). Column 0 is the indent
|
||||
// gutter, and columns 1..N are the N levels — so the last level is column N,
|
||||
// not N - 1. The hidden grand-total column is the *data* one at
|
||||
// tree_header_offset, which the psp-split-total rule zeroes out; it is not
|
||||
// this one.
|
||||
//
|
||||
// Only the columns for levels currently on show are rendered, so at
|
||||
// group_by_depth 1 the deeper ones have no cells at all. Sizing this one by
|
||||
// measuring the DOM therefore cannot work — it is sized blind, ahead of being
|
||||
// needed, which is exactly why it is a constant rather than a fit.
|
||||
//
|
||||
// 218px was measured by hand: the width a rep/customer/month/part tree wants
|
||||
// once it is open. This is the number to turn.
|
||||
const ROW_LABEL_WALL_W = 218
|
||||
|
||||
async function ensureRowLabelWidth() {
|
||||
const grid = (await viewerRef.current?.getPlugin())?.regular_table
|
||||
const viewer = viewerRef.current
|
||||
const grid = (await viewer?.getPlugin())?.regular_table
|
||||
if (!grid?.saveColumnSizes) return
|
||||
|
||||
const cells = [...grid.querySelectorAll('tbody th')]
|
||||
@ -1293,6 +1315,15 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
||||
for (const idx of idxs) {
|
||||
if ((sizes[idx] ?? 0) < min) { sizes[idx] = min; changed = true }
|
||||
}
|
||||
|
||||
// A floor, like the rest: a wall someone has dragged wider is left alone.
|
||||
const { group_by = [] } = (await viewer.save()) || {}
|
||||
const wall = group_by.length
|
||||
if (wall > 0 && (sizes[wall] ?? 0) < ROW_LABEL_WALL_W) {
|
||||
sizes[wall] = ROW_LABEL_WALL_W
|
||||
changed = true
|
||||
}
|
||||
|
||||
if (!changed) return
|
||||
grid.restoreColumnSizes(sizes)
|
||||
await grid.draw({ invalid_columns: true })
|
||||
@ -1319,11 +1350,16 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
||||
// the same circularity that stops headers sizing themselves.
|
||||
//
|
||||
// Set by column *index* through regular-table's own saveColumnSizes /
|
||||
// restoreColumnSizes, not as a plugin_config column_size_override. The override
|
||||
// path maps the key "__ROW_PATH__" to index tree_header_offset - 1, which with
|
||||
// two group_by levels is index 2 — the first data column, not a row label.
|
||||
// Pinning that was doing nothing visible because that column is the
|
||||
// grand-total one, which the stylesheet hides.
|
||||
// restoreColumnSizes, not as a plugin_config column_size_override, which maps
|
||||
// the single key "__ROW_PATH__" onto one index and so cannot address a
|
||||
// multi-level row header at all.
|
||||
//
|
||||
// Note the index arithmetic, which an earlier version of this comment had
|
||||
// wrong: tree_header_offset is group_by.length + 1 and is where the DATA
|
||||
// starts. The row labels are columns 0..group_by.length, of which 0 is the
|
||||
// indent gutter and 1..N are the N levels. tree_header_offset - 1 is the last
|
||||
// *label* column, not a data column; the hidden grand-total column is the
|
||||
// data one at tree_header_offset itself.
|
||||
async function fitRowLabels(grid) {
|
||||
const cells = [...grid.querySelectorAll('tbody th')]
|
||||
if (cells.length === 0) return
|
||||
|
||||
Loading…
Reference in New Issue
Block a user