diff --git a/site/app.py b/site/app.py index 6201cf1..21c2075 100644 --- a/site/app.py +++ b/site/app.py @@ -18,7 +18,7 @@ from routes.api import bp as api_bp from routes.api_test import bp as api_test_bp # Версия — меняется при КАЖДОМ изменении кода. Показывается в топбаре UI. -VERSION = "1.1.26" +VERSION = "1.1.27" 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/static/app.js b/site/static/app.js index 97b4010..2afaf85 100644 --- a/site/static/app.js +++ b/site/static/app.js @@ -29,6 +29,7 @@ let svcInstances=[], selectedInst=null, selectedOp=null, pollTimer=null; let currentSvcId=1; // динамический — обновляется при selectService() let currentSvcName=''; // имя текущего сервиса (колонка «тип инстанса») let currentSvcShort=''; // краткое имя (redis, postgres) для displayName +let busy=false; // блокировка: запрет операций пока идёт другая const AUTOTEST_PREFIX='autotest-'; // Первый сервис из списка (рендерится Jinja2) @@ -73,6 +74,7 @@ async function toggleInstance(iuid){ document.getElementById('params-area').style.display='none'; const opsEl=document.getElementById('ops-'+iuid); + if(busy){opsEl.innerHTML='⏳ операция выполняется...';opsEl.classList.add('open');return;} if(opsEl.classList.contains('open')){opsEl.classList.remove('open');return;} document.querySelectorAll('.inst-ops').forEach(e=>e.classList.remove('open')); @@ -96,6 +98,7 @@ function opClass(opName){ } async function startCreate(){ + if(busy) return; selectedInst=null; stopPoll(); document.querySelectorAll('[data-iuid]').forEach(e=>e.classList.remove('active')); document.querySelectorAll('.inst-ops').forEach(e=>e.classList.remove('open')); @@ -117,6 +120,7 @@ function makeCreateDisplayName(){ } function runOp(opName,opId){ + if(busy) return; stopPoll(); selectedOp={opId,opName,svcId:currentSvcId}; if(opName==='modify'){ @@ -274,6 +278,7 @@ function validateJson(el,quiet){ } function setFinishedState(statusText, statusClass, statusError, statusDuration, instanceName){ + busy=false; const btn=document.getElementById('btn-test'); btn.disabled=false; btn.textContent='Готово'; @@ -293,6 +298,7 @@ function setRunningState(opName, displayName){ } async function executeOp(params){ + busy=true; stopPoll(); const isCreate=selectedOp?.opName==='create'; const displayNameInput=document.getElementById('param-displayname');