pf_app
Clicking the blank `partgroup` node under ALTMAN PLANTS selected the customer's whole $27,588,393.62 (6,851 rows) rather than the $6,198,860.42 (2,421) under the node clicked -- and the ledger agreed, because the panel totals through the same filter list the operation writes from. The key was not narrowed, it was absent, and an absent key means every value of it. The drop is the engine's: `getCellConfig` builds the click's filter list with `pivot_value ? [pivot, '==', pivot_value] : undefined`, so a blank group key is gone before `perspective-click` is dispatched -- and being falsy, so is a dimension whose value is 0. `cellFilters()` re-derives both axes from `detail.row.__ROW_PATH__` and the clicked column name instead; the click and a dragged region now share that one derivation rather than keeping two copies of the same falsy test. Both blanks are real here and they are different rows: `partgroup` is null on 51,964 and '' on 111,696. So they stay distinct end to end. `buildWhere` renders a null as IS NULL, where it used to fall through `esc()` to `= ''` and select *the other blank* -- the slice naming one node while the operation wrote the other. In a list the null arm is ORed on, since `IN (NULL)` is never true. The ledger filters with `is null` rather than `== null`, the engine matching on type and a null threshold against a string column being the same dropped predicate. Only `undefined` now means absent, which keeps a subtotal row (a shorter row path) and a collapsed column level reading as "not part of the slice". A blank on the *column* axis still cannot be isolated: a column name is its values joined with '|' and a null joins as the empty string, so the two blanks are the same text by the time it reaches the client. Those cells are refused with a message rather than widened. The panel prints (null) and (blank), and keeps em dash for a column genuinely absent from the slice -- isolating the blank node and ignoring the column are opposite statements and read identically before. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| lib | ||
| public | ||
| routes | ||
| setup_sql | ||
| ui | ||
| .env.example | ||
| .gitignore | ||
| CLAUDE.md | ||
| install.sh | ||
| package-lock.json | ||
| package.json | ||
| PERSPECTIVE.md | ||
| pf_perspective_options.md | ||
| pf_spec.md | ||
| pf.sh | ||
| server.js | ||