// 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; } }