Skip to content

Add improvement backlog, fix chart rendering, and improve accessibility - #4

Merged
GChavez0210 merged 4 commits into
mainfrom
claude/charming-clarke-xlvlb8
Jun 10, 2026
Merged

GChavez0210 merged 4 commits into
mainfrom
claude/charming-clarke-xlvlb8

Conversation

@GChavez0210

Copy link
Copy Markdown
Owner

Summary

This PR adds a comprehensive improvement backlog document, fixes chart rendering performance issues, improves accessibility, and makes several quality-of-life improvements to the renderer and database layer.

Key Changes

Documentation

  • Added docs/IMPROVEMENT_BACKLOG.md: A detailed, prioritized list of 60+ fixes and improvements across security (7 items), data-analysis correctness (14 items), performance (11 items), and renderer efficiency (9 items). Each task is self-contained with effort estimates, file locations, and implementation guidance.

Renderer Performance & UX

  • Chart downsampling: Added src/renderer/utils/downsample.js with a stride-based downsampling function that reduces long time-series (>400 points) to ~300 points for snappy Chart.js rendering without losing accuracy.
  • Stabilized chart props: Wrapped trendsData computation in useMemo and applied downsampling before passing to charts, preventing unnecessary Chart.js instance recreation.
  • Theme context: Created src/renderer/ThemeContext.js to eliminate prop-threading of the theme value through intermediate components; TrendChart now uses useTheme() hook.
  • Report generation robustness:
    • Added guard against empty date ranges (prevents blank PDF generation)
    • Replaced hardcoded setTimeout waits with a polling mechanism (waitForCharts) that checks for actual Chart.js instances and canvas dimensions, with a 5-second cap
    • Improved error handling in saveReport

Accessibility & HTML Quality

  • Focus management: Added focus trap and restoration logic to the About modal (aboutCloseButtonRef, aboutPreviousFocusRef) so keyboard users can navigate modals properly.
  • Form labels: Updated ProfileSelector to use htmlFor attributes linking labels to input IDs.
  • Data attributes: Added data-report-key attributes to chart containers for reliable DOM querying during report capture.

Constants & Code Organization

  • Created src/renderer/constants.js: Centralized clinical thresholds (AHI_MILD, AHI_MODERATE, LEAK_HIGH, LEAK_WARNING, USAGE_COMPLIANCE_HOURS, USAGE_WARNING_HOURS, SPO2_NORMAL, SPO2_WARNING) so all components read from a single source of truth instead of hardcoded magic numbers.
  • Updated severity() function: Now uses the centralized constants instead of inline literals.

Insights Page Improvements

  • Correlation display: Enhanced CorrelationBar to show:
    • Spearman correlation (ρ) when available, with Pearson (r) as fallback
    • Sample count (n) for each correlation
    • Significance status (grayed out if p ≥ 0.05)
    • Improved tooltip and styling for non-significant correlations

Database & Performance

  • SQLite optimization: Enabled WAL (Write-Ahead Logging) mode and NORMAL synchronous pragma in database.js to improve bulk-insert performance (~2-3x faster) while maintaining durability.

Testing & Robustness

  • Test data guards: Updated edf-parser.test.js and cpap-data-loader.test.js to check for the presence of test data before running data-dependent tests, allowing CI to skip them gracefully.

Cleanup

  • Removed unused dependency: Deleted vite-plugin-compression from package.json (no longer needed).

Implementation Details

  • All chart components now receive theme via context instead of props, reducing prop-drilling.
  • Downsampling uses a simple stride-based approach (evenly-spaced indices) that preserves first/last points and is fast enough for real-time rendering.
  • The waitForCharts polling function uses requestAnimationFrame for initial DOM settlement, then polls every 100ms with a 5-second timeout to handle slow machines gracefully.
  • Constants are exported as named exports for tree-shaking and clarity.
  • WAL mode creates -wal and -shm sidecar files; existing backup/delete logic

https://claude.ai/code/session_0195cFbLhjgDithCgUbwCqcV

claude added 4 commits June 9, 2026 18:18
Skip the two tests that depend on the gitignored 'Test Data/' folder when
it is absent so 'npm run check' passes on clean checkouts (CI was guaranteed
to fail otherwise). Enable WAL journal mode with NORMAL synchronous on both
databases to speed up bulk imports.

https://claude.ai/code/session_0195cFbLhjgDithCgUbwCqcV
- Fix PeriodicBreathingCard confound badge to count confounded nights among
  significant nights only
- Downsample trend series to ~300 points beyond 400 nights (index-aligned
  across labels and all series; rolling averages computed before sampling)
- Extract clinical thresholds to constants.js; hoist repeated static styles
- saveReport: bail on empty range, poll Chart.getChart/canvas dimensions
  (5s cap) instead of fixed 1500ms waits
- ThemeContext replaces theme prop drilling for TrendChart
- Remove unused vite-plugin-compression dependency
- A11y: canvas role/aria-labels, keyboard-expandable chart cards, About
  modal focus management, ProfileSelector label/input pairing
