updated startup monitoring

This commit is contained in:
2026-02-14 18:57:20 +01:00
parent c3b80cffdc
commit 0be798af5d
4 changed files with 187 additions and 14 deletions
+163 -9
View File
@@ -426,6 +426,27 @@ const deployTmpl = `
</div>
{{end}}
</form>
<div id="deploy-progress" class="deploy-progress" style="display:none">
<h3>Telepítés folyamatban...</h3>
<div class="deploy-steps">
<div class="deploy-step active" id="step-config">
<span class="step-icon">&#9203;</span>
<span class="step-text">Konfiguráció mentése...</span>
</div>
<div class="deploy-step" id="step-containers">
<span class="step-icon">&#9203;</span>
<span class="step-text">Konténer(ek) indítása...</span>
</div>
<div class="deploy-step" id="step-health">
<span class="step-icon">&#9203;</span>
<span class="step-text">Alkalmazás inicializálása...</span>
</div>
</div>
<div id="deploy-warning" class="alert alert-warning" style="display:none"></div>
<div id="deploy-result" style="display:none"></div>
<p class="deploy-elapsed" id="deploy-elapsed"></p>
</div>
</div>
<script>
@@ -466,7 +487,6 @@ document.getElementById('deploy-form').addEventListener('submit', async function
}
const btn = e.target.querySelector('[type=submit]');
const origText = btn.textContent;
btn.disabled = true;
btn.textContent = 'Telepítés folyamatban...';
@@ -482,28 +502,114 @@ document.getElementById('deploy-form').addEventListener('submit', async function
}
});
var stackName = '{{.Stack.Name}}';
var progressEl = document.getElementById('deploy-progress');
var formEl = document.getElementById('deploy-form');
var stepConfig = document.getElementById('step-config');
var stepContainers = document.getElementById('step-containers');
var stepHealth = document.getElementById('step-health');
var warningEl = document.getElementById('deploy-warning');
var resultEl = document.getElementById('deploy-result');
var elapsedEl = document.getElementById('deploy-elapsed');
function setStep(el, status, text) {
el.className = 'deploy-step ' + status;
if (text) el.querySelector('.step-text').textContent = text;
var icon = el.querySelector('.step-icon');
if (status === 'done') icon.textContent = '\u2705';
else if (status === 'error') icon.textContent = '\u274C';
else if (status === 'warn') icon.textContent = '\u26A0\uFE0F';
else if (status === 'active') icon.textContent = '\u23F3';
}
// Phase 1: Deploy request
try {
const resp = await fetch('/api/stacks/{{.Stack.Name}}/deploy', {
var resp = await fetch('/api/stacks/' + stackName + '/deploy', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({values: values})
});
const data = await resp.json();
var data = await resp.json();
if (!data.ok) {
alert('Hiba: ' + data.error);
btn.textContent = origText;
btn.textContent = 'Telepítés indítása';
btn.disabled = false;
return;
}
// Deploy API returned success — switch to progress view
formEl.style.display = 'none';
progressEl.style.display = 'block';
setStep(stepConfig, 'done', 'Konfiguráció mentve');
setStep(stepContainers, 'active', 'Konténer(ek) indítása...');
if (data.data && data.data.warning) {
alert('Sikeres telepítés!\n\nFigyelmeztetés: ' + data.data.warning);
} else {
alert('Sikeres telepítés!');
warningEl.textContent = data.data.warning;
warningEl.style.display = 'block';
}
window.location.href = '/stacks';
// Phase 2: Poll stack status
var startTime = Date.now();
var pollTimeout = 120000;
var pollTimer = setInterval(async function() {
var elapsed = Math.round((Date.now() - startTime) / 1000);
elapsedEl.textContent = elapsed + ' másodperce...';
if (Date.now() - startTime > pollTimeout) {
clearInterval(pollTimer);
setStep(stepHealth, 'warn', 'Időtúllépés — az alkalmazás még indulhat');
resultEl.innerHTML = '<div class="alert alert-warning" style="margin-top:1rem">' +
'A telepítés időtúllépésbe futott. Az alkalmazás még indulhat.' +
'</div><a href="/stacks" class="btn btn-primary" style="margin-top:.75rem">Alkalmazások megtekintése</a>';
resultEl.style.display = 'block';
return;
}
try {
var sr = await fetch('/api/stacks/' + stackName);
var sd = await sr.json();
if (!sd.ok || !sd.data) return;
var state = sd.data.state;
if (state === 'running') {
clearInterval(pollTimer);
setStep(stepContainers, 'done', 'Konténerek elindultak');
setStep(stepHealth, 'done', 'Alkalmazás kész!');
progressEl.querySelector('h3').textContent = 'Telepítés sikeres!';
resultEl.innerHTML = '<div class="alert alert-info" style="margin-top:1rem">' +
'Az alkalmazás fut. Átirányítás 3 másodperc múlva...' +
'</div>';
resultEl.style.display = 'block';
setTimeout(function() { window.location.href = '/stacks'; }, 3000);
} else if (state === 'starting') {
setStep(stepContainers, 'done', 'Konténerek elindultak');
setStep(stepHealth, 'active', 'Alkalmazás inicializálása...');
} else if (state === 'unhealthy') {
clearInterval(pollTimer);
setStep(stepContainers, 'done', 'Konténerek elindultak');
setStep(stepHealth, 'warn', 'Állapotjelző: nem egészséges');
resultEl.innerHTML = '<div class="alert alert-warning" style="margin-top:1rem">' +
'Az alkalmazás elindult, de az állapotjelző nem egészséges. ' +
'Ez normális lehet az első percekben.' +
'</div><a href="/stacks" class="btn btn-primary" style="margin-top:.75rem">Alkalmazások megtekintése</a>';
resultEl.style.display = 'block';
} else if (state === 'exited' || state === 'stopped') {
clearInterval(pollTimer);
setStep(stepContainers, 'error', 'A konténer leállt');
setStep(stepHealth, 'error');
progressEl.querySelector('h3').textContent = 'Telepítés sikertelen';
resultEl.innerHTML = '<div class="alert alert-error" style="margin-top:1rem">' +
'A konténer leállt. Ellenőrizze a naplókat.' +
'</div><a href="/stacks/' + stackName + '/logs" class="btn btn-outline" style="margin-top:.75rem">Naplók megtekintése</a>' +
' <a href="/stacks" class="btn btn-primary" style="margin-top:.75rem">Alkalmazások</a>';
resultEl.style.display = 'block';
}
} catch(pollErr) {}
}, 3000);
} catch (err) {
alert('Hálózati hiba: ' + err.message);
btn.textContent = origText;
btn.textContent = 'Telepítés indítása';
btn.disabled = false;
}
});
@@ -1187,6 +1293,54 @@ select.form-control option { background: var(--bg-secondary); color: var(--text-
border-top: 1px solid var(--border-color);
}
/* Deploy progress */
.deploy-progress {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--radius);
padding: 1.5rem;
}
.deploy-progress h3 {
margin-bottom: 0.5rem;
}
.deploy-steps {
margin: 1rem 0;
}
.deploy-step {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.5rem 0;
font-size: .95rem;
color: var(--text-muted);
}
.deploy-step.active {
color: var(--text-primary);
}
.deploy-step.done {
color: var(--text-primary);
}
.deploy-step.done .step-icon {
color: var(--green);
}
.deploy-step.error .step-icon {
color: var(--red);
}
.deploy-step.warn .step-icon {
color: var(--yellow);
}
.step-icon {
font-size: 1.1rem;
width: 1.5rem;
text-align: center;
flex-shrink: 0;
}
.deploy-elapsed {
color: var(--text-muted);
font-size: .85rem;
margin-top: 0.5rem;
}
/* Toggle switch */
.toggle { cursor: pointer; display: flex; align-items: center; gap: .5rem; }
.toggle input[type="checkbox"] { accent-color: var(--accent-blue); }