Skip to content

Charts improvements#115

Merged
p-hoffmann merged 31 commits into
developfrom
feat/shared-chart-components
Jun 20, 2026
Merged

Charts improvements#115
p-hoffmann merged 31 commits into
developfrom
feat/shared-chart-components

Conversation

@p-hoffmann

Copy link
Copy Markdown
Member

Summary

Promotes the ECharts chart components into the shared @ohdsi/atlas-ui design-system library (with Histoire stories) and fixes a categorical-axis regression where time-series and numeric line charts were rendered on an evenly-spaced category axis instead of a real time/value axis.

Shared chart library

  • New components under src/components/ui/charts/: AtlasLineChart, AtlasPieChart, AtlasBarChart, AtlasTreemapChart, AtlasSunburstChart, AtlasBoxPlotChart, AtlasTrellisChart, and AtlasChartExport — each with a .story.vue / .story.md.
  • Exported from packages/atlas-ui/index.ts together with the chart data types (LineChartData, ChartXAxisType, PieChartData, …) and option-builders, so plugin developers can consume them.
  • echarts / vue-echarts are now peerDependencies and externalized from the library build (vite.lib.config.ts) — the published bundle no longer ships ~1 MB of echarts (dist ≈ 134 KB).
  • chart-config relocated from src/utils/ to src/ui/ (library source tree).

Axis-type fix

  • Line option-builders gained an xAxisType: 'category' | 'value' | 'time' mode, defaulting to 'category' for backward compatibility.
  • YYYYMM month codes are parsed to UTC timestamps (parseYyyymm); value/time series are emitted as [x, y] point pairs.
  • The data-mapping functions now emit xAxisType + aligned monthCodes / xValues, so:
    • time axis: Observations-by-Month, Data-Density monthly records, Death prevalence-by-month, Drilldown prevalence-by-month
    • value axis: Cumulative Observation, Observation-Period cumulative
  • This matches the continuous scales used by the original OHDSI Atlas (scaleTime / scaleLinear); missing months and irregular gaps now render proportionally instead of being collapsed to even spacing.