- Insights: show n, prefer Spearman rho, mute non-significant correlations

https://claude.ai/code/session_0195cFbLhjgDithCgUbwCqcV
Copilot AI review requested due to automatic review settings June 10, 2026 17:51
@GChavez0210
GChavez0210 merged commit 027e795 into main Jun 10, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an improvement backlog document and implements several renderer, accessibility, and performance improvements, including chart downsampling/stabilization and SQLite WAL configuration, plus a few test/maintenance cleanups.

Changes:

  • Added an extensive improvement backlog document (docs/IMPROVEMENT_BACKLOG.md) and updated README development notes.
  • Improved renderer/chart UX & performance (downsampling, theme context, chart capture polling) and expanded chart accessibility via ARIA labels and keyboard interactions.
  • Enabled SQLite WAL + NORMAL synchronous pragmas and updated tests to gracefully skip data-dependent suites when local test data is absent.

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/renderer/utils/reportBuilder.js Adds warnings + null-return guard behavior in computeScores() for empty/insufficient data.
src/renderer/utils/downsample.js Introduces a stride-based downsampling index helper for long time-series.
src/renderer/ThemeContext.js Adds a ThemeContext + useTheme() hook to reduce theme prop drilling.
src/renderer/pages/Insights.jsx Enhances correlation display (ρ vs r, n, significance styling) and wires report keys for report capture.
src/renderer/constants.js Centralizes clinical threshold constants used across renderer logic.
src/renderer/components/ProfileSelector.jsx Improves form accessibility by linking labels to inputs via htmlFor/id.
src/renderer/components/charts/PressureHistogramChart.jsx Adds role="img" + aria-label to canvas for accessibility.
src/renderer/components/charts/PeriodicBreathingCard.jsx Adjusts confounding logic for periodic breathing significant-night interpretation.
src/renderer/components/charts/LeakSeverityGauge.jsx Adds role="img" + detailed aria-label to the gauge canvas.
src/renderer/components/charts/FlowLimitationChart.jsx Adds role="img" + aria-label to canvas for accessibility.
src/renderer/components/charts/EventTypeSplitChart.jsx Adds role="img" + aria-label to canvas for accessibility.
src/renderer/components/charts/AHITrendChart.jsx Adds role="img" + aria-label to canvas for accessibility.
src/renderer/charts/TrendChart.jsx Switches to ThemeContext, adds report key attribute, and enables keyboard expand behavior + ARIA labeling.
src/renderer/App.jsx Integrates ThemeContext provider, adds downsampling, replaces hard waits with polling for report capture, adds About modal focus restoration, and uses centralized thresholds.
README.md Adds renderer/testing development notes and clarifies type-checking expectations.
package.json Removes vite-plugin-compression dev dependency.
package-lock.json Removes vite-plugin-compression lockfile entries.
electron/main/services/database.js Enables WAL journal mode and NORMAL synchronous pragmas for better bulk import performance.
electron/main/services/cpap-data-loader.test.js Skips data-dependent tests when Test Data/ is not present.
electron/main/parsers/edf-parser.test.js Skips data-dependent EDF parsing test when Test Data/ is not present.
docs/IMPROVEMENT_BACKLOG.md Adds a detailed, prioritized backlog of security/correctness/performance/renderer tasks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +15 to +22
const indices = new Uint32Array(target);
indices[0] = 0;
indices[target - 1] = length - 1;

for (let i = 1; i < target - 1; i++) {
// Evenly spaced positions across [0, length-1]
indices[i] = Math.round((i / (target - 1)) * (length - 1));
}
Comment thread src/renderer/App.jsx
Comment on lines 305 to 307
rolling7Ahi: rolling7,
ahiThreshold: Array(n).fill(5),
leakThreshold: Array(n).fill(24),
Comment thread src/renderer/App.jsx
Comment on lines +446 to +450
const containers = document.querySelectorAll("[data-report-key]");
const ready = Array.from(containers).every((el) => {
const canvas = el.querySelector("canvas");
return canvas && canvas.width > 0 && canvas.height > 0 && Chart.getChart(canvas) != null;
});
Comment thread src/renderer/App.jsx
Comment on lines 1165 to 1167
<div
role="dialog" aria-modal="true"
role="dialog" aria-modal="true" aria-label="About PAPLens"
onClick={(e) => e.stopPropagation()}
? "var(--muted)"
: displayCoeff > 0.4 ? "#22D3EE" : displayCoeff < -0.4 ? "#ef4444" : "var(--muted)";
const positive = displayCoeff >= 0;
const tooltipText = getCorrelationInsight(pair, r);
Comment on lines +642 to +646
r={c.r}
rho={c.rho}
pValue={c.pValue}
significant={c.significant}
n={c.n}
@GChavez0210
GChavez0210 deleted the claude/charming-clarke-xlvlb8 branch June 10, 2026 18:37
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.

3 participants