Add visualization_ui/js/ui.js
This commit is contained in:
parent
b0cc8652ed
commit
2bf072fd99
1 changed files with 100 additions and 0 deletions
100
visualization_ui/js/ui.js
Normal file
100
visualization_ui/js/ui.js
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
/**
|
||||||
|
* UI Rendering Module for Visualization UI
|
||||||
|
* Handles rendering of Alerts table and Outlier summary panel.
|
||||||
|
*
|
||||||
|
* @module ui
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the Max-only alert data into a table structure within #alert-dashboard.
|
||||||
|
* @param {Array<Object>} alerts - Array of alert objects from /alert-data endpoint.
|
||||||
|
*/
|
||||||
|
export function renderAlertDashboard(alerts = []) {
|
||||||
|
const container = document.getElementById('alert-dashboard');
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
container.innerHTML = '';
|
||||||
|
const status = document.createElement('div');
|
||||||
|
status.className = 'visualization_ui__status';
|
||||||
|
|
||||||
|
if (!Array.isArray(alerts) || alerts.length === 0) {
|
||||||
|
status.textContent = 'Keine Alert-Daten vorhanden.';
|
||||||
|
container.appendChild(status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const table = document.createElement('table');
|
||||||
|
table.className = 'visualization_ui__table';
|
||||||
|
|
||||||
|
const thead = document.createElement('thead');
|
||||||
|
thead.innerHTML = `
|
||||||
|
<tr>
|
||||||
|
<th>corr_id</th>
|
||||||
|
<th>stratum</th>
|
||||||
|
<th>expires_at_dist_hours</th>
|
||||||
|
<th>retry_total_overhead_ms</th>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
table.appendChild(thead);
|
||||||
|
|
||||||
|
const tbody = document.createElement('tbody');
|
||||||
|
for (const alert of alerts) {
|
||||||
|
const row = document.createElement('tr');
|
||||||
|
row.innerHTML = `
|
||||||
|
<td>${escapeHTML(alert.corr_id ?? '')}</td>
|
||||||
|
<td>${escapeHTML(alert.stratum ?? '')}</td>
|
||||||
|
<td>${escapeHTML(alert.expires_at_dist_hours ?? '')}</td>
|
||||||
|
<td>${escapeHTML(alert.retry_total_overhead_ms ?? '')}</td>
|
||||||
|
`;
|
||||||
|
tbody.appendChild(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.appendChild(tbody);
|
||||||
|
container.appendChild(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays outlier analysis summary metrics inside #outlier-summary panel.
|
||||||
|
* @param {Object} report - Report object fetched from /outlier-report endpoint.
|
||||||
|
*/
|
||||||
|
export function renderOutlierSummary(report = {}) {
|
||||||
|
const container = document.getElementById('outlier-summary');
|
||||||
|
if (!container) return;
|
||||||
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
const summary = document.createElement('div');
|
||||||
|
summary.className = 'visualization_ui__outlier-summary';
|
||||||
|
|
||||||
|
if (!Object.keys(report).length) {
|
||||||
|
summary.textContent = 'Noch keine Outlier-Daten verfügbar.';
|
||||||
|
container.appendChild(summary);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const list = document.createElement('dl');
|
||||||
|
for (const [key, value] of Object.entries(report)) {
|
||||||
|
const term = document.createElement('dt');
|
||||||
|
term.textContent = key;
|
||||||
|
const desc = document.createElement('dd');
|
||||||
|
desc.textContent = typeof value === 'number' ? value.toFixed(3) : String(value);
|
||||||
|
list.appendChild(term);
|
||||||
|
list.appendChild(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.appendChild(list);
|
||||||
|
container.appendChild(summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escapes potential HTML in strings to prevent XSS injection.
|
||||||
|
* @param {string} str
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function escapeHTML(str) {
|
||||||
|
return String(str)
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''');
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue