fix(ux): P0 — dashboard dataset widgets, detail field leak, startup race - #103
Merged
Conversation
Three P0 issues surfaced by the mobile UX walkthrough:
1. Dashboard widgets spun forever. 8.0-spec widgets reference an analytics
`dataset` (+ `values`/`dimensions`) instead of a raw `object`, so the data
hook ran `useQuery` disabled — and `useQuery` leaves `isLoading: true`
forever when disabled. Resolve each dataset to its base object + measure
aggregate + dimension field (client-side aggregation, no dependency on a
server analytics endpoint the published runtime may not mount), and
short-circuit any still-unqueryable widget to a terminal empty state. Also
fix count-aggregate charts returning all-zero buckets when the count
measure has no value field, and add `{current_week_start}` / `{N_weeks_ago}`
filter macros the widgets use.
2. Detail screen leaked `Organization Id` (and other injected tenancy /
metadata-hidden fields) at the top of the auto-layout. The fallback now
mirrors the form's `isEntryField` filtering.
3. Cold start fired a storm of connection-refused requests against the default
API host before `hydrate()` re-targeted the clients. Gate the whole app
shell (auth session + data providers + navigation) on hydration so the
first request — including better-auth's get-session — hits the configured
server. Verified zero stale-host requests on reload.
All three verified in the browser against a live app-todo server (widgets show
real data + proper empty states, detail leads with Subject, no :3100 storm).
+9 tests; 1275 pass, typecheck + lint clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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 the three P0 issues from the mobile UX walkthrough. Verified in-browser against a live
app-todoserver (8.0 dataset dashboard).1. Dashboard widgets span forever → real data + terminal states
8.0-spec widgets declare an analytics
dataset(+ values/dimensions/layout/options) instead of a rawobject. The data hook ranuseQuerydisabled, anduseQueryleavesisLoading: trueforever when disabled — hence the perpetual spinners.resolveDatasetWidget()resolves a dataset → its baseobject+ the measure'saggregate/valueField+ the dimension'scategoryField, then reuses the existing client-side aggregation. No dependency on a server analytics endpoint (the dev/published runtime's/analytics/queryis unreliable / may be unmounted).useWidgetQueryshort-circuits any still-unqueryable widget to a terminal empty state — never a stuck spinner.buildChartDatareturning all-zero buckets for a count chart with no value field (the common dataset case).{current_week_start}/{N_weeks_ago}filter macros the widgets use.Result:
Total Tasks 8,Tasks by Status/Categorycharts render real grouped data,Overdue/Due Today/Weeklyshow proper No data — zero infinite spinners.2. Detail screen leaked
Organization IdThe no-form-view fallback laid out raw
Object.keys(record), leaking injected tenancy keys (organization_id) and metadata-hidden fields at the top. It now mirrors the form'sisEntryFieldfiltering (drops internal/tenancy +hidden/systemfields). Detail now leads with Subject.3. Cold-start request storm against the default host
Before
hydrate()re-targeted the clients, the whole nav tree mounted and fired session/notifications/meta/dashboard requests at the default API host — a storm ofERR_CONNECTION_REFUSED(and the dev-overlay error). The app shell (auth session + providers + navigation) is now gated on hydration, so the first request — including better-auth'sget-session— hits the configured server. Verified zero stale-host requests on reload.Tests
+9 tests (dataset resolution, count-chart fix, spinner guard, week macros, detail field filtering). 1275 pass, typecheck + lint clean.
🤖 Generated with Claude Code