fix(plugin-report): 透视表 bucket id / cell key 改用 JSON 编码,维度值不再串桶串格 (objectstack#5665) - #3415
Merged
Merged
Conversation
…uously (objectstack#5665) The cross-tab's bucketId joined dimension values with the EMPTY string, so adjacent values had no boundary at all: bucketId(['region','segment'], …) spelled "xyz" for BOTH "x" + "yz" and "xy" + "z". Two different buckets became one on either axis and the later row silently overwrote the earlier one. The cell key then joined the two bucket ids with a plain space — the same defect #3414 fixed in the dashboard widget — while dimension values carry spaces constantly, so "New" x "York Q1" and "New York" x "Q1" met in one key too. A merged bucket showed a different row's measure, the overwritten row's value was unreachable, and because the cell entry carries the flat row index that drill-through reads drillRawRows by, the click drilled into another record's list. All of it silent. bucketId now encodes with JSON.stringify, whose quoting carries the boundary instead of a character the data is assumed never to contain. This renderer keys FOUR lookups off the same encoder — row headers, column headers, the row subtotal map and the column subtotal map — so the swap is wholesale; leaving any one on the old spelling would reintroduce the header-vs-subtotal split #3414 had just removed on the dashboard side. The encoders moved to @object-ui/core (pivotBucketId / pivotCellKey) and are now shared with plugin-dashboard, whose local copies they replace: both packages hand-rolling the same key is the reason the same collision had to be found and fixed twice. The dashboard's exports, call sites and behaviour are unchanged — its #3414 cases still pass. Tests assert behaviour, not key spelling: which bucket renders which measure, which raw record a colliding cell drills to, and which subtotal lands under which multi-dimension row. The pre-existing pivot cases use one row dimension and space-free values, where an empty separator is indistinguishable from a correct one — which is why they never saw either defect. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes objectstack-ai/objectstack#5665
问题
packages/plugin-report/src/DatasetReportRenderer.tsx的 matrix 交叉表把三类查找都建在「维度值拼接」上,两处拼接各自有缺陷:bucketId用真空串join('')—— 相邻维度值之间一个边界字符都没有。bucketId(['region','segment'], …)对x+yz与xy+z同样产出xyz。这条同时作用在行轴和列轴上(rid/cid都走它),两个不同的桶合并成一个,后写覆盖先写。rid/cid—— 与 fix(plugin-dashboard): 透视表 cell key 改用 JSON 编码,维度值含空格不再串格 (objectstack#5473) #3414 在 dashboard 修掉的完全同形。维度值含空格是常态(New York/In Progress),于是New×York Q1与New York×Q1落进同一个 key。合并后的桶显示的是另一行的度量,被覆盖那行的值取不到;
cells的 value 还带index,而 drill-through 正是用它读drillRawRows,所以点开的是另一条记录的列表。全程无任何报错。修法(与 PR #3414 同形,整体换)
bucketId改走JSON.stringify:边界由 JSON 自身的引号承载,不再依赖「数据不会包含的字符」。本渲染器有四处查找共用这一个 encoder —— 行表头、列表头、行小计
rowTotalById、列小计colTotalById—— 所以整体换:任何一处留在旧拼法,就会把 #3414 刚在 dashboard 侧修掉的「表头与小计各用一套编码」重新引进来。cell key 的set与get两处也一并换成pivotCellKey。共享 helper(按 PM 裁定核了依赖拓扑)
plugin-report与plugin-dashboard都workspace:*依赖@object-ui/core,且已有先例 ——buildDatasetDrillFilter正是为「两边 drill 行为一致」抽过去的。方向干净,因此:packages/core/src/utils/dataset-pivot.ts,导出pivotBucketId/pivotCellKey;DatasetWidget.tsx仅改 import(pivotBucketId as pivotRowId)+ 删本地 helper,导出面、调用点、行为一律不动,fix(plugin-dashboard): 透视表 cell key 改用 JSON 编码,维度值含空格不再串格 (objectstack#5473) #3414 的用例全部复跑通过;pivotBucketId而非pivotRowId:report 侧列轴也用它编码(dashboard 的 across 只有单维度,行轴才拼多值),叫 row 会在cid处误导。dashboard 侧用别名保留其原有本地名,不扩大改动面。两个包各写一份同样的 key,正是同一个碰撞被发现两次、修两次的根因;现在只有一份实现。
用例(钉行为,不钉 key 拼法)
新增 5 例,覆盖 issue 与 PM 点名的每一族:
x+yzvsxy+z21/2Q+1xvsQ1+x(含列小计)New×York Q1vsNew York×Q1New显示222111,缺失格为—objectFilter=NEW-YORK/Q1(另一行)NEW/YORK-Q1['1','2']反向验证方向(修前红 / 修后绿,预先判定并复现):先只加用例、不动实现,5 例全红,且失败形态与预测逐条吻合 —— drill 那例直接打出
billing_state: "NEW-YORK",即「钻到另一行」的实证。同文件既有 36 例始终绿:它们的 pivot fixture 行/列各只有一个维度、值不含空格,此时空串分隔与正确分隔不可区分,所以两个缺陷从未被跑到。消费半径清扫
grep全仓已无`${a} ${b}`形态的 map key;.join('')的其余命中都是图标名/首字母拼接,不是桶 id。plugin-dashboard/PivotTable.tsx用嵌套对象bucket[r][c]、单行单列字段,不属此类,无需改动。验证
vitest run packages/plugin-report/.../DatasetReportRenderer.test.tsx packages/plugin-dashboard/.../DatasetWidget.test.tsx→ 88 passed (2 files)type-check:@object-ui/core/plugin-report(含tsconfig.test.json)/plugin-dashboard全部 Donepnpm check:control-bytesOK,并对本 PR 全部改动文件做了越过 gate 的自扫(含0x01等 gate 不扫的字节),无命中已知残留(不在本 PR 范围)
null/undefined 维度值仍编码为占位符
∅,与字面等于该占位符的值相撞 —— 这是占位符的性质而非编码的,已由 objectstack#5666 单独跟踪,dataset-pivot.ts的注释里指了过去。🤖 Generated with Claude Code
https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
Generated by Claude Code