Skip to content

A dashboard global filter sourced from optionsFrom commits the display LABEL as its value — every widget it drives silently returns zero rows #4465

Description

@baozhoutao

Symptom

A dashboard global filter whose options come from optionsFrom (a live server GROUP BY, rather than a static options list) commits the rendered label as the filter value. Every widget bound to that filter then queries for a value that does not exist and repaints to "No rows".

Static, metadata-declared options are not affected — Revenue Pulse's region filter shows the label EMEA on the trigger and correctly commits the value emea.

Reproduction (2× in the browser, 1× on the API)

  1. Author a dashboard with an optionsFrom-sourced select filter and one bound widget:
globalFilters: [{
  name: 'st', field: 'status', label: 'Status', type: 'select', scope: 'dashboard',
  optionsFrom: { object: 'showcase_task', valueField: 'status', labelField: 'status' },
}]
widgets: [{ type: 'bar', dataset: 'showcase_task_metrics',
            dimensions: ['status'], values: ['task_count'] }]
  1. Publish, open it as admin, open the Status select and pick In Review.

Expected the widget re-queries with status = 'in_review' and draws 2 tasks.
Actual the widget re-queries with runtimeFilter { "status": "In Review" } and renders "No rows" (0 bars). Same with In Progress.

Confirmed on the API from both sides:

  • runtimeFilter {status:'In Review'}{"rows":[]}
  • runtimeFilter {status:'in_review'}{"rows":[{"status":"In Review","task_count":2}]}

Root cause

The option-source response carries both forms, and the filter bar reads the wrong one:

  • rows → server-resolved display labels: [{status:'Backlog'},{status:'Done'},{status:'In Progress'},{status:'In Review'},{status:'To Do'}]
  • drillRawRowsraw values: [{status:'backlog'},…,{status:'in_review'},{status:'todo'}]

packages/plugin-dashboard/src/DashboardFilterBar.tsx reads r?.[from.valueField] off rows (the dataset branch, ~line 204 on main) and never consults drillRawRows, so the label becomes the committed value.

Sharpening contrast on the same page: the drill path consumes the same response correctly — clicking a Backlog bar issues GET /api/v1/data/showcase_task?filter=["and",…,["status","=","backlog"]] with the raw value. Two consumers of one response; one right, one wrong.

Not a stale-bundle artifact

DashboardFilterBar.tsx's optionsFrom resolution is unchanged between the vendored console pin (6314e87f2d49) and current origin/main (b4d3c2204) — same reads of from.valueField off rows, no drillRawRows consumer on either ref. Checked line by line rather than by diffing whole files.

Suggested shape (not prescriptive)

Pair each option as {value: drillRawRows[i][valueField], label: rows[i][labelField ?? valueField]} so the committed value is always the raw one, and fall back to rows only when drillRawRows is absent. Whatever the shape, the gate that keeps it fixed is a test asserting the committed filter value for an optionsFrom select equals the raw value, not the rendered label — the current tests only assert the option list renders.

Source

Found by the platform checklist retest of dashboards.global-filters-rescope (framework 279ee48a, console pin 6314e87f2d49).

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions