/* ui.js - UI Renderer for Frozen Runs Visualization */ /** * Zeichnet Bootstrap-Verteilungen und CI-Diagramme für die gegebenen Metrikdaten. * @param {Array} metricsData - Array der Metrikobjekte mit Namen, Run-ID, pinned_flag, Effektgröße und CI. */ export function renderCharts(metricsData = []) { const chartContainer = document.querySelector('#chartsContainer'); if (!chartContainer) return; chartContainer.innerHTML = ''; metricsData.forEach(metric => { const { metricName, effectSize, ci_lower, ci_upper } = metric; const chartEl = document.createElement('div'); chartEl.className = 'chart-item'; const title = document.createElement('h3'); title.textContent = metricName; const canvas = document.createElement('canvas'); canvas.setAttribute('role', 'img'); canvas.setAttribute('aria-label', `Bootstrap-Verteilung für ${metricName}`); chartEl.appendChild(title); chartEl.appendChild(canvas); chartContainer.appendChild(chartEl); // Example mock rendering logic (replace with chart lib rendering) const ctx = canvas.getContext('2d'); if (ctx) { ctx.fillStyle = '#cce5ff'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#004085'; ctx.fillText(`Effektgröße: ${effectSize}`, 10, 20); ctx.fillText(`CI: [${ci_lower}, ${ci_upper}]`, 10, 40); } }); } /** * Erstellt die Tabellenansicht der Metriken mit Effektgrößen und CI. * @param {Array} metricsData - Array strukturierter Metrikdaten. */ export function renderMetricsTable(metricsData = []) { const tableContainer = document.querySelector('#metricsTable'); if (!tableContainer) return; tableContainer.innerHTML = ''; const table = document.createElement('table'); table.className = 'table table-striped'; const thead = document.createElement('thead'); const headerRow = document.createElement('tr'); ['Metrik', 'Run-ID', 'Pinned', 'Effektgröße', 'CI Lower', 'CI Upper'].forEach(label => { const th = document.createElement('th'); th.textContent = label; headerRow.appendChild(th); }); thead.appendChild(headerRow); table.appendChild(thead); const tbody = document.createElement('tbody'); metricsData.forEach(row => { const tr = document.createElement('tr'); const tdName = document.createElement('td'); tdName.textContent = row.metricName; const tdRun = document.createElement('td'); tdRun.textContent = row.run_id ?? '-'; const tdPinned = document.createElement('td'); tdPinned.textContent = row.pinned_flag ? 'pinned' : 'unpinned'; const tdEffect = document.createElement('td'); tdEffect.textContent = row.effectSize; const tdCiLow = document.createElement('td'); tdCiLow.textContent = row.ci_lower; const tdCiHigh = document.createElement('td'); tdCiHigh.textContent = row.ci_upper; [tdName, tdRun, tdPinned, tdEffect, tdCiLow, tdCiHigh].forEach(td => tr.appendChild(td)); tbody.appendChild(tr); }); table.appendChild(tbody); tableContainer.appendChild(table); } /** * Aktualisiert Diagramme und Tabellen basierend auf der Filterauswahl. * @param {string} filter - 'pinned' oder 'unpinned'. * @param {Array} allMetrics - gesamte Metrikdaten. */ export function updateUIOnFilter(filter, allMetrics = []) { const filtered = allMetrics.filter(m => { if (filter === 'pinned') return m.pinned_flag; if (filter === 'unpinned') return !m.pinned_flag; return true; }); renderCharts(filtered); renderMetricsTable(filtered); const statusEl = document.querySelector('#filterStatus'); if (statusEl) statusEl.textContent = `Aktueller Filter: ${filter}`; }