Migration

  • All report/datasource call-sites switched to the shared components (importing from source via @/components/ui/charts/*).
  • Old reports/charts/{PieChart,BarChart,LineChart}.vue and the temporary chart-config re-export shim removed; existing tests migrated to the new components.
  • MultiLineChart and the dashboard chart wrappers were kept and made axis-aware.

Testing

  • type-check, lib:build, and all chart / formatter / datasource-chart / option-builder test suites pass.
  • New unit tests cover parseYyyymm, the three axis modes, and the time/value builders.

Follow-ups (non-blocking)

  • The monthCodes! / xValues! non-null assertions in the dashboard builders could use a dev-time guard.
  • defaultLineChartOptions is now legacy (no production call-site) and could be retired.

@p-hoffmann p-hoffmann force-pushed the feat/shared-chart-components branch from 23b95be to 2560b1c Compare June 20, 2026 15:33
…ineXAxis

The shared buildLineXAxis helper was missing the axisLabel config
(rotate/hideOverlap/fontSize) that both multiLineChartOptions and
defaultLineChartOptions had before the refactor. Adds it back in the
category branch and adds a covering test.
…Options builder

Replace CategoryLineSeries/ScalarLineSeries union (ScalarLineSeries.data was
[number,number][] which never matched the builder) with a single LineChartSeries
(data: number[]) and an expanded LineChartData that mirrors MultiLineChartData's
shape (xAxisType, categories, monthCodes, xValues). Widen multiLineChartOptions
to accept UILineChartData | DatasourceMultiLineChartData so AtlasLineChart can
use LineChartData from @/ui/chart-types as its prop type without a cast.
Promotes TreemapChart, SunburstChart, BoxPlotChart, and TrellisChart
into src/components/ui/charts/ with the Atlas prefix, fixes chart-config
imports, repoints 8 call-site importers, adds Histoire stories and
exports all four from packages/atlas-ui/index.ts.
Repoint PieChart/BarChart imports in ObservationPeriodReport, DeathReport,
PersonReport, and DrilldownDetails from old reports/charts/* components to
AtlasPieChart/AtlasBarChart. Migrate DrilldownDetails LineChart to
AtlasLineChart with x-axis-type="time" and reconstructed monthCodes from
MM/YYYY date strings.
Fix the categorical-axis regression for time-series and numeric line
charts. Data formatters now set xAxisType, monthCodes (YYYYMM arrays),
and xValues on every MultiLineChartData/LineChartData object so the
chart builders render proper time/value axes instead of evenly-spaced
category axes.

Changes:
- MultiLineChart.vue: guard on series.length instead of categories.length
  so time/value mode charts (no categories) are not silently skipped
- transformDashboardReport: observationByMonth → xAxisType:'time' +
  monthCodes from monthYear; cumulativeObservation → xValues from
  xLengthOfObservation
- transformDataDensityReport: totalRecords and recordsPerPerson →
  xAxisType:'time' + monthCodes from xCalendarMonth arrays
- transformObservationPeriodReport: observedByMonth → xAxisType:'time' +
  monthCodes from monthYear; cumulativeObservation → xAxisType:'value' +
  xValues from xLengthOfObservation
- transformDeathReport: prevalenceByMonth → xAxisType:'time' + monthCodes
  from xCalendarMonth
- tests/unit/utils/chart-config.spec.ts: fix 22 pre-existing failures by
  updating dashboardCumulativeLineOptions and
  dashboardObservationMonthLineOptions tests to pass xValues/monthCodes
  and verify the new time/value axis contract
…Report

The observationByMonth object was missing xAxisType: 'time', causing the
dashboard "Observations by Month" chart to render on an evenly-spaced
category axis instead of a proper time axis.
Moved components were git-mv'd to src/components/ui/charts/ with Atlas
prefix; update all 7 test files to import from the new locations.
IncidenceRateTreemap spec also updated findComponent lookup from
'TreemapChart' to 'AtlasTreemapChart' (Vue infers name from filename).
… Pie/Bar tests to Atlas components

- Deleted src/components/reports/charts/{PieChart,BarChart,LineChart}.vue
- Deleted tests for LineChart (incompatible data contract; covered by chart-config.spec.ts)
- Migrated tests/component and tests/unit Pie/Bar specs to AtlasPieChart/AtlasBarChart:
  import path, vi.mock path, CSS selectors (.pie-chart-container→.atlas-pie-chart,
  .bar-chart-container→.atlas-bar-chart)
- NOTE: src/utils/chart-config.ts shim retained — 4 datasources/charts components still
  import from @/utils/chart-config and must be migrated before the shim can be removed
…refix

Update findComponent/findAllComponents name queries and vi.mock paths in
four spec files to match the renamed Atlas* components:
- DomainPrevalenceTreemap.spec.ts: mock AtlasTreemapChart.vue, find AtlasTreemapChart
- PersonReport.spec.ts: mock AtlasPieChart.vue, find AtlasPieChart
- DeathReport.spec.ts: find AtlasTrellisChart (was TrellisChart)
- DrilldownDetails.spec.ts: rename LineChart stub key to AtlasLineChart, find
  AtlasLineChart; update formatTimeSeriesData assertion to new shape
  (monthCodes/series/yAxisLabel instead of xAxis/yAxis/seriesName)
…month format, restore axis cosmetics in value/time mode
@p-hoffmann p-hoffmann force-pushed the feat/shared-chart-components branch from 2560b1c to 42ddf42 Compare June 20, 2026 15:36
@codecov

codecov Bot commented Jun 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.31081% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.75%. Comparing base (9e8ed52) to head (0d70964).

Files with missing lines Patch % Lines
src/services/datasource.service.ts 92.10% 3 Missing ⚠️
src/utils/datasource-formatters.ts 96.61% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #115      +/-   ##
===========================================
+ Coverage    92.69%   92.75%   +0.06%     
===========================================
  Files          442      442              
  Lines        94331    94333       +2     
  Branches      8005    10674    +2669     
===========================================
+ Hits         87442    87503      +61     
+ Misses        6889     6830      -59     
Flag Coverage Δ
unit 92.75% <98.31%> (+0.06%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The dashboard report is run through DashboardReportSchema.safeParse in the
service layer, and Zod strips keys not declared in the schema. LineChartDataSchema
and MultiLineChartDataSchema did not list xAxisType/monthCodes/xValues, so the
axis-fix data was silently removed; dashboardCumulativeLineOptions then dereferenced
the now-undefined xValues array (data.xValues![i]) and threw during render, blanking
all dashboard charts.

- Add xAxisType/monthCodes/xValues to LineChartDataSchema + MultiLineChartDataSchema
  so safeParse preserves them.
- Guard the line builders to fall back to the point index instead of throwing when
  the scalar/time arrays are absent (defense in depth).
- Tests for both the schema preservation and the builder guards.
Length-of-observation x-values come from WebAPI in days. Matching the original
Atlas behaviour, convert to years when the span is large (>1000 days): scale the
histogram intervalSize for Observation Length, and the value-axis xValues for
Cumulative Observation (dashboard + observation period), labelling the axis Years.
mapBoxPlotData read item.min/item.max, but the WebAPI box-plot payload uses
minValue/maxValue (consistent with p25Value/medianValue/...). Min and max came
back as 0, collapsing the box (e.g. drilldown 'Age at First Occurrence' showed
max 0). Read minValue/maxValue with a min/max fallback for older payloads.
…lude pure-type chart-types from coverage

- Exclude src/ui/chart-types.ts from coverage (interfaces only, no runtime code,
  same rationale as the existing *.types.ts exclusions).
- Add multiLineChartOptions value-mode tests (xValues mapping + index fallback)
  and the dashboardObservationMonthLineOptions monthCodes fallback.
- Add a DataDensityReport mount smoke test (renders the two monthly line charts
  and the box plot; hides the concepts section when empty).
…race

fetchJSON cancels any previous in-flight request to the same endpoint. On app
start the TrexSQL availability check (App.vue) and the data sources view both
fetch /source/sources concurrently, so the second aborted the first — surfacing a
spurious 'Unable to load data sources' error and an empty / 'not implemented'
report on reload or deep-link. listDataSources now coalesces concurrent callers
into a single in-flight request (cleared on completion), so neither is aborted.
- Add space between the logo and the first menu item via the nav wrapper
  margin (does not affect inter-item spacing).
- The active item used font-weight 700, which widened it and shifted the rest
  of the menu. Keep weight 500 and apply a text-shadow faux-bold instead, so the
  item width (and the menu layout) stays stable on selection.
Long category names (race/ethnicity) in the left-vertical legend overlapped the
pie, and the outside percentage labels overflowed the card edge. Move the legend
to a scrollable bottom row (names truncate with ellipsis, full name on hover) and
draw the percentage inside each slice, so nothing extends past the chart.
@p-hoffmann p-hoffmann changed the title Shared chart components in atlas-ui + time/value axis fix Charts improvements Jun 20, 2026
@p-hoffmann p-hoffmann enabled auto-merge (squash) June 20, 2026 17:03
@p-hoffmann p-hoffmann merged commit 4976834 into develop Jun 20, 2026
19 checks passed
@p-hoffmann p-hoffmann deleted the feat/shared-chart-components branch June 20, 2026 17:11
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