Skip to content

Fix dashboard loading: migrate election analysis from JSON to CSV loaders#1249

Merged
pethers merged 7 commits intomainfrom
copilot/fix-dashboard-loading-issues
Mar 17, 2026
Merged

Fix dashboard loading: migrate election analysis from JSON to CSV loaders#1249
pethers merged 7 commits intomainfrom
copilot/fix-dashboard-loading-issues

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 17, 2026

  • Identify actionable items from latest PR review thread
  • Inspect current election loader logic and tests
  • Run baseline lint/build/test commands
  • Harden majority/riskLevel parsing in TypeScript election loader
  • Harden majority/riskLevel parsing in dashboard JS election loader
  • Replace brittle shape-based JSON-removal tests with behavior-based fetch assertions
  • Run targeted tests and static checks for touched files
  • Run code review and CodeQL checks
  • Reply to PR comment with commit hash and validation evidence

🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

@github-actions github-actions Bot added the size-xs Extra small change (< 10 lines) label Mar 17, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🏷️ Automatic Labeling Summary

This PR has been automatically labeled based on the files changed and PR metadata.

Applied Labels: size-xs

Label Categories

  • 🗳️ Content: news, dashboard, visualization, intelligence
  • 💻 Technology: html-css, javascript, workflow, security
  • 📊 Data: cia-data, riksdag-data, data-pipeline, schema
  • 🌍 I18n: i18n, translation, rtl
  • 🔒 ISMS: isms, iso-27001, nist-csf, cis-controls
  • 🏗️ Infrastructure: ci-cd, deployment, performance, monitoring
  • 🔄 Quality: testing, accessibility, documentation, refactor
  • 🤖 AI: agent, skill, agentic-workflow

For more information, see .github/labeler.yml.

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
@github-actions github-actions Bot added dashboard Interactive dashboards (Chart.js/D3.js) javascript JavaScript code changes testing Test coverage size-m Medium change (50-250 lines) labels Mar 17, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

…a-exports/ from gitignore

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
@github-actions github-actions Bot added cia-data CIA platform data integration visualization Data visualization features intelligence Political intelligence analysis size-l Large change (250-1000 lines) labels Mar 17, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

… as-any in tests

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Copilot AI changed the title [WIP] Fix dashboard loading issues related to JSON data Fix dashboard loading: migrate election analysis from JSON to CSV loaders Mar 17, 2026
@pethers pethers marked this pull request as ready for review March 17, 2026 12:29
Copilot AI review requested due to automatic review settings March 17, 2026 12:29
Copilot AI requested a review from pethers March 17, 2026 12:32
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Migrates the dashboard’s election analysis loading path from a JSON file (missing in deployed builds) to the existing CSV-based loading approach used elsewhere, by introducing election CSV sources and rebuilding loadElectionAnalysis() from CSV rows.

Changes:

  • Added election forecast + coalition scenarios CSV files under cia-data/election/.
  • Rewrote loadElectionAnalysis() in both the TypeScript and dashboard JS loaders to assemble ElectionAnalysis from CSV via loadCSV(), and removed the dashboard loaders’ JSON loader/base URL.
  • Added Vitest coverage for CSV-based election analysis loading and for ensuring the CIA loader no longer exposes JSON-specific members.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/cia-data-loader-election.test.ts Adds tests verifying election analysis is built from CSV and that JSON-specific members are not present on CIADataLoader.
src/browser/cia/data-loader.ts Adds election CSV source mappings and rebuilds loadElectionAnalysis() from CSV rows (removing the JSON loader/base URL).
dashboard/cia-data-loader.js Mirrors the TS loader changes for the dashboard runtime loader (CSV-based election analysis; removes JSON loader/base URL).
dashboard/election-predictions.js Updates documentation comments to reflect CSV-based election analysis sourcing.
cia-data/election/election_forecast.csv Introduces election forecast dataset (party seat predictions, vote share, confidence interval).
cia-data/election/coalition_scenarios.csv Introduces coalition scenario dataset (probability, composition, seats, majority, risk level).
.gitignore Stops ignoring data/cia-exports/.

Comment thread dashboard/cia-data-loader.js Outdated
Comment on lines +420 to +431
const parties = forecastRows.map(r => ({
name: r.name,
currentSeats: r.currentSeats,
predictedSeats: r.predictedSeats,
change: r.change,
voteShare: r.voteShare,
confidenceInterval:
r.confidenceMin != null && r.confidenceMax != null
? { min: r.confidenceMin, max: r.confidenceMax }
: undefined
}));

Comment thread src/browser/cia/data-loader.ts Outdated
Comment on lines +534 to +545
const parties = forecastRows.map(r => ({
name: r.name as string,
currentSeats: r.currentSeats as number,
predictedSeats: r.predictedSeats as number,
change: r.change as number,
voteShare: r.voteShare as number,
confidenceInterval:
r.confidenceMin != null && r.confidenceMax != null
? { min: r.confidenceMin as number, max: r.confidenceMax as number }
: undefined
}));

@pethers
Copy link
Copy Markdown
Member

pethers commented Mar 17, 2026

@copilot apply changes based on the comments in this thread

…to reject empty CSV strings

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 17, 2026

@copilot apply changes based on the comments in this thread

Fixed in 86f1b97. Both data-loader.ts and cia-data-loader.js now use typeof r.confidenceMin === 'number' && Number.isFinite(r.confidenceMin) instead of != null, so empty CSV cells (which remain as empty strings after parseCSV) correctly produce undefined instead of { min: '', max: '' }. Added a dedicated test case that verifies empty confidence interval cells are dropped.

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Migrates the dashboard’s election analysis loading path from JSON artifacts (previously causing 404s in deployment) to the existing CSV-based loading approach used across the rest of the CIA dashboard data pipeline.

