exit_metrics_analysis/metrics_visualization/js/ui.js

124 lines
No EOL
4.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
/**
* @module ui
* Verantwortlich für Rendering und Interaktion der UI-Komponenten.
*/
/**
* Rendert oder aktualisiert das Diagramm basierend auf Metrikdaten.
* @param {Array<Object>} metricsData - Metrikdaten aus der API.
* @param {HTMLElement} chartContainer - Zielcontainer (z. B. Canvas- oder SVG-Element).
*/
export function renderChart(metricsData, chartContainer) {
if (!chartContainer) return;
chartContainer.innerHTML = '';
if (!Array.isArray(metricsData) || metricsData.length === 0) {
const msg = document.createElement('p');
msg.textContent = 'Keine Metrikdaten verfügbar.';
chartContainer.appendChild(msg);
return;
}
// Beispiel: einfache Balkenvisualisierung auf Basis von warn_rate
const maxWarnRate = Math.max(...metricsData.map(m => m.warn_rate ?? 0));
const chart = document.createElement('div');
chart.classList.add('metrics-visualization__bars');
metricsData.forEach(run => {
const bar = document.createElement('div');
bar.classList.add('metrics-visualization__bar');
const height = maxWarnRate > 0 ? (run.warn_rate / maxWarnRate) * 100 : 0;
bar.style.setProperty('--bar-height', `${height}%`);
bar.setAttribute('title', `Run ${run.run_id}: warn_rate ${run.warn_rate}`);
const label = document.createElement('span');
label.classList.add('metrics-visualization__bar-label');
label.textContent = run.run_id;
bar.appendChild(label);
chart.appendChild(bar);
});
chartContainer.appendChild(chart);
}
/**
* Füllt die Tabelle mit Metrikdaten und Run-Vergleichen.
* @param {Array<Object>} metricsData - Metrikdaten aus der API.
* @param {HTMLTableSectionElement} tableBody - tbody-Element zur Befüllung.
*/
export function renderTable(metricsData, tableBody) {
if (!tableBody) return;
tableBody.innerHTML = '';
if (!Array.isArray(metricsData) || metricsData.length === 0) {
const row = document.createElement('tr');
const cell = document.createElement('td');
cell.colSpan = 6;
cell.textContent = 'Keine Daten vorhanden';
row.appendChild(cell);
tableBody.appendChild(row);
return;
}
metricsData.forEach(run => {
const row = document.createElement('tr');
const idCell = document.createElement('td');
idCell.textContent = run.run_id;
const setupCell = document.createElement('td');
setupCell.textContent = run.setup_fingerprint;
const warnCell = document.createElement('td');
warnCell.textContent = run.warn_rate?.toFixed(3) ?? '-';
const unknownCell = document.createElement('td');
unknownCell.textContent = run.unknown_rate?.toFixed(3) ?? '-';
const deltaCell = document.createElement('td');
deltaCell.textContent = run.delta_t_stats ?? '-';
const timeCell = document.createElement('td');
const date = new Date(run.timestamp);
timeCell.textContent = isNaN(date.getTime()) ? '-' : date.toLocaleString();
row.append(idCell, setupCell, warnCell, unknownCell, deltaCell, timeCell);
tableBody.appendChild(row);
});
}
/**
* Filtert Metrikdaten anhand der vom Nutzer gewählten Kriterien.
* @param {Array<Object>} allMetrics - Alle verfügbaren Metrikdaten.
* @param {Object} filters - Vom Nutzer gewählte Filterkriterien.
* @param {('all'|'pinned'|'unpinned')} [filters.type='all'] - Filtern nach pinned/unpinned.
* @param {string|null} [filters.setupFingerprint=null] - Optionaler Setup-Fingerprint zum Vergleich.
* @returns {Array<Object>} Gefilterte Metrikdaten.
*/
export function applyFilters(allMetrics, filters = {}) {
const { type = 'all', setupFingerprint = null } = filters;
let result = Array.isArray(allMetrics) ? [...allMetrics] : [];
if (setupFingerprint) {
result = result.filter(d => d.setup_fingerprint === setupFingerprint);
}
if (type === 'pinned') {
result = result.filter(d => d.pinned === true);
} else if (type === 'unpinned') {
result = result.filter(d => d.pinned === false);
}
return result;
}
/**
* Initialisiert UI-Events für Filterung.
* @param {Function} onFilterChange - Callback, z.B. fetchMetrics(Filter).
*/
export function initFilterListeners(onFilterChange) {
const filterForm = document.querySelector('#filter-panel');
if (!filterForm) return;
filterForm.addEventListener('change', () => {
const type = filterForm.querySelector('[name="runFilter"]:checked')?.value ?? 'all';
const setupFingerprint = filterForm.querySelector('[name="setupFingerprint"]')?.value || null;
onFilterChange({ type, setupFingerprint });
});
}
// Bar-Darstellung Style-Vorgabe per CSS Variable (wird über CSS Datei gehandhabt).