Skip to content

Fix alignment_rate scale bugs across coalition and party dashboards#738

Merged
pethers merged 6 commits intomainfrom
copilot/improve-dashboard-quality
Mar 2, 2026
Merged

Fix alignment_rate scale bugs across coalition and party dashboards#738
pethers merged 6 commits intomainfrom
copilot/improve-dashboard-quality

Conversation

Copy link
Contributor

Copilot AI commented Mar 2, 2026

CIA platform CSV alignment_rate values are 0–1 (0.84 = 84%), but multiple dashboards applied an additional /100, rendering all alignment data ~100× too small.

Data processing fixes

  • coalition-dashboard.ts: Remove erroneous /100 on alignment_rate in network link strength and heat map rendering — values like 0.84 were becoming 0.0084
  • coalition-dashboard.ts: Fix node influence formula from avg/10 + 3avg*10 + 3 so 0–1 inputs produce meaningful size variation (was collapsing all nodes to ~3.06)
  • coalition-dashboard.ts: Make alignment matrix symmetric at CSV load time — CSV stores each pair once (e.g., KD,M but not M,KD), so both directions are now populated to prevent silent fallback to 0.5 on reverse lookups
  • coalition-dashboard.ts: Filter non-party rows (e.g., party1 = '-' for aggregate/independent data) before storing in the symmetric alignment matrix, preventing non-party entries from polluting node influence averages
  • coalition-dashboard.ts: Add defensive reverse-pair fallback in network and heat map lookups as belt-and-suspenders protection
  • party-dashboard.ts: Fix Math.round(rate)Math.round(rate * 100)Math.round(0.84) = 1, so all coalitions displayed as "1%"
  • party-dashboard.ts: Extract alignmentRateToPercent() as an exported helper used by both production code and tests, ensuring the conversion logic is tested against the real implementation
  • party-dashboard.ts: Fix momentum filter row.momentum (rejects 0 as falsy) → row.momentum !== undefined && row.momentum !== ''
// Before: 0.84 / 100 = 0.0084 → tooltip shows "0.84%"
const strength = alignment[source.id][target.id] / 100;

// After: 0.84 used directly → tooltip shows "84%"  
const strength = alignment[source.id][target.id];

Mock data fallbacks

  • generateMockAnomalyData() and generateMockAnnualVotesData() now use deterministic fixed values (no Math.random()) and always return non-empty results, preventing blank charts and ensuring visual regression test stability
  • Both generators are exported so tests invoke the real production functions rather than duplicating logic locally

HTML metadata

  • Fix og:image:width/height from 1200×630 to 140×140 across all 28 index HTML files to match actual cia-icon-140.webp dimensions

Tests

  • 13 tests covering alignment rate scale invariants, reverse-pair lookup resolution, non-party row filtering, mock data determinism/non-emptiness, zero-alignment edge cases, and momentum zero-value filtering with string types matching CSV parsing runtime
  • Mock data tests import and call the real exported generateMockAnomalyData() and generateMockAnnualVotesData() generators, asserting determinism, non-emptiness, and known per-party baselines — regressions to random/empty output will now fail tests
  • Alignment rate tests import and call the real exported alignmentRateToPercent() helper — a regression back to Math.round(rate) will now fail tests
  • Test fixtures updated to match actual CSV pair direction (e.g., KD,M not M,KD)
  • All 246 dashboard tests pass

🔒 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.

…:image dimensions

- coalition-dashboard.ts: Remove erroneous /100 division on alignment_rate (already 0-1)
- coalition-dashboard.ts: Fix influence calculation to use *10 instead of /10
- coalition-dashboard.ts: Add meaningful mock anomaly and annual votes fallback data
- party-dashboard.ts: Fix Math.round(rate) to Math.round(rate * 100) for percentage display
- party-dashboard.ts: Fix momentum filter to accept zero values
- Fix og:image dimensions (140x140) in all 28 index*.html and dashboard/index*.html files
- Add targeted tests for alignment rate processing and mock data quality

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Copilot AI changed the title [WIP] Improve quality and testing for all dashboards Fix alignment_rate scale bugs across coalition and party dashboards Mar 2, 2026
@pethers pethers requested a review from Copilot March 2, 2026 17:02
@github-actions github-actions bot added dashboard Interactive dashboards (Chart.js/D3.js) html-css HTML/CSS changes javascript JavaScript code changes i18n Internationalization/localization translation Translation updates rtl RTL language support (Arabic, Hebrew) testing Test coverage size-l Large change (250-1000 lines) labels Mar 2, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 2, 2026

