// scenario-list.js — список сценариев, запуск, поллинг
let scenarioOpen=false, scenarioPollTimer=null;
async function toggleScenario(){
const body=document.getElementById('scenario-body');
scenarioOpen=!scenarioOpen;
body.style.display=scenarioOpen?'block':'none';
if(!scenarioOpen){ stopScenarioPoll(); return; }
await loadScenarios();
}
async function loadScenarios(){
const body=document.getElementById('scenario-body');
try{
const [sr, srHistory]=await Promise.all([
fetch('/api/scenarios').then(r=>r.json()),
fetch('/api/scenario/status').then(r=>r.json()),
]);
let html='';
html+=``;
if(sr.length){
html+='
';
sr.forEach(s=>{
const seed = s.is_seed;
html+=`
`;
html+=``;
if(!seed) html+=``;
html+=``;
if(!seed) html+=``;
if(seed) html+=`seed`;
html+=`
`;
});
html+='
';
}else{
html+='Нет сценариев в БД';
}
const curVer=window.APP&&window.APP.version||'';
const verHistory=srHistory&&srHistory.filter(r=>r.app_version===curVer);
if(verHistory && verHistory.length){
const last=verHistory[0];
const icon=last.status==='OK'?'✅':last.status==='FAIL'?'❌':last.status==='RUNNING'?'⏳':'⏱';
const time=last.created_at?last.created_at.replace('T',' ').substring(0,19):'?';
const runningStyle = last.status==='RUNNING' ? 'background:#fef3c7;padding:2px 4px;border-radius:3px;' : '';
html+=`Последний: ${icon} ${_esc(last.scenario_name)} — ${last.status} (шаг ${last.current_step}/${last.total_steps}) ${last.duration_sec!=null?last.duration_sec.toFixed(1)+'s':''} — ${time}
`;
if(last.error_log) html+=`${_esc(last.error_log)}
`;
}
body.innerHTML=html;
}catch(e){body.innerHTML='Ошибка загрузки';}
}
async function runScenario(defId){
if(busy){ return; }
busy=true;
stopScenarioPoll();
const body=document.getElementById('scenario-body');
body.innerHTML=`⏳ Запуск...
`;
try{
const r=await fetch('/api/scenario/run',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({definition_id:defId})});
const d=await r.json();
if(d.error){ body.innerHTML=`Ошибка: ${_esc(d.error)}`; busy=false; return; }
const runId=d.run_id;
if(!runId){ body.innerHTML=`Ошибка: нет run_id в ответе`; busy=false; return; }
scenarioPollTimer=setInterval(async()=>{
try{
const sr=await fetch('/api/scenario/run/'+runId);
if(!sr.ok){ return; }
const last=await sr.json();
if(!last||last.error) return;
const icon=last.status==='OK'?'✅':last.status==='FAIL'?'❌':last.status==='RUNNING'?'⏳':'⏱';
const time=last.created_at?last.created_at.replace('T',' ').substring(0,19):'?';
const runningBg = last.status==='RUNNING' ? 'background:#fef3c7;padding:2px 4px;border-radius:3px;' : '';
let html=`${icon} ${_esc(last.scenario_name)} — ${last.status} (шаг ${last.current_step}/${last.total_steps}) ${last.duration_sec!=null?last.duration_sec.toFixed(1)+'s':''} — ${time}
`;
if(last.error_log) html+=`${_esc(last.error_log)}
`;
body.innerHTML=html;
if(last.status!=='RUNNING'){
stopScenarioPoll();
busy=false;
await refreshInstances();
if(historyOpen) await loadHistory();
}
}catch(e){}
},3000);
}catch(e){
body.innerHTML=`Ошибка: ${_esc(e.message)}`;
busy=false;
}
}
function stopScenarioPoll(){
if(scenarioPollTimer){ clearInterval(scenarioPollTimer); scenarioPollTimer=null; }
}