Skip to content

analytics: ready for React 19 and Router 7 (drizzle-cube 0.12.2) - #14

Merged
robinbowes merged 6 commits into
mainfrom
feat/analytics-react19-ready
Nov 3, 2026
Merged

robinbowes merged 6 commits into
mainfrom
feat/analytics-react19-ready

Conversation

@robinbowes

Copy link
Copy Markdown
Contributor

Step 1 of the React 19 / Router 7 move: analytics compiles and runs on today's kit (React 18, Router 6) and on React 19.3 with Router 7.18, so the kit can move next. Imports stay on react-router-dom; switching to react-router is 4.0.0.

Summary

 plugins/analytics/
   rocketflare-plugin.json, plugin.json   (both copies)
-    "drizzle-cube": "0.8.3"
+    "drizzle-cube": "0.12.2"             # declares React 19 peers; fixes GHSA-g3qv-p2w6-c95h
-    '@nivo/heatmap': path.resolve(__dirname, …)
+    '@nivo/heatmap': path.resolve(import.meta.dirname, …)
   ui/pages/QueryBuilderPage.tsx
-    builder: React.RefObject<AnalysisBuilderRef>
+    builder: React.RefObject<AnalysisBuilderRef | null>
   tests/ui/date-filter.test.tsx
-    <MemoryRouter future={{ v7_startTransition, v7_relativeSplatPath }}>
+    <MemoryRouter>

drizzle-cube 0.8.3 → 0.12.2 only adds optional fields to the types the plugin imports, and reads stored analytics_pages configs unchanged. Three of its behaviour changes needed code:

Recent Members portlet (no timeDimensions)
  mapping: [TIME_FILTER]  →  [{ filterId: TIME_FILTER, member: 'TenantUsers.joinedAt' }]
  (0.10.1+ warns on a card a universal date filter cannot reach; all-templates test now fails that)

dashboardDateFilters(config, range)
  overrides filter.values  →  filter.values AND filter.dateRange
  (drizzle-cube reads dateRange first; a saved one froze the page's 7/30/90 control)

AnalyticsDashboard
  + onDashboardFiltersChange → useDashboardDateFilter.setFromFilter
  (0.12.2 shows its own filter bar to viewers and disables host-owned filters without it)
  URL: ?range=7d|30d|90d|custom (unchanged)  +  ?range=rel&rel=<server-parseable range>

The analytics* skills, README and dashboard docs now name 0.12.2 and its query rules (no server gap fill, unparseable dates and ungrouped measure filters are 400s). docs/upgrades/unreleased.md has the porting note; breaking: false.

Evidence

All in scratch kit worktrees on kit main (2b2558c, 0.24.0), plugin installed from this branch.

  • Before (earlier kit session, same day): on React 19.3.1 / Router 7.18.5 with analytics 3.4.2 the kit's typecheck failed (TS2322 at QueryBuilderPage.tsx:77, and the future prop on MemoryRouter).
    After:

    Host pnpm gate Browser
    React 18.3 / Router 6.30 / Vite 8 exit 0 · 1870 passed, 5 skipped ✓
    React 19.3.1 / Router 7.18.5, kit future props removed exit 0 · 1870 passed, 5 skipped ✓
    analytics 3.7.0 → this branch via pnpm plugin upgrade exit 0 · 1867 passed, 8 skipped, after the porting note's Biome step ✓

    Browser on each: both seeded dashboards render; Explore runs a query; Save to dashboard adds the portlet; the grid editor opens; no console errors. On React 19 the lockfile resolves one react-router (7.18.5) and one react-dom (19.3.1).

  • Before: the date-control test with a saved dateRange failed — expected "dateRange": "last 7 days", received "last 30 days".
    After: passes; 26/26 analytics UI tests.

  • Before: drizzle-cube's filter bar showed greyed out, "This filter is controlled by the host application", beside the page control.
    After: clicking 3M in the bar sets ?range=rel&rel=last+3+months and moves every mapped chart; clicking "Last 30 days" on the page selects 30D in the bar.

  • Before: with the old [TIME_FILTER] mapping restored, all-templates fails: recent-members needs timeDimensions or a member for time-filter.
    After: passes; at "Last 7 days" Recent Members lists the 2 members who joined in that window.

  • Upgrade path: plugin upgrade replaces the alias line in place (one '@nivo/heatmap': path.resolve( line, no __dirname) and leaves stored dashboard configs byte-identical. It does not run Biome on the replaced line, so the note adds a format step. A pre-upgrade page shows the "does not narrow" warning on Recent Members until it is reset (template pages) or remapped in the editor (copies); both were checked.

Not in this PR:

  • (!) Some chunks are larger than 500 kB: present with 0.8.3 too (exceljs, 907 KB); a follow-up PR.
  • /api/analytics/facts/status reads max() across all tenants when TENANT_SCOPE_MODE is off; a follow-up PR.
  • Kit: plugin upgrade does not Biome-format core edits; plugin add runs pnpm install without minimum-release-age.

Merge Danger

Door: two-way

Nothing is released until node scripts/release.mjs 3.8.0. After release, an installed copy rolls back with pnpm plugin upgrade analytics --to 3.7.0; no schema change.

Blast Radius: dashboards

Every host with analytics gets drizzle-cube 0.12.2 on upgrade. Raw /cubejs-api/v1/load and MCP load callers no longer get zero-filled time buckets unless they set fillMissingDates: true; dashboards and Explore look the same. Pre-existing Organisation Overview pages show a warning on Recent Members until reset or remapped.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com

robinbowes and others added 6 commits November 3, 2026 15:22
Widen SavePortletModal's builder ref to RefObject<T | null>, drop the
removed v7 future flags from the date-filter test's MemoryRouter, and
resolve the @nivo/heatmap alias with import.meta.dirname so Vite 8's
native config loader stops warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0.12.2 declares React 19 peers and fixes a stored XSS in markdown
portlets. Its types only gain optional fields and it reads stored
dashboard configs unchanged.

Since 0.10.1 drizzle-cube warns on a portlet mapped to a universal time
filter it cannot reach, so Recent Members now pins the filter to
TenantUsers.joinedAt, and the template test fails such a mapping. The
skills and docs describe 0.12.2's query rules: no server gap fill,
granularity-less time dimensions filter only, unparseable dates and
ungrouped measure filters are 400s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
drizzle-cube resolves a universal time filter from dateRange before
values, and its filter editor saves both. dashboardDateFilters only
replaced values, so once a dashboard's date filter had been edited the
page's 7/30/90-day control no longer changed that dashboard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The kit's vite.config.ts names '@nivo/heatmap' in a comment, and Biome
splits the alias across lines, so counting the bare name prints 2 on a
correct install.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0.12.2 shows its own date filter bar to viewers and disables a filter
the host owns unless the host takes its changes. The dashboard now
passes onDashboardFiltersChange, so both controls drive the same URL
state. A bar choice the page buttons don't offer, such as last 3 months
or this quarter, is kept as ?range=rel&rel=<range>, checked against the
relative ranges the server parses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
plugin upgrade replaces the heatmap alias line but does not run Biome,
so the gate fails lint until vite.config.ts is formatted. Pages copied
from Organisation Overview keep the old mapping and cannot be reset, so
the note says how to remap the card instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@robinbowes
robinbowes merged commit 1bb4437 into main Nov 3, 2026
15 checks passed
@robinbowes robinbowes mentioned this pull request Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant