v1.1.1: scrollable services + dynamic CREATE for any service

This commit is contained in:
2026-07-28 11:24:51 +04:00
parent 0b810fdee1
commit 12e3d12e09
3 changed files with 21 additions and 19 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ from routes.api import bp as api_bp
from routes.api_test import bp as api_test_bp from routes.api_test import bp as api_test_bp
# Версия — меняется при КАЖДОМ изменении кода. Показывается в топбаре UI. # Версия — меняется при КАЖДОМ изменении кода. Показывается в топбаре UI.
VERSION = "1.1.0" VERSION = "1.1.1"
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")
+19 -17
View File
@@ -26,28 +26,21 @@
* showStages() — отрисовка этапов выполнения операции (⏳/✅/❌) * showStages() — отрисовка этапов выполнения операции (⏳/✅/❌)
*/ */
let svcInstances=[], selectedInst=null, selectedOp=null, pollTimer=null; let svcInstances=[], selectedInst=null, selectedOp=null, pollTimer=null;
let currentSvcId=1; // динамический — загружается из /api/services let currentSvcId=1; // динамический — обновляется при selectService()
const AUTOTEST_PREFIX='autotest-'; const AUTOTEST_PREFIX='autotest-';
// Загрузка списка сервисов при старте // Первый сервис из списка (рендерится Jinja2)
(async function initServices(){ selectService(currentSvcId);
try{
const r=await fetch('/api/services');
const svcList=await r.json();
if(!svcList||!svcList.length) return;
// Сохраняем глобально для UI переключения
window._svcList=svcList;
currentSvcId=svcList[0].svcId; // первый сервис по умолчанию
selectService(currentSvcId);
}catch(e){
selectService(1); // fallback — Болванка
}
})();
async function selectService(svcId){ async function selectService(svcId){
currentSvcId=svcId;
selectedInst=null; selectedOp=null; stopPoll(); selectedInst=null; selectedOp=null; stopPoll();
document.getElementById('params-card').style.display='none'; document.getElementById('params-card').style.display='none';
document.getElementById('stages-box').style.display='none'; document.getElementById('stages-box').style.display='none';
// Подсветить активный сервис в боковой панели
document.querySelectorAll('.svc-item').forEach(e=>e.classList.remove('active'));
const svcEl=document.querySelector(`.svc-item[onclick*="${svcId}"]`);
if(svcEl) svcEl.classList.add('active');
const r=await fetch('/api/operations/'+svcId); const r=await fetch('/api/operations/'+svcId);
const d=await r.json(); const d=await r.json();
@@ -97,11 +90,20 @@ function opClass(opName){
return ''; return '';
} }
function startCreate(){ async function startCreate(){
selectedInst=null; stopPoll(); selectedInst=null; stopPoll();
document.querySelectorAll('[data-iuid]').forEach(e=>e.classList.remove('active')); document.querySelectorAll('[data-iuid]').forEach(e=>e.classList.remove('active'));
document.querySelectorAll('.inst-ops').forEach(e=>e.classList.remove('open')); document.querySelectorAll('.inst-ops').forEach(e=>e.classList.remove('open'));
showParams(18,'create'); // Найти svcOperationId для create у текущего сервиса
try{
const r=await fetch('/api/operations/'+currentSvcId);
const d=await r.json();
const createOp=d.operations.find(o=>o.operation==='create');
const opId=createOp?createOp.svcOperationId:18; // fallback — Болванка
showParams(opId,'create');
}catch(e){
showParams(18,'create'); // fallback
}
} }
function makeCreateDisplayName(){ function makeCreateDisplayName(){
+1 -1
View File
@@ -9,7 +9,7 @@
.topbar { max-width:1200px; margin:0 auto; padding:10px 16px 0; display:flex; align-items:center; gap:12px; } .topbar { max-width:1200px; margin:0 auto; padding:10px 16px 0; display:flex; align-items:center; gap:12px; }
.layout { display:flex; gap:12px; max-width:1200px; margin:8px auto; padding:0 16px; } .layout { display:flex; gap:12px; max-width:1200px; margin:8px auto; padding:0 16px; }
.col-infra { width:280px; flex-shrink:0; } .col-infra { width:280px; flex-shrink:0; }
.col-svc { width:240px; flex-shrink:0; } .col-svc { width:240px; flex-shrink:0; max-height:calc(100vh - 50px); overflow-y:auto; }
.col-main { flex:1; min-width:0; } .col-main { flex:1; min-width:0; }
.svc-item { cursor:pointer; padding:4px 8px; font-size:12px; border-radius:4px; } .svc-item { cursor:pointer; padding:4px 8px; font-size:12px; border-radius:4px; }
.svc-item:hover, .svc-item.active { background:var(--brand-grey-light); } .svc-item:hover, .svc-item.active { background:var(--brand-grey-light); }