Подробные комментарии ко всем JS-файлам фронтенда
This commit is contained in:
@@ -1,7 +1,19 @@
|
||||
// history.js — история тестов
|
||||
// history.js — история тестов (вид «История»)
|
||||
//
|
||||
// Загружает последние 50 записей из GET /api/history.
|
||||
// Каждая запись — строка таблицы: время, операция, инстанс, статус, длительность.
|
||||
// При клике на строку — раскрываются этапы выполнения (stages).
|
||||
//
|
||||
// Цветовая маркировка:
|
||||
// RUNNING → жёлтый фон (#fef3c7)
|
||||
// FAIL → красный фон (#fef2f2)
|
||||
|
||||
let historyOpen=false;
|
||||
|
||||
/**
|
||||
* Переключить панель истории (открыть/закрыть).
|
||||
* При открытии — автозагрузка через loadHistory().
|
||||
*/
|
||||
async function toggleHistory(){
|
||||
const body=document.getElementById('history-body');
|
||||
historyOpen=!historyOpen;
|
||||
@@ -9,19 +21,34 @@ async function toggleHistory(){
|
||||
if(historyOpen) await loadHistory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Загрузить и отрисовать историю.
|
||||
*
|
||||
* Формат ответа API: массив объектов:
|
||||
* [{created_at, op_name, display_name, instance_uid, status, duration_sec, stages}, ...]
|
||||
*/
|
||||
async function loadHistory(){
|
||||
const body=document.getElementById('history-body');
|
||||
if(!body||body.style.display==='none') return;
|
||||
try{
|
||||
const r=await fetch('/api/history');
|
||||
const rows=await r.json();
|
||||
if(!rows||!rows.length){body.innerHTML='<span style="color:var(--muted);font-size:11px;">Нет записей</span>'; return;}
|
||||
if(!rows||!rows.length){
|
||||
body.innerHTML='<span style="color:var(--muted);font-size:11px;">Нет записей</span>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Таблица с фиксированной шириной колонок
|
||||
let html='<table style="width:100%;font-size:11px;table-layout:fixed;">';
|
||||
html+='<tr><th style="padding:2px 6px;width:130px;">Время</th><th style="padding:2px 6px;width:90px;">Операция</th><th style="padding:2px 6px;">Инстанс</th><th style="padding:2px 6px;width:50px;">Статус</th><th style="padding:2px 6px;width:55px;">Длит.</th></tr>';
|
||||
|
||||
rows.forEach((r, i)=>{
|
||||
const time=r.created_at?r.created_at.replace('T',' ').substring(0,19):'?';
|
||||
const cls=r.status==='OK'?'badge-success':r.status==='FAIL'?'badge' :'';
|
||||
const cls=r.status==='OK'?'badge-success':r.status==='FAIL'?'badge':'';
|
||||
// Цвет фона строки: RUNNING → жёлтый, FAIL → красный
|
||||
const stCls=r.status==='RUNNING'?'background:#fef3c7;':r.status==='FAIL'?'background:#fef2f2;':'';
|
||||
|
||||
// Строка таблицы — кликабельна (раскрывает этапы)
|
||||
html+=`<tr style="cursor:pointer;${stCls}" onclick="toggleHistoryRow(${i})">
|
||||
<td style="padding:2px 6px;">${time}</td>
|
||||
<td style="padding:2px 6px;">${_esc(r.op_name||'?')}</td>
|
||||
@@ -29,24 +56,43 @@ async function loadHistory(){
|
||||
<td style="padding:2px 6px;"><span class="badge ${cls}" style="font-size:9px;">${_esc(r.status||'?')}</span></td>
|
||||
<td style="padding:2px 6px;">${r.duration_sec!=null?r.duration_sec.toFixed(1)+'s':'-'}</td>
|
||||
</tr>`;
|
||||
|
||||
// Скрытая строка с этапами (раскрывается по клику)
|
||||
html+=`<tr id="hist-stages-${i}" style="display:none;"><td colspan="5" style="padding:4px 8px;">${renderStages(r.stages)}</td></tr>`;
|
||||
});
|
||||
html+='</table>';
|
||||
body.innerHTML=html;
|
||||
}catch(e){body.innerHTML='<span style="color:var(--destructive);font-size:11px;">Ошибка загрузки</span>';}
|
||||
}catch(e){
|
||||
body.innerHTML='<span style="color:var(--destructive);font-size:11px;">Ошибка загрузки</span>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Раскрыть/скрыть строку с этапами для записи истории.
|
||||
*
|
||||
* @param {number} i — индекс записи в массиве rows
|
||||
*/
|
||||
function toggleHistoryRow(i) {
|
||||
const el = document.getElementById('hist-stages-' + i);
|
||||
if (!el) return;
|
||||
el.style.display = el.style.display === 'none' ? 'table-row' : 'none';
|
||||
}
|
||||
|
||||
/**
|
||||
* Отрисовать этапы выполнения для записи истории.
|
||||
*
|
||||
* Каждый этап: иконка (✅/❌/⏳) + название + время + длительность.
|
||||
*
|
||||
* @param {Array} stages — [{stage, dtStart, dtFinish, isSuccessful, duration}, ...]
|
||||
* @returns {string} HTML
|
||||
*/
|
||||
function renderStages(stages) {
|
||||
if (!stages || !stages.length) return '<span style="color:var(--muted);font-size:10px;">Нет данных об этапах</span>';
|
||||
if (!stages || !stages.length)
|
||||
return '<span style="color:var(--muted);font-size:10px;">Нет данных об этапах</span>';
|
||||
|
||||
let html = '<div style="font-size:11px;"><b>Этапы выполнения</b></div>';
|
||||
stages.forEach(s => {
|
||||
const done = !!s.dtFinish;
|
||||
const done = !!s.dtFinish; // этап завершён?
|
||||
const icon = done ? (s.isSuccessful ? '✅' : '❌') : '⏳';
|
||||
const start = s.dtStart ? s.dtStart.replace('T',' ').substring(0,19) : '?';
|
||||
const finish = s.dtFinish ? s.dtFinish.replace('T',' ').substring(0,19) : '...';
|
||||
|
||||
Reference in New Issue
Block a user