diff --git a/results_visualization/js/uiRenderer.js b/results_visualization/js/uiRenderer.js new file mode 100644 index 0000000..f35ca3c --- /dev/null +++ b/results_visualization/js/uiRenderer.js @@ -0,0 +1,121 @@ +'use strict'; + +/** + * uiRenderer.js + * Verantwortlich für DOM-Manipulation zur Anzeige von Daten. + * Enthält Rendering-Methoden für Timeline, Statistik-Zusammenfassungen und Tabellen. + */ + +/** + * Rendert die Timeline der write_pre / write_post Ereignisse. + * @param {Array<{corr_id: string, type: string, timestamp: number, details?: object}>} eventPairs + */ +export function renderTimeline(eventPairs = []) { + const panel = document.getElementById('timeline-panel'); + if (!panel) return; + panel.innerHTML = ''; + + if (!Array.isArray(eventPairs) || eventPairs.length === 0) { + const msg = document.createElement('p'); + msg.textContent = 'Keine Ereignisse vorhanden.'; + panel.appendChild(msg); + return; + } + + const list = document.createElement('ul'); + list.className = 'timeline__list'; + + eventPairs.forEach(event => { + const item = document.createElement('li'); + item.className = `timeline__item timeline__item--${event.type}`; + + const label = document.createElement('div'); + label.className = 'timeline__label'; + const tsDate = new Date(event.timestamp).toLocaleTimeString(); + label.textContent = `${event.type} [${tsDate}] (corr: ${event.corr_id})`; + + item.appendChild(label); + list.appendChild(item); + }); + + panel.appendChild(list); +} + +/** + * Aktualisiert Statistik-Karten und Übersichten. + * @param {Object} statsObj - Enthält berechnete Statistiken + * @param {number} statsObj.totalEvents - Gesamtanzahl der Events + * @param {number} statsObj.avgDuration - Durchschnittliche Dauer zwischen pre/post + * @param {number} statsObj.numWrites - Anzahl write Events + * @param {number} statsObj.numReads - Anzahl read Events + */ +export function renderStatsSummary(statsObj = {}) { + const container = document.getElementById('stats-summary'); + if (!container) return; + + const { totalEvents = 0, avgDuration = 0, numWrites = 0, numReads = 0 } = statsObj; + container.innerHTML = ''; + + const createCard = (label, value) => { + const card = document.createElement('div'); + card.className = 'stats__card'; + const header = document.createElement('h3'); + header.textContent = label; + const val = document.createElement('p'); + val.textContent = value; + card.append(header, val); + return card; + }; + + container.append( + createCard('Gesamtanzahl Events', totalEvents), + createCard('Durchschnittliche Dauer (ms)', avgDuration.toFixed(2)), + createCard('Writes', numWrites), + createCard('Reads', numReads) + ); +} + +/** + * Füllt Tabelle mit den Schreib-/Lesepaaren. + * @param {Array<{corr_id: string, type: string, timestamp: number, details?: object}>} dataPairs + */ +export function renderDataTable(dataPairs = []) { + const table = document.getElementById('data-table'); + if (!table) return; + + const tbody = table.querySelector('tbody') || document.createElement('tbody'); + tbody.innerHTML = ''; + + if (!Array.isArray(dataPairs) || dataPairs.length === 0) { + const tr = document.createElement('tr'); + const td = document.createElement('td'); + td.colSpan = 4; + td.textContent = 'Keine Daten verfügbar'; + tr.appendChild(td); + tbody.appendChild(tr); + table.appendChild(tbody); + return; + } + + dataPairs.forEach(item => { + const tr = document.createElement('tr'); + const tsFmt = new Date(item.timestamp).toLocaleString(); + + const cols = [ + item.corr_id, + item.type, + tsFmt, + item.details ? JSON.stringify(item.details) : '-' + ]; + + cols.forEach(value => { + const td = document.createElement('td'); + td.textContent = value; + tr.appendChild(td); + }); + + tbody.appendChild(tr); + }); + + table.appendChild(tbody); +}