Files
felhom-controller/controller/internal/web/templates/settings_system.html
T
admin f8e18a9ec9 D1 Part 2: settings.html split into four pages + sidebar restructure
- settings.html (1451 lines) deleted; sections moved verbatim into
  settings_system.html (Rendszer konfiguráció, Verzió és frissítés,
  Vezérlő/Kiszolgáló újraindítása + update/restart JS),
  settings_notifications.html (Értesítések, Alkalmazás-email),
  settings_security.html (Jelszó módosítás, Földrajzi korlátozás + geo
  JS, Vészhelyzeti információk — heading + section copy accents fixed),
  storage.html (Adattárolók, NAS, migrate progress, agent view + all
  storage JS; wizard entry links now /storage/init|attach with sprite
  icons instead of emoji). The NAS + migrate sections were nested inside
  {{if .StoragePaths}} in the monolith and vanished with zero drives —
  now unconditional on /storage.
- layout.html: Tárhely main-nav item (hard-drive icon) + the
  'Beállítások' sidebar group with Rendszer / Értesítések / Biztonság és
  hozzáférés sub-links (active-state per page key); orphaned
  .sidebar-settings-link CSS deleted (grep-zero), .nav-group-label /
  .nav-links-sub added.
- Handlers wired to their own builders + templates; the legacy
  settingsData() merge deleted.
- scripts/template_id_gate.py: the §10 JS element-ID integrity gate
  (getElementById/querySelector('#…') must resolve in the SAME template;
  JS-created + template-parameterized IDs handled; layout modal IDs
  allowlisted). Red-proven: a storage function planted in the
  notifications template failed the gate with 'static #migrate-progress
  not defined'.
- Tests: per-page section markers + cross-leak assertions, h3 section
  inventory (all 11 old headings accounted for; typo rename asserted).
2026-07-02 19:07:32 +02:00

275 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{define "settings_system"}}
{{template "layout_start" .}}
<div class="page-header">
<h2>Beállítások — Rendszer</h2>
</div>
<!-- Section A: System Configuration (read-only) -->
<div class="settings-card">
<h3>Rendszer konfiguráció</h3>
<p class="settings-card-desc">Az üzemeltető által beállított értékek. Módosításhoz kérd az üzemeltetőt.</p>
<div class="settings-grid">
<div class="settings-row">
<span class="settings-label">Ügyfél azonosító</span>
<span class="settings-value mono">{{.CustomerID}}</span>
</div>
<div class="settings-row">
<span class="settings-label">Ügyfél neve</span>
<span class="settings-value">{{.CustomerName}}</span>
</div>
<div class="settings-row">
<span class="settings-label">Domain</span>
<span class="settings-value mono">{{.CustomerDomain}}</span>
</div>
{{if .GitRepoURL}}
<div class="settings-row">
<span class="settings-label">Alkalmazás sablon forrás</span>
<span class="settings-value mono settings-value-truncate">{{.GitRepoURL}}</span>
</div>
{{end}}
<div class="settings-row">
<span class="settings-label">Sablon szinkronizálás</span>
<span class="settings-value mono">{{.GitSyncInterval}}</span>
</div>
<div class="settings-row">
<span class="settings-label">Biztonsági mentés</span>
<span class="settings-value">{{if .BackupEnabled}}<span class="state-text-run"><svg class="ico ico-sm"><use href="#i-check"/></svg> Aktív</span>{{else}}<span class="state-text-neutral">Inaktív</span>{{end}}</span>
</div>
{{if .BackupEnabled}}
<div class="settings-row">
<span class="settings-label">Mentés ütemezés</span>
<span class="settings-value mono">{{.DBDumpSchedule}} / {{.ResticSchedule}}</span>
</div>
{{end}}
<div class="settings-row">
<span class="settings-label">Monitoring</span>
<span class="settings-value">{{if .MonitoringEnabled}}<span class="state-text-run"><svg class="ico ico-sm"><use href="#i-check"/></svg> Aktív</span>{{else}}<span class="state-text-neutral">Inaktív</span>{{end}}</span>
</div>
{{if .MonitoringEnabled}}
<div class="settings-row">
<span class="settings-label">Healthchecks URL</span>
<span class="settings-value mono settings-value-truncate">{{if .HealthchecksBase}}{{.HealthchecksBase}}{{else}}{{end}}</span>
</div>
{{end}}
<div class="settings-row">
<span class="settings-label">Hub jelentés</span>
<span class="settings-value">{{if .HubEnabled}}<span class="state-text-run"><svg class="ico ico-sm"><use href="#i-check"/></svg> Aktív</span>{{else}}{{end}}</span>
</div>
</div>
</div>
<!-- Section: Version & Update -->
<div class="settings-card">
<h3>Verzió és frissítés</h3>
<div class="settings-grid">
<div class="settings-row">
<span class="settings-label">Jelenlegi verzió</span>
<span class="settings-value mono">{{.Version}}</span>
</div>
{{if .SelfUpdateEnabled}}
{{if .LatestVersion}}
<div class="settings-row">
<span class="settings-label">Legújabb verzió</span>
<span class="settings-value mono">
{{.LatestVersion}}
{{if .UpdateAvailable}}
<span class="state-text-run" style="margin-left:0.5em;">● Frissítés elérhető</span>
{{else}}
<span style="margin-left:0.5em; color:var(--text-3);">— naprakész</span>
{{end}}
</span>
</div>
{{end}}
{{if .LastCheckTime}}
<div class="settings-row">
<span class="settings-label">Utolsó ellenőrzés</span>
<span class="settings-value mono">{{.LastCheckTime}}</span>
</div>
{{end}}
{{if .LastCheckError}}
<div class="settings-row">
<span class="settings-label">Hiba</span>
<span class="settings-value state-text-crit">{{.LastCheckError}}</span>
</div>
{{end}}
<div class="settings-row">
<span class="settings-label">Automatikus frissítés</span>
<span class="settings-value">
{{if .AutoUpdateEnabled}}<span class="state-text-run"><svg class="ico ico-sm"><use href="#i-check"/></svg> Aktív</span> <span class="mono">({{.AutoUpdateTime}})</span>{{else}}{{end}}
</span>
</div>
{{if .ControllerFloor}}
<div class="settings-row">
<span class="settings-label">Minimális verzió (üzemeltető)</span>
<span class="settings-value mono">
{{.ControllerFloor}}
<span style="margin-left:0.5em; color:#888;">— a rendszer automatikusan erre a verzióra frissít, ha régebbi</span>
</span>
</div>
{{end}}
{{if .UpdateRunning}}
<div class="settings-row">
<span class="settings-label">Állapot</span>
<span class="settings-value state-text-progress" id="auto-update-status"><svg class="ico ico-sm ico-spin"><use href="#i-rotate-cw"/></svg> Frissítés folyamatban — a vezérlő hamarosan újraindul…</span>
</div>
{{end}}
{{with .LastUpdateState}}
<div class="settings-row">
<span class="settings-label">Utolsó frissítés</span>
<span class="settings-value">
{{if eq .Status "success"}}<span class="state-text-run"><svg class="ico ico-sm"><use href="#i-check"/></svg> Sikeres</span> ({{.PreviousVersion}} → {{.TargetVersion}})
{{else if eq .Status "failed"}}<span class="state-text-crit"><svg class="ico ico-sm"><use href="#i-x"/></svg> Sikertelen</span> — {{.Error}}
{{else if eq .Status "pending"}}<span class="state-text-progress"><svg class="ico ico-sm ico-spin"><use href="#i-rotate-cw"/></svg> Folyamatban</span>
{{end}}
</span>
</div>
{{end}}
<div class="settings-row" style="padding-top: 0.5em;">
<span class="settings-label"></span>
<span class="settings-value">
<button class="btn btn-secondary btn-sm" id="btn-check-update" onclick="checkUpdate()">Frissítés keresése</button>
{{if .UpdateAvailable}}
<button class="btn btn-primary btn-sm" id="btn-trigger-update" onclick="triggerUpdate()" style="margin-left:0.5em;">Frissítés telepítése</button>
{{end}}
<span id="update-status-msg" style="margin-left:0.5em; display:none;"></span>
</span>
</div>
{{end}}
</div>
</div>
<script>
function checkUpdate() {
var btn = document.getElementById('btn-check-update');
var msg = document.getElementById('update-status-msg');
btn.disabled = true;
btn.textContent = 'Ellenőrzés...';
msg.style.display = 'none';
fetch('/api/selfupdate/check', {method:'POST', headers: csrfHeaders()})
.then(function(r) { return r.json(); })
.then(function(data) {
if (data.ok) {
location.reload();
} else {
msg.textContent = data.error || 'Hiba történt';
msg.style.display = 'inline';
btn.disabled = false;
btn.textContent = 'Frissítés keresése';
}
})
.catch(function() {
msg.textContent = 'Kapcsolódási hiba';
msg.style.display = 'inline';
btn.disabled = false;
btn.textContent = 'Frissítés keresése';
});
}
function triggerUpdate() {
if (!confirm('Biztosan frissíti a controllert?\n\nA folyamat alatt a vezérlőpult rövid időre elérhetetlenné válik.')) return;
var btn = document.getElementById('btn-trigger-update');
var checkBtn = document.getElementById('btn-check-update');
var msg = document.getElementById('update-status-msg');
btn.disabled = true;
btn.textContent = 'Frissítés...';
if (checkBtn) checkBtn.disabled = true;
msg.textContent = 'Frissítés folyamatban...';
msg.style.display = 'inline';
fetch('/api/selfupdate/update', {method:'POST', headers: csrfHeaders()})
.then(function(r) { return r.json(); })
.then(function(data) {
if (data.ok) {
msg.textContent = 'Újraindulás...';
pollUntilBack();
} else {
msg.textContent = data.error || 'Hiba történt';
btn.disabled = false;
btn.textContent = 'Frissítés telepítése';
if (checkBtn) checkBtn.disabled = false;
}
})
.catch(function() {
msg.textContent = 'Kapcsolódási hiba';
pollUntilBack();
});
}
function pollUntilBack() {
var iv = setInterval(function() {
fetch('/api/health')
.then(function(r) {
if (r.ok) {
clearInterval(iv);
location.reload();
}
})
.catch(function() {});
}, 3000);
}
// If an update is already in flight when the page loads (e.g. a floor-driven AUTO-update kicked off by
// the hub, not a button click), surface the same restart-poll panel so the page recovers itself.
{{if .UpdateRunning}}
pollUntilBack();
{{end}}
</script>
<!-- Section: Controller restart (self-serve) — always available (not gated on RetrievalPassword) -->
<div class="settings-card">
<h3>Vezérlő újraindítása</h3>
<p class="settings-card-desc">
Ha a vezérlő hibásan működik, itt biztonságosan újraindíthatja — nem kell az egész szervert újraindítani.
Az alkalmazásai futnak tovább; csak a vezérlő indul újra (néhány másodperc).
</p>
<div id="restart-status"></div>
<button type="button" class="btn btn-outline" id="btn-restart-controller" onclick="restartController()">Vezérlő újraindítása</button>
</div>
<!-- Section: Full server (guest) restart — a deliberate maintenance affordance, sibling to the controller restart -->
<div class="settings-card">
<h3>Kiszolgáló ú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álja, ha a teljes rendszer újraindítására van szükség — egyébként a fenti „Vezérlő újraindítása” elegendő.
</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>
</div>
<script>
function restartController() {
if (!confirm('Biztosan újraindítja a vezérlőt? A művelet néhány másodpercig tart, és a felület rövid időre elérhetetlen lesz.')) return;
var btn = document.getElementById('btn-restart-controller');
var status = document.getElementById('restart-status');
btn.disabled = true;
status.innerHTML = '<div class="alert alert-info">Újraindítás folyamatban… újracsatlakozás…</div>';
fetch('/api/selfrestart', { method: 'POST', headers: csrfHeaders() })
.then(function(){ pollRestart(0); })
.catch(function(){ pollRestart(0); }); // connection may drop as the process exits — poll regardless
}
function restartServer() {
if (!confirm('Biztosan újraindítja a kiszolgálót? Az alkalmazások és a vezérlőpult kb. 30 másodpercre elérhetetlenné válnak.')) return;
var btn = document.getElementById('btn-restart-server');
var status = document.getElementById('server-restart-status');
if (btn) btn.disabled = true;
if (status) status.innerHTML = '<div class="alert alert-info">Újraindítás folyamatban… a vezérlőpult néhány másodperc múlva újratölt.</div>';
fetch('/api/server/reboot', { method: 'POST', headers: csrfHeaders() })
.then(function(){ pollRestart(0); })
.catch(function(){ pollRestart(0); }); // the guest reboot drops the connection — poll regardless
}
function pollRestart(attempt) {
if (attempt > 60) { // ~2 min cap — never leave the user on a dead page silently
document.getElementById('restart-status').innerHTML =
'<div class="alert alert-error">Az újraindítás a vártnál tovább tart. Töltse újra az oldalt kézzel.</div>';
return;
}
setTimeout(function(){
fetch('/', { method: 'GET', cache: 'no-store' })
.then(function(r){ if (r.ok) { window.location.reload(); } else { pollRestart(attempt + 1); } })
.catch(function(){ pollRestart(attempt + 1); });
}, 2000);
}
</script>
{{template "layout_end" .}}
{{end}}