Repository navigation
feat(plugin-report): the report page exports the drawn table as CSV / XLSX (exportOptions) - #27089
Conversation
…drawn table (exportOptions) Claude-Session: https://claude.ai/code/session_01JQwxbYfDeaywgrS5N1PZfg Co-authored-by: Claude <noreply@anthropic.com>
…s liveness to live Claude-Session: https://claude.ai/code/session_01JQwxbYfDeaywgrS5N1PZfg Co-authored-by: Claude <noreply@anthropic.com>
… raw byte Claude-Session: https://claude.ai/code/session_01JQwxbYfDeaywgrS5N1PZfg Co-authored-by: Claude <noreply@anthropic.com>
…t the flip Claude-Session: https://claude.ai/code/session_01JQwxbYfDeaywgrS5N1PZfg Co-authored-by: Claude <noreply@anthropic.com>
…/types; regenerate liveness counts Claude-Session: https://claude.ai/code/session_01JQwxbYfDeaywgrS5N1PZfg Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift Check
What this run could not see
Coarse fallback — 147 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
…headers are data values Claude-Session: https://claude.ai/code/session_01JQwxbYfDeaywgrS5N1PZfg Co-authored-by: Claude <noreply@anthropic.com>
席位核对ACCEPT · 席位意见:报表页导出的就是屏幕上画出的那张表(含服务器合计),不重新查询;导出按钮按基础对象的
|
…-p301jn # Conflicts: # packages/lint/src/lint-liveness-properties.test.ts # ui/packages/plugin-report/src/DatasetReportRenderer.tsx
Claude-Session: https://claude.ai/code/session_01JQwxbYfDeaywgrS5N1PZfg Co-authored-by: Claude <noreply@anthropic.com>
席位核对ACCEPT · 席位意见:#27070 合并后按约定合入 main,导出代码与已审版本一致,只把日期芯片和导出按钮并到同一行表头,lint 测试改为两个键都静默并带有仍会告警的对照项。
|
Requested by Warren · project thread
Refs #25873 (item: the report page reads exportOptions)
Clause-②: no
Metadata-protocol: none
维护者速读
exportOptions从 planned 翻为 live。exportOptions,但没有渲染器读它,报表无法带去开会。export操作判定,无提供者时照列表默认放行;回滚 = revert 本 PR。ui/packages/plugin-report/src/ReportExport.tsx(权限判定与文件写出),DatasetReportRenderer.tsx两处快照块,packages/spec/liveness/report.json的 exportOptions 子树。pnpm --dir ui exec vitest run packages/plugin-report/src/__tests__/DatasetReportRenderer.export-25873.test.tsx,预期 11 个用例全绿。What changes
ui/packages/plugin-report/src/ReportExport.tsx.ReportExportControldraws an Export popover offering the declared formats (absent = CSV and XLSX in that order,formats: []= no control). It reads the report'sexportOptions,labelandname.DatasetReportTable(tabular / summary) andDatasetMatrixTablebuild a snapshot of exactly the cells they render (header labels, rows in layout order, server totals row and totals column) and hand it up throughReportTableSnapshotContext, keyed on content, not identity (ui AGENTS chore: version packages #10). The download re-queries nothing and re-aggregates nothing, so it inherits the table's ownruntimeFilterand, once feat(plugin-report): the report page reads dateRange — a period chip and one timeDimensions window #27070 lands, its period.object) includeexport, the list toolbar's predicate, read throughusePermissions().getObjectApiOperationsfrom@object-ui/permissions. An absent set (no provider, an unrestricted object) keeps it, as on the list.ReportExportEngineuses (a formatted measure keeps its minus); the tab guard applies to data cells and to every header cell (a matrix's across headers are data values). XLSX: one sheet named for the report, header bold, measure cells as numbers, dimension cells as drawn text; ExcelJS isimport()ed only when an XLSX is asked for. File name =buildExportFileNamefrom@object-ui/core(the list export's builder):fileNamePrefix, else the report label, else the name, plus a local timestamp.includeHeaders: falsedrops the header row.joined(the spec refusesexportOptionsthere): the joined branch mounts no snapshot context, so its blocks publish nothing and no control is drawn.@object-ui/plugin-reportnow depends on@object-ui/permissions(workspace:*) andexceljs(^4.4.0, the version@object-ui/plugin-gridalready pins);pnpm-lock.yamlgains the importer lines only (+6).packages/spec/liveness/report.jsonexportOptionssubtree flipped tolivecitingReportExport.tsx#ReportExportControl,authorWarn/authorHintdropped in the same edit;state-counts/report.mdregenerated (gen:liveness-counts).packages/lint/src/lint-liveness-properties.test.ts, the spec(report): a report declares a dataset-dimension date range and export options #26548 block, seat-accepted deviation): rewritten as a silence pin forexportOptionswith an anti-vacuity read of the live row;dateRangestill warns in the same call, so the ledger is proven loaded..changeset/25873-report-export.md:@object-ui/plugin-reportpatch.Why
Ruling 6408567749 on #25873, letter B: "A, plus CSV / XLSX export of the report table through the existing list-export permission". The spec half shipped in #26548 (PR #26628); until this PR no renderer read
exportOptions, so the key was inert.Tests
New
ui/packages/plugin-report/src/__tests__/DatasetReportRenderer.export-25873.test.tsx, 12/12:Totalrow), formula guard on the data cell only, file name from the label.formatsoffers CSV and XLSX;formats: ['csv']offers only CSV;formats: []draws no control.apiOperationson the base object excludeexportsees no control; CONTROL: same provider withexportshows it; CONTROL: no provider shows it.includeHeaders: falsedrops the header row;fileNamePrefixnames the file.Ablation (at 54aa045,
node scripts/ablation-replace.mjs): deleting the predicate line inReportExportControl(anchor x1 to x0, blob 7eae13a4 to b22beff9) turns exactly 1 of 11 red, theapiOperationsrefusal test; restored blob 7eae13a4 equals the HEAD blob,git diff HEADempty. No dist leg: the test imports the renderer by relative path.Acceptance notes
liveness/report.json(disjoint subtrees) and itsstate-counts/report.md. Whichever lands second mergesmain: keep both children (ideally one header row: chip left, Export right), make the lint block a silence pin for both keys with another warned control (the [Decision] A greyed-out record action can only say 对此记录不可用 — re-ask for an authored disabled reason now that a second app needs it (re-file per #24034 B′) #26619 pattern usesobject.externalSharingModel), and rerungen:liveness-counts.viewLabelslot; noted for whichever PR lands second.Verification
Head
858f0fe5:pnpm --filter @object-ui/plugin-report run type-check && pnpm --dir ui exec vitest run packages/plugin-report/ && pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 src/lint-liveness-properties.test.tsunder the verify lock: VERDICT command-exit 0; plugin-report 29 files, 269 passed / 7 skipped; lint 110/110.node scripts/pm/dispatch-gates.mjs --commands: 83 families;--ranreconciliation: 82 run, all exit 0, 1 NOT MEASURED (pnpm check:dual-build-cjs-loads, exit 3, PREREQUISITE NOT MET: not every package hasdist/locally; CI runs it). First readings that were red and repaired on this branch:pnpm --dir ui exec vitest run scripts/(one-authority-per-exported-name:ReportExportFormatcollided with@object-ui/types, renamedReportTableExportFormat),check:liveness(state counts stale, regenerated),check-plugin-teardown-shape --self-test(exit 3, control sha outside the shallow clone, fetched).node scripts/check-sdui-manifest.mjsexit 0.pnpm --dir ui run check:new-line-citationsexit 0 (0 new); eslint on the three touched plugin-report files: 0 errors (react-refresh warnings only, same rule the renderer already carries);node scripts/check-nul-bytes.mjsexit 0.Human Minimum
packages/specholds no runtime logic.pnpm lintpasses. (No formatter ran; repo-widepnpm lintis CI-owned.)main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code