Changes:

  • Reworked loadElectionAnalysis() in both the TS and dashboard JS loaders to build the election analysis object from cia-data/election/*.csv.
  • Added election forecast and coalition scenario CSV datasets under cia-data/election/.
  • Added a dedicated Vitest suite covering CSV-based election analysis loading (including empty-string confidence interval edge case) and removed data/cia-exports/ from .gitignore.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/cia-data-loader-election.test.ts Adds test coverage for CSV-based loadElectionAnalysis() and verifies JSON dependency removal.
src/browser/cia/data-loader.ts Adds CSV source definitions and rebuilds loadElectionAnalysis() using CSV loaders; removes JSON loader usage.
dashboard/election-predictions.js Updates inline documentation to reflect CSV-based election analysis sourcing.
dashboard/cia-data-loader.js Mirrors TS loader changes for CSV-based election analysis; removes JSON loader; updates module docs.
cia-data/election/election_forecast.csv Adds the election forecast dataset consumed by loaders.
cia-data/election/coalition_scenarios.csv Adds coalition scenario dataset consumed by loaders.
.gitignore Stops ignoring data/cia-exports/ (previous JSON export location).

Comment thread src/browser/cia/data-loader.ts Outdated
Comment on lines +534 to +555
const parties = forecastRows.map(r => ({
name: r.name as string,
currentSeats: r.currentSeats as number,
predictedSeats: r.predictedSeats as number,
change: r.change as number,
voteShare: r.voteShare as number,
confidenceInterval:
typeof r.confidenceMin === 'number' && Number.isFinite(r.confidenceMin) &&
typeof r.confidenceMax === 'number' && Number.isFinite(r.confidenceMax)
? { min: r.confidenceMin, max: r.confidenceMax }
: undefined
}));

const coalitionScenarios = scenarioRows.map(r => ({
name: r.name as string,
probability: r.probability as number,
composition: (r.composition as string).split(',').map(s => s.trim()),
totalSeats: r.totalSeats as number,
majority: String(r.majority).toLowerCase() === 'true',
riskLevel: r.riskLevel as string
}));

Comment thread dashboard/cia-data-loader.js Outdated
Comment on lines +420 to +441
const parties = forecastRows.map(r => ({
name: r.name,
currentSeats: r.currentSeats,
predictedSeats: r.predictedSeats,
change: r.change,
voteShare: r.voteShare,
confidenceInterval:
typeof r.confidenceMin === 'number' && Number.isFinite(r.confidenceMin) &&
typeof r.confidenceMax === 'number' && Number.isFinite(r.confidenceMax)
? { min: r.confidenceMin, max: r.confidenceMax }
: undefined
}));

const coalitionScenarios = scenarioRows.map(r => ({
name: r.name,
probability: r.probability,
composition: String(r.composition).split(',').map(s => s.trim()),
totalSeats: r.totalSeats,
majority: String(r.majority).toLowerCase() === 'true',
riskLevel: r.riskLevel
}));

Comment thread dashboard/cia-data-loader.js Outdated
Comment on lines 71 to 81
@@ -80,7 +75,7 @@
* return await this.loadLocal(category); // Tier 1: Local CSV
* } catch (err) {
* try {
* return await this.loadJSON(category); // Tier 2: Local JSON
* return await this.loadCSV(category); // Tier 2: CSV fallback
* } catch (err) {
* return await this.loadRemote(category); // Tier 3: GitHub
* }
@pethers
Copy link
Copy Markdown
Member

pethers commented Mar 17, 2026

@copilot apply changes based on the comments in this thread

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 17, 2026

@copilot apply changes based on the comments in this thread

Implemented in e5c1072.

  • loadElectionAnalysis() in both TS and dashboard loaders now coerces required numeric fields via finite-number parsing and drops invalid rows instead of passing through empty strings.
  • Confidence interval handling remains finite-number guarded.
  • Updated the dashboard loader module documentation to match actual local CSV loading behavior.
  • Added tests covering invalid numeric forecast/scenario rows.

Validation run: targeted Vitest suite (10/10), browser TypeScript check, and ESLint on modified files all pass.

No UI was changed in this patch, so there is no UI screenshot to provide.

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Migrates the election analysis data path away from JSON artifacts and into the existing CSV-based loader pipeline, aligning election predictions with the rest of the dashboard’s data ingestion model.

Changes:

  • Implement loadElectionAnalysis() using CSV sources (election_forecast.csv, coalition_scenarios.csv) in both the TS browser loader and the dashboard JS loader.
  • Add election CSV datasets under cia-data/election/ and add targeted Vitest coverage for numeric coercion and invalid/blank CSV cells.
  • Update dashboard-side documentation/comments to remove references to election-analysis.json and remove data/cia-exports/ from .gitignore.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/cia-data-loader-election.test.ts Adds tests validating CSV-based election analysis loading and numeric field handling.
src/browser/cia/data-loader.ts Removes JSON loader usage and builds ElectionAnalysis from CSV rows with coercion/validation.
dashboard/election-predictions.js Updates comments to reflect CSV-based election analysis inputs.
dashboard/cia-data-loader.js Mirrors TS loader changes: removes JSON loader and builds election analysis from CSV sources.
cia-data/election/election_forecast.csv Introduces the election forecast CSV source data.
cia-data/election/coalition_scenarios.csv Introduces the coalition scenarios CSV source data.
.gitignore Stops ignoring data/cia-exports/ (previous JSON export location).

Comment thread src/browser/cia/data-loader.ts Outdated
Comment on lines +588 to +590
majority: String(r.majority).toLowerCase() === 'true',
riskLevel: String(r.riskLevel ?? '')
}];
Comment on lines +460 to +463
totalSeats,
majority: String(r.majority).toLowerCase() === 'true',
riskLevel: String(r.riskLevel ?? '')
}];
Comment thread tests/cia-data-loader-election.test.ts Outdated
Comment on lines +203 to +211
describe('no JSON dependency', () => {
it('should not have a loadJSON method', () => {
const loader = new CIADataLoader();
expect('loadJSON' in loader).toBe(false);
});

it('should not have a jsonBaseURL property', () => {
const loader = new CIADataLoader();
expect('jsonBaseURL' in loader).toBe(false);
Comment thread tests/cia-data-loader-election.test.ts Outdated
Comment on lines +209 to +211
it('should not have a jsonBaseURL property', () => {
const loader = new CIADataLoader();
expect('jsonBaseURL' in loader).toBe(false);
@pethers
Copy link
Copy Markdown
Member

pethers commented Mar 17, 2026

@copilot apply changes based on the comments in this thread

…ests

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 17, 2026

@copilot apply changes based on the comments in this thread

Applied in 030942d.

  • Coalition scenario rows now require a parseable majority (true/false) and a non-empty trimmed riskLevel; invalid rows are dropped in both loaders.
  • Replaced brittle shape assertions with behavior-based coverage: tests now verify election analysis requests CSV endpoints and does not request election-analysis.json.
  • Added coverage for invalid majority and empty riskLevel rows.

Validation passed: baseline npm run lint, npm run build, npm run test; targeted Vitest suite (10/10); browser TS check; ESLint on modified files; code review (no findings); CodeQL (0 alerts).

No UI changes were made in this patch, so no screenshot is applicable.

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

@pethers pethers requested a review from Copilot March 17, 2026 13:22
@pethers pethers merged commit 2dfede2 into main Mar 17, 2026
27 checks passed
@pethers pethers deleted the copilot/fix-dashboard-loading-issues branch March 17, 2026 13:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Migrates election analysis loading for both the TypeScript browser bundle and the dashboard JS loader away from election-analysis.json to the same CSV-based loading approach used for other CIA dashboard datasets.

Changes:

  • Implement CSV-based loadElectionAnalysis() in both src/browser/cia/data-loader.ts and dashboard/cia-data-loader.js, removing the JSON loader/fallback.
  • Add election CSV datasets (election_forecast.csv, coalition_scenarios.csv) and a dedicated Vitest suite validating parsing and fetch behavior.
  • Update dashboard documentation comments and adjust .gitignore to stop ignoring data/cia-exports/.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/cia-data-loader-election.test.ts Adds tests ensuring election analysis is built from CSV fetches and invalid rows are dropped.
src/browser/cia/data-loader.ts Adds election CSV sources and implements CSV-based loadElectionAnalysis(); removes JSON loading path.
dashboard/election-predictions.js Updates inline documentation references from JSON to CSV-based sources.
dashboard/cia-data-loader.js Mirrors TS loader changes: removes JSON loading and builds election analysis from CSV.
cia-data/election/election_forecast.csv Adds party forecast CSV used by election analysis loader.
cia-data/election/coalition_scenarios.csv Adds coalition scenarios CSV used by election analysis loader.
.gitignore Stops ignoring data/cia-exports/.

this.loadCSV(CIADataLoader.CSV_SOURCES.electionForecast.local),
this.loadCSV(CIADataLoader.CSV_SOURCES.coalitionScenarios.local)
]);

* Render key factors affecting the election
* NOTE: Reserved for future implementation - requires adding <div id="key-factors"></div> to HTML
* and calling this method from dashboard-init.js. The data is available in election-analysis.json.
* and calling this method from dashboard-init.js. The data is built from election CSV sources.
* Get election date formatted
* NOTE: Reserved for future implementation - can be used to display election date in dashboard header.
* The data is available as electionDate in election-analysis.json.
* The data is available as electionDate from election CSV sources.
Comment on lines +214 to +226
describe('CSV_SOURCES', () => {
it('should include election forecast and coalition scenarios', () => {
expect(CIADataLoader.CSV_SOURCES.electionForecast).toBeDefined();
expect(CIADataLoader.CSV_SOURCES.electionForecast.local).toBe(
'election/election_forecast.csv'
);
expect(CIADataLoader.CSV_SOURCES.coalitionScenarios).toBeDefined();
expect(CIADataLoader.CSV_SOURCES.coalitionScenarios.local).toBe(
'election/coalition_scenarios.csv'
);
});
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cia-data CIA platform data integration dashboard Interactive dashboards (Chart.js/D3.js) intelligence Political intelligence analysis javascript JavaScript code changes size-l Large change (250-1000 lines) size-m Medium change (50-250 lines) size-xs Extra small change (< 10 lines) testing Test coverage visualization Data visualization features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants