v1.2.11: scenario list — expandable steps + run confirmation
- Click on scenario name → expands to show step details:
operation → service_id (output/ref/uid) (params)
- ▶ Запустить button inside expanded view
- confirm('Запустить сценарий?') before running
- CRUD buttons (✏📋🗑) with event.stopPropagation()
- toggleScenarioSteps(defId): single-expand (closes others)
This commit is contained in:
+1
-1
@@ -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
|
from routes.api_scenario_defs import bp_defs as api_scenario_defs_bp
|
||||||
|
|
||||||
# Версия — меняется при КАЖДОМ изменении кода. Показывается в топбаре UI.
|
# Версия — меняется при КАЖДОМ изменении кода. Показывается в топбаре UI.
|
||||||
VERSION = "1.2.10"
|
VERSION = "1.2.11"
|
||||||
|
|
||||||
app = Flask(__name__, template_folder="templates", static_folder="static")
|
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")
|
app.config["NUBES_API_ENDPOINT"] = os.getenv("NUBES_API_ENDPOINT", "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc")
|
||||||
|
|||||||
@@ -23,13 +23,17 @@ async function loadScenarios(){
|
|||||||
html+='<div style="display:flex;flex-direction:column;gap:4px;margin-bottom:4px;">';
|
html+='<div style="display:flex;flex-direction:column;gap:4px;margin-bottom:4px;">';
|
||||||
sr.forEach(s=>{
|
sr.forEach(s=>{
|
||||||
const seed = s.is_seed;
|
const seed = s.is_seed;
|
||||||
html+=`<div style="display:flex;align-items:center;gap:4px;">`;
|
html+=`<div style="border:1px solid var(--brand-gray);border-radius:4px;padding:4px 6px;">`;
|
||||||
html+=`<button class="btn btn-sm" style="font-size:12px;flex:1;text-align:left;" onclick="runScenario(${s.id})" title="Запустить">▶ ${_esc(s.name)} <span style="color:var(--muted);">(${s.steps} шагов)</span></button>`;
|
html+=`<div style="display:flex;align-items:center;gap:4px;cursor:pointer;" onclick="toggleScenarioSteps(${s.id})">`;
|
||||||
if(!seed) html+=`<button class="btn btn-sm" style="font-size:13px;padding:0 6px;" onclick="editScenario(${s.id})" title="Редактировать">✏</button>`;
|
html+=`<span style="font-size:13px;font-weight:600;flex:1;">${_esc(s.name)}</span>`;
|
||||||
html+=`<button class="btn btn-sm" style="font-size:13px;padding:0 6px;" onclick="cloneScenario(${s.id},'${_esc(s.name)}')" title="Копировать">📋</button>`;
|
html+=`<span style="color:var(--muted);font-size:11px;">${s.steps} шагов</span>`;
|
||||||
if(!seed) html+=`<button class="btn btn-sm" style="font-size:13px;padding:0 6px;color:var(--destructive);" onclick="deleteScenario(${s.id},'${_esc(s.name)}')" title="Удалить">🗑</button>`;
|
if(!seed) html+=`<button class="btn btn-sm" style="font-size:12px;padding:0 6px;" onclick="event.stopPropagation();editScenario(${s.id})" title="Редактировать">✏</button>`;
|
||||||
|
html+=`<button class="btn btn-sm" style="font-size:12px;padding:0 6px;" onclick="event.stopPropagation();cloneScenario(${s.id},'${_esc(s.name)}')" title="Копировать">📋</button>`;
|
||||||
|
if(!seed) html+=`<button class="btn btn-sm" style="font-size:12px;padding:0 6px;color:var(--destructive);" onclick="event.stopPropagation();deleteScenario(${s.id},'${_esc(s.name)}')" title="Удалить">🗑</button>`;
|
||||||
if(seed) html+=`<span style="font-size:9px;color:var(--muted);padding:0 4px;">seed</span>`;
|
if(seed) html+=`<span style="font-size:9px;color:var(--muted);padding:0 4px;">seed</span>`;
|
||||||
html+=`</div>`;
|
html+=`</div>`;
|
||||||
|
html+=`<div id="scenario-steps-${s.id}" style="display:none;margin-top:4px;padding-left:8px;"></div>`;
|
||||||
|
html+=`</div>`;
|
||||||
});
|
});
|
||||||
html+='</div>';
|
html+='</div>';
|
||||||
}else{
|
}else{
|
||||||
@@ -49,8 +53,39 @@ async function loadScenarios(){
|
|||||||
}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>';}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function toggleScenarioSteps(defId) {
|
||||||
|
const el = document.getElementById('scenario-steps-' + defId);
|
||||||
|
if (!el) return;
|
||||||
|
if (el.style.display === 'block') { el.style.display = 'none'; return; }
|
||||||
|
// Загрузить шаги
|
||||||
|
try {
|
||||||
|
const r = await fetch('/api/scenario/definitions/' + defId);
|
||||||
|
const def = await r.json();
|
||||||
|
if (def.error) return;
|
||||||
|
const steps = def.steps || [];
|
||||||
|
let html = '<div style="font-size:11px;padding:4px 0;">';
|
||||||
|
steps.forEach((s, i) => {
|
||||||
|
const svcName = s.service_id ? 'сервис ' + s.service_id : '?';
|
||||||
|
html += `<div style="padding:2px 0;">${i+1}. <b>${_esc(s.operation)}</b> → ${svcName}`;
|
||||||
|
if (s.output) html += ` <span style="color:var(--muted);">(${_esc(s.output)})</span>`;
|
||||||
|
if (s.instance_ref) html += ` <span style="color:var(--muted);">→ ${_esc(s.instance_ref)}</span>`;
|
||||||
|
if (s.instance_uid) html += ` <span style="color:var(--muted);">→ ${_esc(s.instance_uid.substring(0,8))}...</span>`;
|
||||||
|
const params = Object.entries(s.params || {});
|
||||||
|
if (params.length) html += ' <span style="color:var(--muted);">(' + params.map(([k,v]) => k+'='+v).join(', ') + ')</span>';
|
||||||
|
html += '</div>';
|
||||||
|
});
|
||||||
|
html += `<button class="btn btn-sm" style="margin-top:4px;font-size:11px;background:var(--brand-primary);color:#fff;" onclick="event.stopPropagation();runScenario(${defId})">▶ Запустить</button>`;
|
||||||
|
html += '</div>';
|
||||||
|
el.innerHTML = html;
|
||||||
|
el.style.display = 'block';
|
||||||
|
// Закрыть другие
|
||||||
|
document.querySelectorAll('[id^="scenario-steps-"]').forEach(e => { if (e !== el) e.style.display = 'none'; });
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
async function runScenario(defId){
|
async function runScenario(defId){
|
||||||
if(busy){ return; }
|
if(busy){ return; }
|
||||||
|
if(!confirm('Запустить сценарий?')) return;
|
||||||
busy=true;
|
busy=true;
|
||||||
stopScenarioPoll();
|
stopScenarioPoll();
|
||||||
const body=document.getElementById('scenario-body');
|
const body=document.getElementById('scenario-body');
|
||||||
|
|||||||
Reference in New Issue
Block a user