v0.310.0: „A gép kikapcsolása" — the household turns the whole machine off (R-998); honest restart text (R-999)
gates / gates (push) Successful in 48s

POST /api/server/poweroff (dashboard login, POST only, the typed word KIKAPCSOLÁS / TURN OFF)
→ agent POST /host/poweroff (MinAgent 0.155.0; hidden for an older agent). The controller refuses
during its own backup/restore/app update; the agent's reasons are shown as household sentences.
„Kiszolgáló újraindítása" becomes „A Felhom újraindítása" and says it restarts the Felhom part;
/api/server/reboot is POST only (R-983). Tests red-proofed; parity fixtures regenerated on purpose.
This commit is contained in:
2026-10-13 20:17:30 +02:00
parent 1b2f74c52f
commit 201f936e9a
20 changed files with 743 additions and 41 deletions
@@ -333,10 +333,15 @@ function openDialog(opts){
root.innerHTML='<div class="confirm-overlay" onclick="if(event.target===this)document.getElementById(\'dialog-cancel\').click()"><div class="confirm-box">'
+'<h3>'+escText(opts.title||'Megerősítés')+'</h3>'
+'<p style="white-space:pre-line">'+escText(opts.message||'')+'</p>'
+'<div class="form-actions"><button id="dialog-go" class="btn btn-primary">'+escText(opts.confirmLabel||'Megerősítés')+'</button>'
+(opts.typeToConfirm?'<div class="confirm-input"><label>Megerősítéshez írd be: <strong class="mono">'+escText(opts.typeToConfirm)+'</strong></label>'
+'<input type="text" id="dialog-type" class="form-control" autocomplete="off" placeholder="'+escText(opts.typeToConfirm)+'"></div>':'')
+'<div class="form-actions"><button id="dialog-go" class="btn '+(opts.typeToConfirm?'btn-danger-outline':'btn-primary')+'"'+(opts.typeToConfirm?' disabled':'')+'>'+escText(opts.confirmLabel||'Megerősítés')+'</button>'
+'<button type="button" class="btn btn-outline" id="dialog-cancel">Mégsem</button></div>'
+'</div></div>';
document.getElementById('dialog-go').onclick=function(){ closeDialog(); if(opts.onConfirm) opts.onConfirm(); };
var typed=document.getElementById('dialog-type');
if(typed){ typed.oninput=function(){ document.getElementById('dialog-go').disabled=(this.value.trim().toUpperCase()!==opts.typeToConfirm.toUpperCase()); }; }
document.getElementById('dialog-go').onclick=function(){ var v=typed?typed.value:''; closeDialog(); if(opts.onConfirm) opts.onConfirm(v); };
document.getElementById('dialog-cancel').onclick=function(){ closeDialog(); if(opts.onCancel) opts.onCancel(); };
}
@@ -479,12 +484,23 @@ function pollUntilBack() {
<div class="settings-card">
<h3>Kiszolgáló újraindítása</h3>
<h3>A Felhom újraindítása</h3>
<p class="settings-card-desc">
Az egész kiszolgáló (szerver) újraindítása. Minden alkalmazás rövid időre leáll, és a vezérlőpult kb. 30 másodpercig nem elérhető. Akkor használd, ha a teljes rendszer újraindítására van szükség — egyébként a fenti „Vezérlő újraindítása” elegendő.
Újraindítja a Felhom részt a gépen: a vezérlőpultot és az összes alkalmazást. A gép maga bekapcsolva marad. Kb. 30 másodpercig semmi nem érhető el, utána minden magától visszajön. Ha csak a vezérlőpult akad, a fenti „Vezérlő újraindítása” elég.
</p>
<div id="server-restart-status"></div>
<button type="button" class="btn btn-outline" id="btn-restart-server" onclick="restartServer()">Kiszolgáló újraindítása</button>
<button type="button" class="btn btn-outline" id="btn-restart-server" onclick="restartServer()">A Felhom újraindítása</button>
</div>
<div class="settings-card" id="poweroff-card">
<h3>A gép kikapcsolása</h3>
<p class="settings-card-desc">A gép teljesen kikapcsol. Az alkalmazásaid és a mentések leállnak.</p>
<p class="settings-card-desc"><strong>Újra bekapcsolni csak otthon lehet: nyomd meg a gép bekapcsológombját.</strong></p>
<div id="poweroff-status"></div>
<button type="button" class="btn btn-danger-outline" id="btn-poweroff" onclick="powerOffMachine()">A gép kikapcsolása</button>
</div>
<script>
@@ -503,8 +519,8 @@ function doRestartController() {
.catch(function(){ pollRestart(0); });
}
function restartServer() {
openDialog({title:'Kiszolgáló újraindítása', confirmLabel:'Újraindítás',
message:'Biztosan újraindítod a kiszolgálót? Az alkalmazások és a vezérlőpult kb. 30 másodpercre elérhetetlenné válnak.',
openDialog({title:'A Felhom újraindítása', confirmLabel:'Újraindítás',
message:'Biztosan újraindítod a Felhomot? Az alkalmazások és a vezérlőpult kb. 30 másodpercre elérhetetlenné válnak. A gép bekapcsolva marad.',
onConfirm:doRestartServer});
}
function doRestartServer() {
@@ -516,6 +532,32 @@ function doRestartServer() {
.then(function(){ pollRestart(0); })
.catch(function(){ pollRestart(0); });
}
function powerOffMachine() {
var word = 'KIKAPCSOLÁS';
openDialog({title:'A gép kikapcsolása', confirmLabel:'Kikapcsolás',
message:'Biztosan kikapcsolod a gépet? A Felhom leáll, és a gép kikapcsol. Távolról senki nem tudja újra bekapcsolni: csak otthon, a gép bekapcsológombjával.', typeToConfirm: word,
onConfirm:doPowerOffMachine});
}
function doPowerOffMachine(typed) {
var btn = document.getElementById('btn-poweroff');
var status = document.getElementById('poweroff-status');
if (btn) btn.disabled = true;
var h = csrfHeaders(); h['Content-Type'] = 'application/json';
fetch('/api/server/poweroff', { method: 'POST', headers: h, body: JSON.stringify({confirm: typed}) })
.then(function(r){ return r.json().catch(function(){ return {ok:false}; }); })
.then(function(d){
if (d && d.ok) {
status.innerHTML = '<div class="alert alert-info">' + escText('A gép kikapcsol. Néhány perc múlva teljesen leáll, és ez az oldal nem válaszol többé. Újra bekapcsolni: nyomd meg a gép bekapcsológombját.') + '</div>';
return;
}
status.innerHTML = '<div class="alert alert-error">' + escText((d && d.error) || 'Hiba történt') + '</div>';
if (btn) btn.disabled = false;
})
.catch(function(){
status.innerHTML = '<div class="alert alert-error">' + escText('Kapcsolódási hiba') + '</div>';
if (btn) btn.disabled = false;
});
}
function pollRestart(attempt) {
if (attempt > 60) {
document.getElementById('restart-status').innerHTML =