v1.0.96: history UI — collapsible table below instances, auto-refresh on finish

This commit is contained in:
2026-07-28 10:15:31 +04:00
parent 99b0a79cbd
commit be9e165b4f
3 changed files with 41 additions and 1 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ from routes.api import bp as api_bp
from routes.api_test import bp as api_test_bp
# Версия — меняется при КАЖДОМ изменении кода. Показывается в топбаре UI.
VERSION = "1.0.95"
VERSION = "1.0.96"
app = Flask(__name__, template_folder="templates", static_folder="static")
app.config["NUBES_API_ENDPOINT"] = os.getenv("NUBES_API_ENDPOINT", "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc")
+34
View File
@@ -267,6 +267,7 @@ async function executeOp(params){
if(sd.status==='OK'){
await refreshInstances();
}
if(historyOpen) await loadHistory();
}
},2000);
}catch(e){
@@ -311,6 +312,39 @@ async function refreshInstances(){
document.getElementById('inst-list').innerHTML=html;
}
// === История тестов ===
let historyOpen=false;
async function toggleHistory(){
const body=document.getElementById('history-body');
historyOpen=!historyOpen;
body.style.display=historyOpen?'block':'none';
if(historyOpen) await loadHistory();
}
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;}
let html='<table style="width:100%;font-size:11px;">';
html+='<tr><th style="padding:2px 6px;">Время</th><th style="padding:2px 6px;">Операция</th><th style="padding:2px 6px;">Инстанс</th><th style="padding:2px 6px;">Статус</th><th style="padding:2px 6px;">Длит.</th></tr>';
rows.forEach(r=>{
const time=r.created_at?r.created_at.replace('T',' ').substring(0,19):'?';
const cls=r.status==='OK'?'badge-success':'';
html+=`<tr>
<td style="padding:2px 6px;">${time}</td>
<td style="padding:2px 6px;">${r.op_name||'?'}</td>
<td style="padding:2px 6px;">${r.display_name||r.instance_uid||'?'}</td>
<td style="padding:2px 6px;"><span class="badge ${cls}" style="font-size:9px;">${r.status||'?'}</span></td>
<td style="padding:2px 6px;">${r.duration_sec!=null?r.duration_sec.toFixed(1)+'s':'-'}</td>
</tr>`;
});
html+='</table>';
body.innerHTML=html;
}catch(e){body.innerHTML='<span style="color:var(--destructive);font-size:11px;">Ошибка загрузки</span>';}
}
// === Панель логов (скрыта, показывается по кнопке) ===
let logPollTimer=null;
function startLogPoll(){
+6
View File
@@ -120,6 +120,12 @@
</div>
<div id="stages-box" style="display:none;padding:0 8px 8px;max-height:200px;overflow-y:auto;"></div>
</div>
<div class="card" id="history-card" style="margin-top:8px;">
<div class="card-header" style="font-size:12px;cursor:pointer;" onclick="toggleHistory()">История <span style="color:var(--muted);font-size:10px;">(последние 50)</span></div>
<div class="card-body" style="padding:4px;display:none;max-height:300px;overflow-y:auto;" id="history-body">
<span style="color:var(--muted);font-size:11px;">Загрузка...</span>
</div>
</div>
</div>
</div>