fix(dashboard,charts): send widget query options to the server, order funnel stages by the pipeline (framework#3588) - #2864
Merged
Conversation
… funnel stages by the pipeline (framework#3588)
`DatasetWidget` never read `widget.options`. Four keys an author writes there
change the query the server compiles, so a widget declaring
`options: { dateGranularity: 'month' }` grouped by the raw timestamp and drew
one bar per record, and `sortBy`/`sortOrder` produced no ordering at all.
- `DatasetWidget` lowers `options.dateGranularity`, `options.sortBy` +
`options.sortOrder`, and `options.limit` into the `DatasetSelection` it posts.
A `sortBy` naming something the widget does not project is dropped rather than
sent, so a stale sort key left by an edit degrades to "unordered" instead of
failing the widget against the server's stricter validation. These keys join
the refetch signature, so editing one in the designer refetches instead of
re-rendering the previous grid.
- Funnel stages follow a declared order. `AdvancedChartImpl` sorted funnel
segments by value descending, unconditionally — overriding any server ordering
and rendering a sales pipeline as a tidy narrowing shape whatever the stages'
real sequence, which hides the very anomaly (a bulge at Proposal) the chart
exists to show. It now honours `categoryOrder`, derived from the dimension
field's picklist option order — the pipeline order already declared on the
object — or from an explicit `options.stageOrder`. With no declared order the
value-descending default is unchanged, and a category missing from the order
is kept after the declared ones rather than dropped.
- New `@object-ui/core` helpers `buildCategoryOrder` / `buildCategoryRank`,
keyed by both stored value and display label like `buildOptionColorMap`, so
ordering works whether or not the server resolved the dimension's labels.
Requires the framework-side fix in objectstack#3588 for the selection keys to
take effect server-side.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEZLBGyNoJMLvtGPqsMPRC
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
os-zhuang
marked this pull request as ready for review
July 27, 2026 13:24
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.
Renderer half of objectstack-ai/objectstack#3588. Framework half: objectstack-ai/objectstack#3652 — the selection keys added here need it to take effect server-side.
The problem
DatasetWidgetnever readwidget.optionsat all. Four of the keys an author writes there are not presentation-only — they change the query the server compiles — so a widget declaringoptions: { dateGranularity: 'month' }grouped by the raw timestamp and drew one bar per record, andsortBy/sortOrderproduced no ordering whatsoever.The issue filed this as one framework bug. Two of the three symptoms were, but the funnel one is entirely on this side, and it would have survived any amount of server work:
AdvancedChartImplre-sorted funnel data by value descending, unconditionally, so a correctly-ordered response was overridden client-side before it ever painted.Changes
Widget options reach the query.
DatasetWidgetlowersoptions.dateGranularity,options.sortBy+options.sortOrder, andoptions.limitinto theDatasetSelectionit posts. Two details worth review:sortBynaming something the widget doesn't project is dropped rather than sent. The server now rejects unresolvable order keys with a 400, and a stale sort key left behind by an edit should degrade to "unordered", not blank the widget.Funnels follow a declared stage order. The old unconditional value-sort is the interesting part of this PR. It's a reasonable default for a generic funnel, but for a sales pipeline it manufactures a tidy narrowing shape regardless of the stages' real sequence — which hides the exact anomaly (a bulge at Proposal) the chart exists to reveal.
AdvancedChartImplnow honours acategoryOrder, whichDatasetWidgetderives from the dimension field's picklist option order — the pipeline order an author already declared on the object, so nothing new to author — or from an explicitoptions.stageOrderoverride.With no declared order the value-descending default is byte-for-byte unchanged, and a category missing from the declared order is kept after the declared ones rather than dropped.
New core helpers.
buildCategoryOrder/buildCategoryRank, keyed by both the stored value and the display label exactly like the existingbuildOptionColorMap, so ordering works whether or not the server resolved the dimension's labels before the rows arrived.Testing
DatasetWidget.queryOptions.test.tsx(7) — asserts on the selection handed toqueryDataset, which is the seam the bug lived at: the widget rendered fine and the query ran fine, only the payload was missing what the author wrote. Covers the drop-unprojectable-sortBy path and the refetch-on-change path.AdvancedChartImpl.funnelOrder.test.tsx(5) — renders a real funnel and reads the segment labels in draw order, with fixture data deliberately not monotonically narrowing so a value sort and the declared order produce visibly different output. A first draft of this test passed while asserting nothing (it read anameattribute that recharts doesn't emit, then early-returned); it now asserts on the<text>labels and is guarded by a test that fails if the funnel renders empty.category-order.test.ts(8) — the pure ordering helpers.@object-ui/core,@object-ui/plugin-charts,@object-ui/plugin-dashboard: 1308 passed, 24 skipped.type-checkclean,lint0 errors on all three.Not driven in a browser — the granularity/sort halves need objectstack#3652 deployed to show a visible difference, so end-to-end verification is worth doing once both land.
Generated by Claude Code