From f0d875ffa9958a47829390dec35befdb85db2d14 Mon Sep 17 00:00:00 2001 From: "a.tolmachev" Date: Sat, 2 May 2026 11:24:57 +0000 Subject: [PATCH] ui: harden logs and usage rendering --- apps/ui/js/logs.js | 15 ++++++--- apps/ui/js/usage.js | 74 ++++++++++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 29 deletions(-) diff --git a/apps/ui/js/logs.js b/apps/ui/js/logs.js index fbfdc90..682bf73 100644 --- a/apps/ui/js/logs.js +++ b/apps/ui/js/logs.js @@ -54,6 +54,13 @@ document.addEventListener('DOMContentLoaded', function () { return date.toISOString().slice(11, 23); } + function element(tag, className, text) { + var node = document.createElement(tag); + if (className) node.className = className; + if (text !== undefined && text !== null) node.textContent = text; + return node; + } + function statusClass(statusCode) { if (!statusCode) { return ''; @@ -106,11 +113,9 @@ document.addEventListener('DOMContentLoaded', function () { function renderEmpty(title, message) { logList.innerHTML = ''; - var empty = document.createElement('div'); - empty.className = 'empty-state'; - empty.innerHTML = - '
' + title + '
' + - '
' + message + '
'; + var empty = element('div', 'empty-state'); + empty.appendChild(element('div', 'empty-state-title', title)); + empty.appendChild(element('div', 'empty-state-text', message)); logList.appendChild(empty); } diff --git a/apps/ui/js/usage.js b/apps/ui/js/usage.js index 6954999..94d34c8 100644 --- a/apps/ui/js/usage.js +++ b/apps/ui/js/usage.js @@ -33,6 +33,13 @@ document.addEventListener('DOMContentLoaded', function () { return workspace ? workspace.id : null; } + function element(tag, className, text) { + var node = document.createElement(tag); + if (className) node.className = className; + if (text !== undefined && text !== null) node.textContent = text; + return node; + } + function formatCount(value) { return Number(value || 0).toLocaleString(currentLocale()); } @@ -196,19 +203,30 @@ document.addEventListener('DOMContentLoaded', function () { return normalized; } + function buildEmptyState(title, message, compact) { + var empty = element('div', 'empty-state'); + if (compact) { + empty.style.padding = '0'; + } + empty.appendChild(element('div', 'empty-state-title', title)); + empty.appendChild(element('div', 'empty-state-text', message)); + return empty; + } + function renderEmpty(title, message) { - chartWrap.innerHTML = - '
' + - '
' + title + '
' + - '
' + message + '
' + - '
'; - tableBody.innerHTML = - '' + - '
' + - '
' + title + '
' + - '
' + message + '
' + - '
' + - ''; + chartWrap.innerHTML = ''; + var chartEmpty = buildEmptyState(title, message, false); + chartEmpty.style.width = '100%'; + chartWrap.appendChild(chartEmpty); + + tableBody.innerHTML = ''; + var row = document.createElement('tr'); + var cell = document.createElement('td'); + cell.colSpan = 7; + cell.style.padding = '24px'; + cell.appendChild(buildEmptyState(title, message, true)); + row.appendChild(cell); + tableBody.appendChild(row); } function renderStats() { @@ -249,11 +267,13 @@ document.addEventListener('DOMContentLoaded', function () { chartWrap.innerHTML = ''; if (!timeline.length) { - chartWrap.innerHTML = - '
' + - '
' + tKey('usage.chart.empty.title') + '
' + - '
' + tKey('usage.chart.empty.sub') + '
' + - '
'; + var chartEmpty = buildEmptyState( + tKey('usage.chart.empty.title'), + tKey('usage.chart.empty.sub'), + false + ); + chartEmpty.style.width = '100%'; + chartWrap.appendChild(chartEmpty); return; } @@ -285,13 +305,19 @@ document.addEventListener('DOMContentLoaded', function () { tableBody.innerHTML = ''; if (!operations.length) { - tableBody.innerHTML = - '' + - '
' + - '
' + tKey('usage.table.empty.title') + '
' + - '
' + tKey('usage.table.empty.sub') + '
' + - '
' + - ''; + var row = document.createElement('tr'); + var cell = document.createElement('td'); + cell.colSpan = 7; + cell.style.padding = '24px'; + cell.appendChild( + buildEmptyState( + tKey('usage.table.empty.title'), + tKey('usage.table.empty.sub'), + true + ) + ); + row.appendChild(cell); + tableBody.appendChild(row); return; }