Add metrics_visualization/js/ui.js
This commit is contained in:
parent
8896e957bc
commit
1bbe7a7086
1 changed files with 124 additions and 0 deletions
124
metrics_visualization/js/ui.js
Normal file
124
metrics_visualization/js/ui.js
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
'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).
|
||||||
Loading…
Reference in a new issue