v1.2.6: instance dropdown: outputs only + cloud button + RUNNING highlight
scenario-form.js: - renderStepRow: non-create dropdown shows only 🆕 outputs by default - «📥 Из облака» button toggles cloud autotest-* instances in same select - toggleCloudInstances(idx): snapshot, flip _showCloud flag, re-render - Button label: 📥 Из облака ↔ ➖ Скрыть облако scenario-list.js: - RUNNING status: yellow background #fef3c7 on both loadScenarios() and runScenario() polling
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.5"
|
VERSION = "1.2.6"
|
||||||
|
|
||||||
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")
|
||||||
|
|||||||
@@ -221,15 +221,19 @@ function renderStepRow(idx, step) {
|
|||||||
} else if (op) {
|
} else if (op) {
|
||||||
let refOpts = '<option value="">— инстанс —</option>';
|
let refOpts = '<option value="">— инстанс —</option>';
|
||||||
prevOutputs.forEach(o => { refOpts += `<option value="${o}" ${o == ref ? 'selected' : ''}>🆕 ${_esc(o)} (из шага)</option>`; });
|
prevOutputs.forEach(o => { refOpts += `<option value="${o}" ${o == ref ? 'selected' : ''}>🆕 ${_esc(o)} (из шага)</option>`; });
|
||||||
if (st.cloudInstances && st.cloudInstances.length) {
|
// Облачные autotest-* инстансы (только если раскрыты)
|
||||||
|
if (step._showCloud && st.cloudInstances) {
|
||||||
refOpts += '<option disabled>── облако ──</option>';
|
refOpts += '<option disabled>── облако ──</option>';
|
||||||
st.cloudInstances.forEach(i => {
|
st.cloudInstances.forEach(i => {
|
||||||
if (i.explainedStatus === 'deleted') return;
|
const dn = i.displayName || '';
|
||||||
|
if (!dn.startsWith('autotest-') || i.explainedStatus === 'deleted') return;
|
||||||
const sel = i.instanceUid == ref ? 'selected' : '';
|
const sel = i.instanceUid == ref ? 'selected' : '';
|
||||||
refOpts += `<option value="${i.instanceUid}" ${sel}>☁ ${_esc(i.displayName)} — ${_esc(i.svc||'')} (${_esc(i.explainedStatus||'?')})</option>`;
|
refOpts += `<option value="${i.instanceUid}" ${sel}>☁ ${_esc(dn)} — ${_esc(i.svc||'')} (${_esc(i.explainedStatus||'?')})</option>`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
html += `<div><select id="step-${idx}-ref" style="padding:4px;font-size:12px;max-width:500px;">${refOpts}</select></div>`;
|
const btnLabel = step._showCloud ? '➖ Скрыть облако' : '📥 Из облака';
|
||||||
|
html += `<div style="display:flex;gap:4px;align-items:center;"><select id="step-${idx}-ref" style="padding:4px;font-size:12px;max-width:500px;">${refOpts}</select>`;
|
||||||
|
html += `<button class="btn btn-sm" style="font-size:10px;padding:0 6px;" onclick="toggleCloudInstances(${idx})">${btnLabel}</button></div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Параметры — свёрнутый <details>, заполняется асинхронно в loadStepParams
|
// Параметры — свёрнутый <details>, заполняется асинхронно в loadStepParams
|
||||||
@@ -242,15 +246,20 @@ function renderStepRow(idx, step) {
|
|||||||
// ── Действия ──
|
// ── Действия ──
|
||||||
|
|
||||||
function onOpChange(idx) {
|
function onOpChange(idx) {
|
||||||
// Сброс params при смене операции (несовместимы)
|
|
||||||
scenarioEditorState.steps[idx].params = {};
|
scenarioEditorState.steps[idx].params = {};
|
||||||
scenarioEditorState.steps[idx]._svcOpId = null;
|
scenarioEditorState.steps[idx]._svcOpId = null;
|
||||||
renderEditor();
|
renderEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleCloudInstances(idx) {
|
||||||
|
snapshotAllParams();
|
||||||
|
scenarioEditorState.steps[idx]._showCloud = !scenarioEditorState.steps[idx]._showCloud;
|
||||||
|
renderEditor();
|
||||||
|
}
|
||||||
|
|
||||||
function addStep() {
|
function addStep() {
|
||||||
snapshotAllParams();
|
snapshotAllParams();
|
||||||
scenarioEditorState.steps.push({ service_id: '', operation: '', output: '', instance_ref: '', instance_uid: '', params: {} });
|
scenarioEditorState.steps.push({ service_id: '', operation: '', output: '', instance_ref: '', instance_uid: '', params: {}, _showCloud: false });
|
||||||
renderEditor();
|
renderEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ async function loadScenarios(){
|
|||||||
const last=verHistory[0];
|
const last=verHistory[0];
|
||||||
const icon=last.status==='OK'?'✅':last.status==='FAIL'?'❌':last.status==='RUNNING'?'⏳':'⏱';
|
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 time=last.created_at?last.created_at.replace('T',' ').substring(0,19):'?';
|
||||||
html+=`<div style="font-size:11px;margin-top:4px;color:var(--muted);">Последний: ${icon} ${_esc(last.scenario_name)} — ${last.status} (шаг ${last.current_step}/${last.total_steps}) ${last.duration_sec!=null?last.duration_sec.toFixed(1)+'s':''} — ${time}</div>`;
|
const runningStyle = last.status==='RUNNING' ? 'background:#fef3c7;padding:2px 4px;border-radius:3px;' : '';
|
||||||
|
html+=`<div style="font-size:11px;margin-top:4px;color:var(--muted);${runningStyle}">Последний: ${icon} ${_esc(last.scenario_name)} — ${last.status} (шаг ${last.current_step}/${last.total_steps}) ${last.duration_sec!=null?last.duration_sec.toFixed(1)+'s':''} — ${time}</div>`;
|
||||||
if(last.error_log) html+=`<div style="font-size:10px;color:var(--destructive);">${_esc(last.error_log)}</div>`;
|
if(last.error_log) html+=`<div style="font-size:10px;color:var(--destructive);">${_esc(last.error_log)}</div>`;
|
||||||
}
|
}
|
||||||
body.innerHTML=html;
|
body.innerHTML=html;
|
||||||
@@ -68,7 +69,8 @@ async function runScenario(defId){
|
|||||||
if(!last||last.error) return;
|
if(!last||last.error) return;
|
||||||
const icon=last.status==='OK'?'✅':last.status==='FAIL'?'❌':last.status==='RUNNING'?'⏳':'⏱';
|
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 time=last.created_at?last.created_at.replace('T',' ').substring(0,19):'?';
|
||||||
let html=`<div style="font-size:11px;">${icon} ${_esc(last.scenario_name)} — ${last.status} (шаг ${last.current_step}/${last.total_steps}) ${last.duration_sec!=null?last.duration_sec.toFixed(1)+'s':''} — ${time}</div>`;
|
const runningBg = last.status==='RUNNING' ? 'background:#fef3c7;padding:2px 4px;border-radius:3px;' : '';
|
||||||
|
let html=`<div style="font-size:11px;${runningBg}">${icon} ${_esc(last.scenario_name)} — ${last.status} (шаг ${last.current_step}/${last.total_steps}) ${last.duration_sec!=null?last.duration_sec.toFixed(1)+'s':''} — ${time}</div>`;
|
||||||
if(last.error_log) html+=`<div style="font-size:10px;color:var(--destructive);">${_esc(last.error_log)}</div>`;
|
if(last.error_log) html+=`<div style="font-size:10px;color:var(--destructive);">${_esc(last.error_log)}</div>`;
|
||||||
body.innerHTML=html;
|
body.innerHTML=html;
|
||||||
if(last.status!=='RUNNING'){
|
if(last.status!=='RUNNING'){
|
||||||
|
|||||||
Reference in New Issue
Block a user