Add result_visualization/js/ui.js

This commit is contained in:
Mika 2026-01-26 12:23:43 +00:00
parent 011c95696d
commit ab251d7e4c

View file

@ -0,0 +1,129 @@
/* eslint-disable no-undef */
/**
* @module ui
* Präsentationslogik für die Visualisierung der Analyse-Ergebnisse.
* Verantwortlich für DOM-Manipulationen basierend auf geladenen Daten.
*/
/**
* Rendert eine Übersicht der aggregierten Statistiken zu Runs im Hauptbereich.
* @param {Array<Object>} results - Teil der API-Response mit Statistiken.
*/
export function renderOverview(results = []) {
const container = document.getElementById('results-overview');
if (!container) return;
// Defensive: Cleanup und Fallback
container.innerHTML = '';
if (!Array.isArray(results) || results.length === 0) {
container.textContent = 'Keine Ergebnisse verfügbar.';
return;
}
// Aggregation - Beispielhafte Kennzahlen
const totalRuns = results.length;
const pinnedRuns = results.filter(r => r.type === 'pinned').length;
const unpinnedRuns = totalRuns - pinnedRuns;
const avgCorrelations = (results
.map(r => r?.statistics?.correlation ?? 0)
.reduce((a, b) => a + b, 0)) / totalRuns;
const overviewHTML = `
<section class="overview__stats" aria-label="Ergebnisübersicht">
<h2>Analyseübersicht</h2>
<ul class="overview__list">
<li>Gesamtanzahl Runs: <strong>${totalRuns}</strong></li>
<li>Pinned Runs: <strong>${pinnedRuns}</strong></li>
<li>Unpinned Runs: <strong>${unpinnedRuns}</strong></li>
<li>Ø Korrelation: <strong>${avgCorrelations.toFixed(3)}</strong></li>
</ul>
</section>
`;
container.innerHTML = overviewHTML;
}
/**
* Aktualisiert oder rendert Diagramme auf Basis der gegebenen API-Daten.
* Wird bei Initialisierung und Filter-Events aufgerufen.
* @param {Array<Object>} runData - Liste der Runs mit chartData-Feldern.
* @param {string} [filterType] - Optionaler Filter (pinned/unpinned)
*/
export function updateCharts(runData = [], filterType) {
const chartPanel = document.getElementById('chart-panel');
if (!chartPanel) return;
chartPanel.innerHTML = '';
// Optionales Filtern
const filteredData = filterType
? runData.filter(r => r.type === filterType)
: runData;
if (filteredData.length === 0) {
chartPanel.textContent = 'Keine Diagrammdaten verfügbar.';
return;
}
// Dynamisches Rendern pro Run
filteredData.forEach(run => {
const canvas = document.createElement('canvas');
canvas.setAttribute('aria-label', `Chart für Run ${run.id}`);
canvas.setAttribute('role', 'img');
chartPanel.appendChild(canvas);
const ctx = canvas.getContext('2d');
if (ctx && run.chartData && Chart) {
// Chart.js Standard-Konfiguration
new Chart(ctx, {
type: 'line',
data: {
labels: run.chartData.labels,
datasets: [{
label: `${run.type} Run ${run.id}`,
data: run.chartData.values,
borderColor: run.type === 'pinned' ? '#007ACC' : '#FF9900',
fill: false,
tension: 0.1
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: true,
labels: {
color: '#333'
}
},
tooltip: {
mode: 'index',
intersect: false
}
},
interaction: {
mode: 'nearest',
axis: 'x',
intersect: false
},
scales: {
x: {
title: {
display: true,
text: 'Parameter Index'
}
},
y: {
title: {
display: true,
text: 'Wert'
}
}
}
}
});
}
});
}
// Hinweis: Wird von app.initApp() und Filter-Events importiert und genutzt.