🔍 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
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

Fixes incorrect handling of alignment_rate values (0–1 scale) across coalition/party dashboards so displayed percentages, network strengths, and node sizing match CSV semantics; also improves mock-data fallbacks and corrects OG image metadata.

Changes:

  • Correct alignment_rate scaling and related derived calculations in coalition/party dashboards (remove /100, fix percentage rounding, fix influence formula, fix momentum filtering for 0).
  • Add/expand tests around alignment rate scaling and momentum filtering.
  • Update Open Graph og:image dimensions across index HTML pages to match cia-icon-140.webp.

Reviewed changes

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

Show a summary per file
File Description
tests/party-dashboard.test.js Adds tests for alignment rate percentage display and momentum filtering behavior
tests/coalition-dashboard.test.js Adds tests for alignment rate usage, influence sizing, and mock data non-emptiness
src/browser/dashboards/party-dashboard.ts Fixes displayed coalition strength percentage and momentum filtering
src/browser/dashboards/coalition-dashboard.ts Fixes alignment scaling, node influence computation, and adds mock anomaly/vote fallback data
index.html Updates og:image width/height metadata to 140x140
index_ar.html Updates og:image width/height metadata to 140x140
index_da.html Updates og:image width/height metadata to 140x140
index_de.html Updates og:image width/height metadata to 140x140
index_es.html Updates og:image width/height metadata to 140x140
index_fi.html Updates og:image width/height metadata to 140x140
index_fr.html Updates og:image width/height metadata to 140x140
index_he.html Updates og:image width/height metadata to 140x140
index_ja.html Updates og:image width/height metadata to 140x140
index_ko.html Updates og:image width/height metadata to 140x140
index_nl.html Updates og:image width/height metadata to 140x140
index_no.html Updates og:image width/height metadata to 140x140
index_sv.html Updates og:image width/height metadata to 140x140
index_zh.html Updates og:image width/height metadata to 140x140
dashboard/index.html Updates og:image width/height metadata to 140x140
dashboard/index_ar.html Updates og:image width/height metadata to 140x140
dashboard/index_da.html Updates og:image width/height metadata to 140x140
dashboard/index_de.html Updates og:image width/height metadata to 140x140
dashboard/index_es.html Updates og:image width/height metadata to 140x140
dashboard/index_fi.html Updates og:image width/height metadata to 140x140
dashboard/index_fr.html Updates og:image width/height metadata to 140x140
dashboard/index_he.html Updates og:image width/height metadata to 140x140
dashboard/index_ja.html Updates og:image width/height metadata to 140x140
dashboard/index_ko.html Updates og:image width/height metadata to 140x140
dashboard/index_nl.html Updates og:image width/height metadata to 140x140
dashboard/index_no.html Updates og:image width/height metadata to 140x140
dashboard/index_sv.html Updates og:image width/height metadata to 140x140
dashboard/index_zh.html Updates og:image width/height metadata to 140x140
Comments suppressed due to low confidence (2)

tests/coalition-dashboard.test.js:1

  • These tests don’t exercise the production mock generators (generateMockAnomalyData / generateMockAnnualVotesData); they only validate locally-constructed data. To cover the new fallback behavior, add tests that call the actual functions (or the public rendering paths that use them when CSV is unavailable) and assert the returned/consumed data is non-empty and shape-correct.
    tests/party-dashboard.test.js:1
  • These assertions re-encode the arithmetic directly instead of validating party-dashboard.ts behavior. Consider adding a test that feeds a minimal CSVRow into the code path that builds coalition entries and asserts the produced strength is 84 (and similarly, that momentum filtering includes momentum: 0 rows). That way the test will fail if the dashboard logic regresses even if the math in the test stays correct.

nodes.forEach((target, j) => {
if (i < j) {
const strength = alignment && alignment[source.id] && alignment[source.id][target.id] ? alignment[source.id][target.id] / 100 : 0.5;
const strength = alignment && alignment[source.id] && alignment[source.id][target.id] ? alignment[source.id][target.id] : 0.5;
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

This truthy-check will treat a valid alignment value of 0 as missing and fall back to 0.5. Use an explicit numeric check (e.g., typeof value === 'number') or nullish coalescing so 0 remains a valid strength.

Suggested change
const strength = alignment && alignment[source.id] && alignment[source.id][target.id] ? alignment[source.id][target.id] : 0.5;
const rawStrength = alignment?.[source.id]?.[target.id];
const strength = typeof rawStrength === 'number' ? rawStrength : 0.5;

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 1025144. Replaced the truthy check with typeof rawStrength === 'number' so alignment value 0 is treated as valid. Added a test verifying 0 is not replaced by the 0.5 fallback.

partyIds.forEach(party1 => {
partyIds.forEach(party2 => {
const alignmentVal = party1 === party2 ? 1.0 : ((dataCache.coalitionAlignment?.[party1]?.[party2]) ? dataCache.coalitionAlignment[party1][party2] / 100 : 0.5);
const alignmentVal = party1 === party2 ? 1.0 : ((dataCache.coalitionAlignment?.[party1]?.[party2]) ? dataCache.coalitionAlignment[party1][party2] : 0.5);
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

Same issue as the network strength: the conditional uses truthiness, so an alignment of 0 will be treated as absent and replaced with 0.5. Prefer an explicit typeof === 'number' check or ?? with a properly typed value retrieval.

Suggested change
const alignmentVal = party1 === party2 ? 1.0 : ((dataCache.coalitionAlignment?.[party1]?.[party2]) ? dataCache.coalitionAlignment[party1][party2] : 0.5);
const rawAlignment = dataCache.coalitionAlignment?.[party1]?.[party2];
const alignmentVal = party1 === party2 ? 1.0 : (typeof rawAlignment === 'number' ? rawAlignment : 0.5);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 1025144. Same typeof rawAlignment === 'number' check applied to the heat map lookup, matching the suggested pattern.

Comment on lines +544 to +578
function generateMockAnomalyData(): AnomalyEntry[] {
// Provide realistic fallback data when CIA anomaly data is unavailable
const parties = Object.keys(PARTIES);
const anomalies: AnomalyEntry[] = [];
parties.forEach(party => {
const deviation = 0.5 + Math.random() * 3;
if (deviation > 1.0) {
anomalies.push({
party,
date: '2024-06-15',
deviation: parseFloat(deviation.toFixed(2)),
severity: deviation > 3 ? 'critical' : deviation > 2 ? 'major' : 'minor'
});
}
});
return anomalies;
}

function generateMockAnnualVotesData(): Record<string, AnnualVoteEntry[]> {
// Provide realistic fallback data for annual vote trends
const data: Record<string, AnnualVoteEntry[]> = {};
const partyBaselines: Record<string, number> = {
'S': 50000, 'M': 35000, 'SD': 25000, 'V': 12000,
'MP': 10000, 'C': 12000, 'L': 10000, 'KD': 10000
};
Object.keys(PARTIES).forEach(party => {
data[party] = [];
const baseline = partyBaselines[party] || 15000;
for (let year = 2002; year <= 2025; year++) {
const variation = 0.8 + Math.random() * 0.4;
data[party].push({ year, votes: Math.round(baseline * variation) });
}
});
return data;
}
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

These mock-data generators depend on Math.random(), making the UI (and any snapshots/visual regression tests) non-deterministic. Also, generateMockAnomalyData() can still return an empty array (low probability, but possible), reintroducing the blank-chart failure mode this change is trying to avoid. Consider generating deterministic (seeded or fixed) values and enforcing at least one anomaly entry when used as a fallback.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 1025144. Both mock generators are now fully deterministic — generateMockAnomalyData() uses a fixed deviation map and always returns exactly 8 entries (one per party), and generateMockAnnualVotesData() uses year-parity-based ±10% variation instead of Math.random().

@pethers
Copy link
Member

pethers commented Mar 2, 2026

@copilot apply changes based on the comments in this thread

…ta deterministic

- Use typeof === 'number' for alignment lookups so value 0 is not treated as missing
- Replace Math.random() in mock data generators with deterministic fixed values
- generateMockAnomalyData() now always returns exactly 8 entries (one per party)
- generateMockAnnualVotesData() uses year-parity-based ±10% variation
- Add tests for zero-alignment edge case and deterministic mock data

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

Copilot AI commented Mar 2, 2026

@copilot apply changes based on the comments in this thread

All three review comments addressed in 1025144:

  • Alignment lookups use typeof === 'number' so value 0 is valid
  • Mock data generators are deterministic (no Math.random()) and always produce non-empty results

@pethers
Copy link
Member

pethers commented Mar 2, 2026

@copilot apply changes based on the comments in this thread

…ixtures

- Store both alignment[party1][party2] and alignment[party2][party1] when loading CSV
  (CSV has KD,M but not M,KD — symmetric matrix ensures all lookups succeed)
- Add defensive reverse-pair fallback in network and heat map lookups
- Update coalition test fixtures to match CSV pair direction (KD,M not M,KD)
- Add test for reverse-pair lookup resolution
- Update momentum test to use string values matching CSV parsing runtime types

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

Copilot AI commented Mar 2, 2026

@copilot apply changes based on the comments in this thread

All 5 review comments addressed in 46e699a:

  • Alignment matrix made symmetric at CSV load time (fixes all lookup direction issues)
  • Reverse-pair fallback added to both network and heat map lookups as defense-in-depth
  • Test fixtures updated to match CSV direction and verify reverse lookups
  • Momentum test uses string values matching CSV parsing runtime types

@github-actions
Copy link
Contributor

github-actions bot commented Mar 2, 2026

🔍 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
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

Copilot reviewed 32 out of 32 changed files in this pull request and generated 1 comment.

Comment on lines 162 to +166
const party1 = row['party1']; const party2 = row['party2']; const alignmentRate = parseFloat(row['alignment_rate']);
if (!alignment[party1]) alignment[party1] = {};
alignment[party1][party2] = alignmentRate;
if (!alignment[party2]) alignment[party2] = {};
alignment[party2][party1] = alignmentRate;
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

When loading coalition alignment CSV, the new symmetric insert will also create entries like alignment['SD']['-'] for rows where party1 is '-' (these exist in cia-data/party/distribution_coalition_alignment.csv). Those '-' values are then included in renderCoalitionNetwork() node influence averaging via Object.values(alignment[id]), skewing influence/size even though '-' is not a real party node. Filter out rows where party1/party2 are not real parties (e.g. '-' or not in PARTIES) before storing (both directions).

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 214f2f6. Added if (!PARTIES[party1] || !PARTIES[party2]) return; guard at the top of the CSV forEach loop, consistent with the party === '-' filter already used in fetchBehavioralData() and fetchDecisionTrendsData(). This prevents - and any other non-party values from entering the symmetric matrix and skewing influence averages.

@pethers
Copy link
Member

pethers commented Mar 2, 2026

@copilot apply changes based on the comments in this thread

CSV rows where party1 or party2 is not in PARTIES (e.g., '-' for
aggregate/independent) are now skipped before storing in the symmetric
alignment matrix. This prevents polluting node influence averages with
non-party alignment rates. Added test verifying '-' entries are excluded.

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

Copilot AI commented Mar 2, 2026

@copilot apply changes based on the comments in this thread

Applied in 214f2f6. Non-party rows (e.g., party1 = '-') are now filtered out before storing in the symmetric alignment matrix, preventing them from polluting node influence averages.

@pethers pethers requested a review from Copilot March 2, 2026 18:42
@github-actions
Copy link
Contributor

github-actions bot commented Mar 2, 2026

🔍 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
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

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

Comment on lines +473 to +482
it('should generate deterministic non-empty mock annual votes data', () => {
const parties = ['S', 'M', 'SD', 'V', 'MP', 'C', 'L', 'KD'];
const baseline = 15000;
const data = {};
parties.forEach(party => {
data[party] = [];
for (let year = 2002; year <= 2025; year++) {
const variation = year % 2 === 0 ? 0.9 : 1.1;
data[party].push({ year, votes: Math.round(baseline * variation) });
}
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

This test creates annual-votes data locally with a single baseline = 15000, but the production fallback generateMockAnnualVotesData() now uses per-party baselines (e.g., S: 50000) and is not invoked here. As written, the test won’t fail if the real generator changes (or regresses to random/empty output). Consider asserting against the real generator’s output (or shared exported helper) so the test actually protects the behavior being changed.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in a5c42e4. Exported generateMockAnnualVotesData() from coalition-dashboard.ts and updated the test to import and call the real generator. The test now verifies determinism, non-emptiness, and per-party baselines from the production function (e.g., S baseline 50000 not generic 15000, M baseline 35000).

Comment on lines +366 to +370
it('should convert 0-1 alignment_rate to percentage for display', () => {
// Real CSV: alignment_rate is 0.84 (meaning 84%)
const rate = 0.84;
const displayStrength = Math.round(rate * 100);
expect(displayStrength).toBe(84);
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

These new assertions validate standalone math (e.g., Math.round(rate * 100)) rather than exercising the dashboard implementation that was changed in src/browser/dashboards/party-dashboard.ts. As a result, the test would still pass if the production code regressed back to Math.round(rate) or if the DOM rendering used a different conversion. Consider testing the actual createCoalitionNetwork() output (e.g., by calling it with fixture rows and asserting rendered % text/width), or extracting/exporting a small helper used by both code and tests so the invariant is enforced against the real implementation.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in a5c42e4. Extracted alignmentRateToPercent() as an exported helper from party-dashboard.ts, used it in createCoalitionNetwork(), and updated tests to import and call the real function. A regression back to Math.round(rate) in the production code would now break the test.

Comment on lines +453 to +460
it('should generate deterministic non-empty mock anomaly data for all parties', () => {
// Deterministic mock deviations (no Math.random)
const deviations = { 'S': 1.85, 'M': 2.10, 'SD': 3.25, 'V': 1.45, 'MP': 2.70, 'C': 1.30, 'L': 1.95, 'KD': 2.50 };
const parties = Object.keys(deviations);
const anomalies = parties.map(party => ({
party, date: '2024-06-15', deviation: deviations[party],
severity: deviations[party] > 3 ? 'critical' : deviations[party] > 2 ? 'major' : 'minor'
}));
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

This mock-data test builds its own anomalies array instead of calling the production fallback (generateMockAnomalyData() in src/browser/dashboards/coalition-dashboard.ts). That means it won’t catch regressions where the real generator becomes non-deterministic again or returns an empty array. Consider invoking the real generator (or an exported helper) and asserting its determinism/non-emptiness directly.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in a5c42e4. Exported generateMockAnomalyData() from coalition-dashboard.ts and updated the test to import and call the real generator. The test now asserts determinism, non-emptiness, and known deviation values (e.g., SD.deviation === 3.25, SD.severity === 'critical') directly from the production function.

@pethers
Copy link
Member

pethers commented Mar 2, 2026

@copilot apply changes based on the comments in this thread

…nctions

- Export generateMockAnomalyData() and generateMockAnnualVotesData() from
  coalition-dashboard.ts so tests can invoke the real generators
- Export alignmentRateToPercent() from party-dashboard.ts and use it in
  createCoalitionNetwork() — tests now exercise the real conversion logic
- Coalition mock data tests import and call the real generators, asserting
  determinism, non-emptiness, and known per-party baselines
- Party alignment rate tests import and call alignmentRateToPercent(),
  ensuring the real implementation matches expected percentages

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

Copilot AI commented Mar 2, 2026

@copilot apply changes based on the comments in this thread

All 3 review comments addressed in a5c42e4:

  • Mock generators exported and tests call the real production functions
  • alignmentRateToPercent() extracted as exported helper; createCoalitionNetwork() uses it; tests exercise the real implementation

@github-actions
Copy link
Contributor

github-actions bot commented Mar 2, 2026

🔍 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
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

Copilot reviewed 32 out of 32 changed files in this pull request and generated no new comments.

@pethers pethers marked this pull request as ready for review March 2, 2026 20:18
@pethers pethers merged commit 05555d0 into main Mar 2, 2026
30 checks passed
@pethers pethers deleted the copilot/improve-dashboard-quality branch March 2, 2026 20:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dashboard Interactive dashboards (Chart.js/D3.js) html-css HTML/CSS changes i18n Internationalization/localization javascript JavaScript code changes rtl RTL language support (Arabic, Hebrew) size-l Large change (250-1000 lines) testing Test coverage translation Translation updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants