diff --git a/site/app.py b/site/app.py index bd59e49..76f63d5 100644 --- a/site/app.py +++ b/site/app.py @@ -19,7 +19,7 @@ from routes.api_scenario_run import bp_run as api_scenario_run_bp from routes.api_scenario_defs import bp_defs as api_scenario_defs_bp # Версия — меняется при КАЖДОМ изменении кода. Показывается в топбаре UI. -VERSION = "1.2.13" +VERSION = "1.2.14" 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") diff --git a/site/routes/api_test.py b/site/routes/api_test.py index 26aab87..8563e7e 100644 --- a/site/routes/api_test.py +++ b/site/routes/api_test.py @@ -387,7 +387,7 @@ def api_history(): SELECT id, created_at, client_id, stand, user_email, svc_id, svc_name, op_name, svc_op_id, op_uid, instance_uid, display_name, - status, duration_sec, error_log, app_version + status, duration_sec, error_log, app_version, stages FROM runs WHERE client_id = %s AND stand = %s ORDER BY created_at DESC diff --git a/site/static/js/history.js b/site/static/js/history.js index c1d67e0..755feae 100644 --- a/site/static/js/history.js +++ b/site/static/js/history.js @@ -18,18 +18,43 @@ async function loadHistory(){ if(!rows||!rows.length){body.innerHTML='Нет записей'; return;} let html=''; html+=''; - rows.forEach(r=>{ + rows.forEach((r, i)=>{ const time=r.created_at?r.created_at.replace('T',' ').substring(0,19):'?'; - const cls=r.status==='OK'?'badge-success':''; - html+=` + const cls=r.status==='OK'?'badge-success':r.status==='FAIL'?'badge' :''; + const stCls=r.status==='RUNNING'?'background:#fef3c7;':r.status==='FAIL'?'background:#fef2f2;':''; + html+=``; + html+=``; }); html+='
ВремяОперацияИнстансСтатусДлит.
${time} ${_esc(r.op_name||'?')} ${_esc(r.display_name||r.instance_uid||'?')} ${_esc(r.status||'?')} ${r.duration_sec!=null?r.duration_sec.toFixed(1)+'s':'-'}
'; body.innerHTML=html; }catch(e){body.innerHTML='Ошибка загрузки';} } + +function toggleHistoryRow(i) { + const el = document.getElementById('hist-stages-' + i); + if (!el) return; + el.style.display = el.style.display === 'none' ? 'table-row' : 'none'; +} + +function renderStages(stages) { + if (!stages || !stages.length) return 'Нет данных об этапах'; + let html = '
Этапы выполнения
'; + stages.forEach(s => { + 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) : '...'; + const dur = s.duration != null ? s.duration.toFixed(1) + ' сек' : '—'; + html += `
`; + html += `${icon} ${_esc(s.stage||'?')}`; + html += `${start} → ${finish} (${dur})`; + html += `
`; + }); + return html; +}