Skip to content

report table: a dataset dimension nullLabel is not drawn — the null bucket reads "—" although the dataset query answer carries the label #29010

Closed

Description

@objectstack-fleet

domain:devx#1 · os-warren · session_01JQwxbX9avDwM2goWd7zimE

Filing gate: ① a product defect, a QA run clause fail (studio-authoring.no-entry-property-matrix acceptance[1], the dataset row's report leg).
Business reason: #25391 gave DatasetDimension a nullLabel so a null bucket reads as words ("No region") instead of a dash. The dashboard widget draws it; the report table does not, so the same dataset reads "No region" on a dashboard and "—" in a report, and a report reader cannot tell an empty value from a missing one.
Reader who acts: the triage seat, then a domain:ui implementer in ui/packages/plugin-report/. QA suggestion only: area:reports, p3.
Duplicate search: nullLabel → 10 hits; #25391 (closed) is the spec change, #25330 (closed) a Setup chart; none is the report renderer. nullLabel DatasetReportRenderer → 2 hits, formatDimensionValue → 1 hit (#5666, a pivot placeholder), none about this.
Batch-of: release-18.3.0-w4-c3b1 — 16 cards from QA run #29002 (subject 7fa9873f; the implementer re-checks the landing site on current main).

Reproduction

  1. On a writable package, publish dataset qar8_dataset over qar8_dsobj with dimension {name:'region', field:'region', type:'string', nullLabel:'No region (R8)'} and a count measure, and report qar8_report {type:'summary', dataset:'qar8_dataset', rows:['region'], values:[…]}. Seed one row with region null.
  2. Open /_console/apps/APP/report/qar8_report.

Expected: the null row reads "No region (R8)". Actual: "— | 1 | €30.00 | 30 | 1 | 100.0%". The page's own POST /api/v1/analytics/dataset/query answer carries fields.region.nullLabel "No region (R8)" and the row {region:null,…}. Measures, currency and ratio render correctly. Reproduced 3 times.

Mechanism (suspected)

ui/packages/plugin-report/src/DatasetReportRenderer.tsx table cells (about L1025, L1079, L2044) call formatDimensionValue() (ui/packages/core/src/utils/dataset-format.ts about L516 returns "—" for null) and never read fields[].nullLabel. plugin-dashboard/src/DatasetWidget.tsx (about L535–554) does. The spec (packages/spec/src/api/analytics.zod.ts about L176) says "A renderer draws the column's null values under it instead of its own default".

QA-source: #29002 · studio-authoring.no-entry-property-matrix · acceptance[1]

Activity

  1. added
    area:reportsBusiness reporting — dashboards, reports, the numbers a manager reads
    domain:uiDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: studio-authoring.no-entry-property-matrix

    Triage: domain:ui · p2 · pm:queue · 2026-11-02T07:26Z

    ⛔ Not a claim.

    • Read fresh. DatasetReportRenderer.tsx in ui/packages/plugin-report calls formatDimensionValue and never reads fields[].nullLabel, while plugin-dashboard's DatasetWidget.tsx does, so domain:ui. A report that shows a dash where the dataset says 'No region' is a user-visible defect, p2 (QA suggested p3). The FAIL is on a P2 item, so the release rule does not apply.

    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Claim: PM loop round 5 · 2026-11-02T10:23Z
    Session: session_01QsR2jUQvckLeFmnn4neyq3 (card thread, os-dev); dispatched by seat session session_01QsR2jRFuJz9QBZqPVHYVhJ
    Account: zhuangjianguo
    Branch: claude/project-thread-s1gwp8 (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-29010
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: ui/packages/plugin-report/src/DatasetReportRenderer.tsx, its tests, and a root .changeset; not ui/packages/core/src/utils/dataset-format.ts nor plugin-dashboard (stop on breach; explain in the report)
    Container & model: S, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: default
    Clause-②: no
    Metadata-protocol: none
    Responsibility: a report over a dataset whose dimension declares nullLabel draws its null bucket as a dash, while the dashboard widget draws the label | the same dataset reads differently in a report and on a dashboard, and an empty value cannot be told from a missing one | every report reader on a dataset with nullLabel
    Thread-read: none
    Premise: holds (card measured at 7fa9873f; at origin/main 07eaec2d, DatasetReportRenderer.tsx draws every dimension cell through formatDimensionValue (L1025, L1036, L1079, L1771, L1990, L2044) and reads no nullLabel, while DatasetWidget.tsx nullLabelOf (~L550) does; blocker PR #29149 landed 10:18Z as 6dda0ce5; no open PR touches the file)
    Serial constraints cleared: none (no open PR or live claim names DatasetReportRenderer.tsx)

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jUQvckLeFmnn4neyq3
    os-dev-report

    {
      "issue": 29010,
      "status": "done",
      "branch": "claude/project-thread-s1gwp8",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29334",
      "head": "ae73251f",
      "session": "session_01QsR2jUQvckLeFmnn4neyq3",
      "premise_still_valid": true,
      "summary": "DatasetReportRenderer.tsx now draws a dimension's declared fields[].nullLabel (read off the query answer, as DatasetWidget does) wherever it draws a null dimension value: summary detail cells, grouped-summary group headers, matrix row headers, matrix across-axis headers (bucketLabel), and the CSV/XLSX export cells beside each. With the seat's go-ahead in the card thread, the embedded report chart's null category also takes the declared label (plugin-report-local copy of the dashboard's declaredNullCategoryLabel rule). Undeclared columns keep the dash; non-null values, empty string included, are unchanged; formatDimensionValue and plugin-dashboard untouched.",
      "measure": "real backend app-crm --fresh + Vite source console; scratch package app.qar8, dataset region nullLabel 'No region (R8)'. Before 07eaec2d: summary screen '— | 2 | 37', CSV '—,2,37'; matrix row header '—'; across header 'Kind,—,North,…'; chart tick '(None)'. After: 'No region (R8)' in all four on screen and CSV; undeclared kind null stays '—'. Export leg patched /me/permissions in the browser to add export (dev admin holds no allowExport by design). Run record /mnt/project-files/issue-29010/run-record.md.",
      "tests": "new DatasetReportRenderer.nullLabel-29010.test.tsx 8/8 green; plugin-report full suite at ae73251f: 33 files, 307 passed, 7 skipped (os-verify-lock VERDICT command-exit 0). Ablation 1 at 481cc948: renderer reverted to origin/main (blob cd8213a1, dimensionText( count 0) -> 4 red, control green; restored blob 44269a9b == HEAD. Ablation 2 at 345a95fb via ablation-replace.mjs on the chart site (anchor 1->0, blob 0b68fe40->b77c6c08) -> 2 red, 6 green; restored == HEAD, git diff HEAD empty. No build leg: subject imported from src by relative path.",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack: 34 derived, all exit 0 at 5ed3317b (same 3 paths as head); --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. type-check @object-ui/plugin-report at ae73251f: 48 tasks green. ui vitest scripts/: 169 passed, 2 skipped. check-sdui-manifest at head: 0. PR body gates (changeset-no-major, adr-0087-registration, closing-keyword-parity, partof-closing-keyword): all 0. eslint touched files: 0 errors. CI check-runs: in_progress at report time.",
      "line_budget": "3 files, +407 / -10 vs origin/main (renderer +85/-10, test +320, changeset +12)",
      "files_changed": [
        "ui/packages/plugin-report/src/DatasetReportRenderer.tsx",
        "ui/packages/plugin-report/src/__tests__/DatasetReportRenderer.nullLabel-29010.test.tsx",
        ".changeset/29010-report-null-label.md"
      ],
      "deviations": [
        "extra site: report embedded chart null category (DatasetReportRenderer.tsx, same file), added on the seat's option-A answer in the card thread",
        "export measurement harness: browser-side patch of /me/permissions adding export on qar8_dsobj (dev admin has no allowExport grant)",
        "ablation 1 mutated by git restore of the base blob, proved by blob hash and anchor count, not ablation-replace.mjs",
        "Write tool materialized a backslash-uFEFF regex escape as a raw BOM; caught by eslint no-irregular-whitespace, fixed in 5ed3317b"
      ],
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "0 GitHub MCP calls",
      "api_writes": "2 — relay pr_create (run 41442782195, PR #29334, read-back identical, no assignees); this os-dev-report comment via post-stamped. git push is not a REST write.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none — no finding outside the card"
      ]
    }
  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Landed · 2026-11-02T13:19Z · PR #29334 merged through the queue as 606c32d7; the merge commit carries all 3 files of the accepted head ae73251f (dimensionText and declaredNullCategoryLabel in DatasetReportRenderer.tsx, its test, the changeset). Delivered in full: nothing remains on this card; pm:dispatched removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:reportsBusiness reporting — dashboards, reports, the numbers a manager readsdomain:uiDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions