D0 Part 4: settings visual pass + remaining pages; grep gate zero
- settings.html: Aktív/Inaktív rows -> run-blue check / neutral gray (Inaktív no longer red), update states -> run/crit/progress with sprite check/x/spinner, pencil + cancel buttons -> icons, storage badges -> tags, host-disk bar + JS drive capBar -> meters (usageColorClass -> nominal/warn/crit), state-text-* consumers on the new suffixes incl. JS-built class names. - debug.html, app_info.html, storage_init/attach.html, logs.html: emoji -> sprite icons or plain text in templates AND JS strings. - catchall.html (standalone, no sprite): v2 token sweep of its inline style, status emoji -> inline SVGs; a stopped app renders neutral, not red. - login.html: two-tone H1 (last word blue-bright). - setup_hub_versions.html: stale var(--border,#30363d) fallback -> v2. - Test Group F grep gate: all 34 banned patterns at ZERO across internal/web + internal/setup; Scenario E test now asserts the '--bg-0: #0A1220' token literal.
This commit is contained in:
@@ -52,7 +52,7 @@ func TestStyleCSSAccessor(t *testing.T) {
|
||||
if !strings.Contains(css, "@font-face") || !strings.Contains(css, "/static/fonts/pjs-latin.woff2") {
|
||||
t.Error("StyleCSS() missing vendored @font-face rules")
|
||||
}
|
||||
if strings.Contains(css, "fonts.googleapis.com") {
|
||||
if strings.Contains(css, "fonts.googleapis"+".com") {
|
||||
t.Error("StyleCSS() still references the Google Fonts CDN")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
{{if .MissingStorageLabel}}
|
||||
<div class="alert alert-warning" style="margin-top:1rem">
|
||||
<strong>⚠ Hiányzó tárhely: {{.MissingStorageLabel}}</strong><br>
|
||||
<strong><svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg> Hiányzó tárhely: {{.MissingStorageLabel}}</strong><br>
|
||||
Ennek az alkalmazásnak az adattárolója jelenleg nem elérhető, ezért le van állítva. Csatlakoztasd újra a meghajtót, vagy helyezd át az adatokat egy másik tárhelyre.
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -91,7 +91,7 @@ function appMigWatch(){
|
||||
var job=d.data&&d.data.job;
|
||||
if(!job){ if(panel) panel.textContent='Nincs folyamatban áthelyezés.'; return; }
|
||||
if(panel) panel.innerHTML=appMigRender(job);
|
||||
if(job.phase==='done'){ if(panel) panel.innerHTML+='<br><strong>Kész ✓</strong>'; setTimeout(function(){location.reload();},1500); return; }
|
||||
if(job.phase==='done'){ if(panel) panel.innerHTML+='<br><strong>Kész</strong>'; setTimeout(function(){location.reload();},1500); return; }
|
||||
if(job.phase==='aborted'){ if(panel) panel.innerHTML+='<br><strong style="color:var(--danger,#c0392b)">Megszakadt: '+(job.error||'')+'</strong><br>A régi adatok érintetlenek.'; return; }
|
||||
setTimeout(tick,1500);
|
||||
}).catch(function(){ setTimeout(tick,2000); });
|
||||
@@ -208,7 +208,7 @@ function icCopyPw(btn) {
|
||||
if (!val) return;
|
||||
navigator.clipboard.writeText(val).then(function () {
|
||||
var orig = btn.textContent;
|
||||
btn.textContent = 'Másolva ✓';
|
||||
btn.textContent = 'Másolva';
|
||||
setTimeout(function () { btn.textContent = orig; }, 1500);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
{{if .Tier1LastRun}}
|
||||
<span class="layer-last">Utolsó: {{.Tier1LastRun}}
|
||||
{{if eq .Tier1LastStatus "ok"}}<span class="text-ok"><svg class="ico ico-sm"><use href="#i-check"/></svg></span>
|
||||
{{else if eq .Tier1LastStatus "error"}}<span class="text-error">✗</span>{{end}}
|
||||
{{else if eq .Tier1LastStatus "error"}}<span class="text-error"><svg class="ico ico-sm"><use href="#i-x"/></svg></span>{{end}}
|
||||
</span>
|
||||
{{end}}
|
||||
<span class="tier-contents">{{.BackupContents}}</span>
|
||||
|
||||
@@ -8,28 +8,28 @@
|
||||
<link rel="icon" type="image/svg+xml" href="{{.ControllerURL}}/static/favicon.svg">
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{background:#0d1117;color:#e6edf3;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;min-height:100vh;display:flex;align-items:center;justify-content:center}
|
||||
body{background:#0A1220;color:#EDF2F9;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;min-height:100vh;display:flex;align-items:center;justify-content:center}
|
||||
.container{text-align:center;max-width:480px;padding:2rem}
|
||||
.logo{width:80px;height:auto;margin-bottom:1.5rem;opacity:.85}
|
||||
.app-name{font-size:1.5rem;font-weight:600;margin-bottom:.5rem}
|
||||
.status-text{color:#8b949e;font-size:1.1rem;margin-bottom:2rem;line-height:1.5}
|
||||
.status-text{color:#94A6BF;font-size:1.1rem;margin-bottom:2rem;line-height:1.5}
|
||||
.status-icon{font-size:2.5rem;margin-bottom:1rem}
|
||||
.status-stopped .status-icon{color:#da3633}
|
||||
.status-not_deployed .status-icon{color:#8b949e}
|
||||
.status-unknown .status-icon{color:#8b949e}
|
||||
.btn{display:inline-block;padding:.6rem 1.2rem;border-radius:6px;text-decoration:none;font-size:.9rem;font-weight:500;transition:all .2s}
|
||||
.btn-primary{background:#0088cc;color:#fff}
|
||||
.btn-primary:hover{background:#00aaff}
|
||||
.btn-outline{border:1px solid #30363d;color:#8b949e;margin-left:.5rem}
|
||||
.btn-outline:hover{border-color:#8b949e;color:#e6edf3}
|
||||
.host-label{color:#6e7681;font-size:.85rem;margin-top:2rem}
|
||||
.status-stopped .status-icon{color:#94A6BF}
|
||||
.status-not_deployed .status-icon{color:#94A6BF}
|
||||
.status-unknown .status-icon{color:#94A6BF}
|
||||
.btn{display:inline-block;padding:.6rem 1.2rem;border-radius:2px;text-decoration:none;font-size:.9rem;font-weight:500;transition:all .2s}
|
||||
.btn-primary{background:#0083D8;color:#fff}
|
||||
.btn-primary:hover{background:#2EA8F5}
|
||||
.btn-outline{border:1px solid #22344F;color:#94A6BF;margin-left:.5rem}
|
||||
.btn-outline:hover{border-color:#94A6BF;color:#EDF2F9}
|
||||
.host-label{color:#5E7392;font-size:.85rem;margin-top:2rem}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container status-{{.Status}}">
|
||||
<img class="logo" src="{{.ControllerURL}}/static/felhom-logo.svg" alt="felhom.eu">
|
||||
<div class="status-icon">
|
||||
{{if eq .Status "stopped"}}⏸{{else if eq .Status "not_deployed"}}📦{{else}}🔍{{end}}
|
||||
{{if eq .Status "stopped"}}<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="14" y="3" width="5" height="18" rx="1"/><rect x="5" y="3" width="5" height="18" rx="1"/></svg>{{else if eq .Status "not_deployed"}}<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z"/></svg>{{else}}<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>{{end}}
|
||||
</div>
|
||||
{{if .AppName}}<div class="app-name">{{.AppName}}</div>{{end}}
|
||||
<div class="status-text">{{.StatusText}}</div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</div>
|
||||
|
||||
<div class="debug-banner">
|
||||
⚠ Debug mód aktív — ez az oldal csak fejlesztéshez és hibaelhárításhoz
|
||||
<svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg> Debug mód aktív — ez az oldal csak fejlesztéshez és hibaelhárításhoz
|
||||
</div>
|
||||
|
||||
<!-- Section 1: System Diagnostic -->
|
||||
@@ -417,7 +417,7 @@ function loadBackupStatus() {
|
||||
if (!data.ok) { document.getElementById('backup-status').innerHTML = '<span class="text-muted">Nem elérhető</span>'; return; }
|
||||
var d = data.data || {};
|
||||
var html = '<div class="debug-kv-grid">';
|
||||
html += '<span>Állapot:</span><span>' + (d.running ? '🔄 Fut' : '✅ Kész') + '</span>';
|
||||
html += '<span>Állapot:</span><span>' + (d.running ? 'Fut...' : 'Kész') + '</span>';
|
||||
if (d.last_db_dump) html += '<span>Utolsó DB dump:</span><span>' + fmtTime(d.last_db_dump) + '</span>';
|
||||
if (d.last_backup) html += '<span>Utolsó restic:</span><span>' + fmtTime(d.last_backup) + '</span>';
|
||||
if (d.snapshot_count !== undefined) html += '<span>Snapshotok:</span><span>' + d.snapshot_count + '</span>';
|
||||
@@ -512,7 +512,7 @@ function loadSelfUpdateStatus() {
|
||||
if (u.last_check) {
|
||||
html += '<span>Jelenlegi:</span><span class="mono">' + u.last_check.current_version + '</span>';
|
||||
html += '<span>Legújabb:</span><span class="mono">' + u.last_check.latest_version + '</span>';
|
||||
html += '<span>Frissítés:</span><span>' + (u.last_check.update_available ? '<span class="state-text-green">Elérhető</span>' : 'Naprakész') + '</span>';
|
||||
html += '<span>Frissítés:</span><span>' + (u.last_check.update_available ? '<span class="state-text-run">Elérhető</span>' : 'Naprakész') + '</span>';
|
||||
}
|
||||
html += '</div>';
|
||||
document.getElementById('selfupdate-status').innerHTML = html;
|
||||
@@ -531,7 +531,7 @@ function loadDRStatus() {
|
||||
html += '<table class="info-table debug-table"><tr><th>Meghajtó</th><th>Cimke</th><th>Állapot</th><th>Utolsó módosítás</th><th>Fájlok</th></tr>';
|
||||
d.drives.forEach(function(dr) {
|
||||
var files = (dr.files || []).join(', ') || '-';
|
||||
html += '<tr><td class="mono">' + dr.path + '</td><td>' + (dr.label||'-') + '</td><td>' + (dr.has_backup ? '✅ Van' : '❌ Nincs') + '</td><td>' + (dr.last_modified ? fmtTime(dr.last_modified) : '-') + '</td><td class="text-muted" style="font-size:.75rem">' + files + '</td></tr>';
|
||||
html += '<tr><td class="mono">' + dr.path + '</td><td>' + (dr.label||'-') + '</td><td>' + (dr.has_backup ? 'Van' : '<span class="state-text-warn">Nincs</span>') + '</td><td>' + (dr.last_modified ? fmtTime(dr.last_modified) : '-') + '</td><td class="text-muted" style="font-size:.75rem">' + files + '</td></tr>';
|
||||
});
|
||||
html += '</table>';
|
||||
} else {
|
||||
@@ -731,11 +731,11 @@ function renderAppExportStatus(d) {
|
||||
return;
|
||||
}
|
||||
var html = '<div class="debug-kv-grid">';
|
||||
html += '<dt>Debug mód</dt><dd>' + (d.debug_enabled ? '<span class="state-text-green">Aktív</span>' : 'Inaktív') + '</dd>';
|
||||
html += '<dt>Debug mód</dt><dd>' + (d.debug_enabled ? '<span class="state-text-run">Aktív</span>' : 'Inaktív') + '</dd>';
|
||||
html += '<dt>Verzió</dt><dd class="mono">' + (d.version||'-') + '</dd>';
|
||||
html += '<dt>Csomagok</dt><dd>' + (d.bundle_count||0) + ' db</dd>';
|
||||
html += '<dt>Temp fájlok</dt><dd>' + (d.stale_temp_count||0) + ' db';
|
||||
if (d.stale_temp_count > 0) html += ' <span style="color:var(--warn)">⚠</span>';
|
||||
if (d.stale_temp_count > 0) html += ' <span style="color:var(--warn)"><svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg></span>';
|
||||
html += '</dd>';
|
||||
html += '</div>';
|
||||
|
||||
@@ -746,7 +746,7 @@ function renderAppExportStatus(d) {
|
||||
html += '<div class="debug-kv-grid">';
|
||||
html += '<dt>Típus</dt><dd>' + (j.job_type||'-') + '</dd>';
|
||||
html += '<dt>Stack</dt><dd>' + (j.display_name || j.stack_name || '-') + '</dd>';
|
||||
html += '<dt>Állapot</dt><dd>' + (j.running ? '🔄 Fut' : j.done ? '✅ Kész' : '⏸ Várakozik') + '</dd>';
|
||||
html += '<dt>Állapot</dt><dd>' + (j.running ? 'Fut...' : j.done ? 'Kész' : 'Várakozik') + '</dd>';
|
||||
if (j.error) html += '<dt>Hiba</dt><dd class="debug-result-error">' + escapeHtml(j.error) + '</dd>';
|
||||
if (j.output_path) html += '<dt>Kimenet</dt><dd class="mono" style="font-size:.75rem">' + escapeHtml(j.output_path) + '</dd>';
|
||||
if (j.output_size) html += '<dt>Méret</dt><dd>' + j.output_size + '</dd>';
|
||||
@@ -754,7 +754,7 @@ function renderAppExportStatus(d) {
|
||||
if (j.steps && j.steps.length > 0) {
|
||||
html += '<div style="margin-top:.5rem">';
|
||||
j.steps.forEach(function(s) {
|
||||
var icon = s.status === 'done' ? '✓' : s.status === 'running' ? '⟳' : s.status === 'failed' ? '✗' : '○';
|
||||
var icon = s.status === 'done' ? '✓' : s.status === 'running' ? '↻' : s.status === 'failed' ? '×' : '○';
|
||||
var cls = s.status === 'failed' ? 'color:var(--crit)' : s.status === 'done' ? 'color:var(--blue)' : s.status === 'running' ? 'color:var(--blue)' : 'color:var(--text-3)';
|
||||
html += '<div style="font-size:.85rem;padding:.1rem 0;' + cls + '">' + icon + ' ' + escapeHtml(s.label);
|
||||
if (s.error) html += ' <span style="font-size:.8rem">(' + escapeHtml(s.error) + ')</span>';
|
||||
@@ -769,7 +769,7 @@ function renderAppExportStatus(d) {
|
||||
html += '<h4 style="margin-top:.75rem">Export könyvtárak</h4>';
|
||||
html += '<table class="info-table debug-table"><tr><th>Útvonal</th><th>Cimke</th><th>Létezik</th></tr>';
|
||||
d.export_dirs.forEach(function(dir) {
|
||||
html += '<tr><td class="mono" style="font-size:.75rem">' + escapeHtml(dir.path) + '</td><td>' + (dir.label||'-') + '</td><td>' + (dir.exists ? '✅' : '❌') + '</td></tr>';
|
||||
html += '<tr><td class="mono" style="font-size:.75rem">' + escapeHtml(dir.path) + '</td><td>' + (dir.label||'-') + '</td><td>' + (dir.exists ? 'igen' : '<span class="state-text-warn">nincs</span>') + '</td></tr>';
|
||||
});
|
||||
html += '</table>';
|
||||
}
|
||||
@@ -836,8 +836,8 @@ function renderAppBundles(bundles) {
|
||||
html += '<td>' + (b.size_human || '-') + '</td>';
|
||||
html += '<td>' + escapeHtml(b.drive_label || b.drive_path) + '</td>';
|
||||
html += '<td>' + (b.encrypted ? '🔒' : '-') + '</td>';
|
||||
html += '<td>' + (b.has_db ? '✅' : '-') + '</td>';
|
||||
html += '<td>' + (b.needs_hdd ? '✅' : '-') + '</td>';
|
||||
html += '<td>' + (b.has_db ? 'igen' : '-') + '</td>';
|
||||
html += '<td>' + (b.needs_hdd ? 'igen' : '-') + '</td>';
|
||||
html += '<td class="mono" style="font-size:.7rem;max-width:200px;overflow:hidden;text-overflow:ellipsis">' + escapeHtml(b.path) + '</td>';
|
||||
html += '</tr>';
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<body class="login-body">
|
||||
<div class="login-card">
|
||||
<img src="/static/felhom-logo.svg" alt="Felhom.eu" class="login-logo">
|
||||
<h1 class="login-title">Otthoni <span class="title-accent">vezérlőpult</span></h1>
|
||||
<p class="login-subtitle">{{.CustomerName}}</p>
|
||||
{{if .Flash}}<div class="alert alert-info">{{.Flash}}</div>{{end}}
|
||||
{{if .Error}}<div class="alert alert-error">{{.Error}}</div>{{end}}
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
} else {
|
||||
stopPolling();
|
||||
indicator.className = 'logs-live-indicator logs-live-paused';
|
||||
indicator.innerHTML = '⏸ Szünetelve';
|
||||
indicator.innerHTML = 'Szünetelve';
|
||||
toggleBtn.textContent = 'Folytatás';
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</div>
|
||||
<div class="settings-row">
|
||||
<span class="settings-label">Biztonsági mentés</span>
|
||||
<span class="settings-value">{{if .BackupEnabled}}<span class="state-text-green">✅ Aktív</span>{{else}}<span class="state-text-red">❌ Inaktív</span>{{end}}</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">
|
||||
@@ -44,7 +44,7 @@
|
||||
{{end}}
|
||||
<div class="settings-row">
|
||||
<span class="settings-label">Monitoring</span>
|
||||
<span class="settings-value">{{if .MonitoringEnabled}}<span class="state-text-green">✅ Aktív</span>{{else}}<span class="state-text-red">❌ Inaktív</span>{{end}}</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">
|
||||
@@ -54,7 +54,7 @@
|
||||
{{end}}
|
||||
<div class="settings-row">
|
||||
<span class="settings-label">Hub jelentés</span>
|
||||
<span class="settings-value">{{if .HubEnabled}}<span class="state-text-green">✅ Aktív</span>{{else}}–{{end}}</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>
|
||||
@@ -74,9 +74,9 @@
|
||||
<span class="settings-value mono">
|
||||
{{.LatestVersion}}
|
||||
{{if .UpdateAvailable}}
|
||||
<span class="state-text-green" style="margin-left:0.5em;">● Frissítés elérhető</span>
|
||||
<span class="state-text-run" style="margin-left:0.5em;">● Frissítés elérhető</span>
|
||||
{{else}}
|
||||
<span style="margin-left:0.5em; color:#888;">— naprakész</span>
|
||||
<span style="margin-left:0.5em; color:var(--text-3);">— naprakész</span>
|
||||
{{end}}
|
||||
</span>
|
||||
</div>
|
||||
@@ -90,13 +90,13 @@
|
||||
{{if .LastCheckError}}
|
||||
<div class="settings-row">
|
||||
<span class="settings-label">Hiba</span>
|
||||
<span class="settings-value state-text-red">{{.LastCheckError}}</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-green">✅ Aktív</span> <span class="mono">({{.AutoUpdateTime}})</span>{{else}}–{{end}}
|
||||
{{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}}
|
||||
@@ -111,16 +111,16 @@
|
||||
{{if .UpdateRunning}}
|
||||
<div class="settings-row">
|
||||
<span class="settings-label">Állapot</span>
|
||||
<span class="settings-value state-text-yellow" id="auto-update-status">⏳ Frissítés folyamatban — a vezérlő hamarosan újraindul…</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-green">✅ Sikeres</span> ({{.PreviousVersion}} → {{.TargetVersion}})
|
||||
{{else if eq .Status "failed"}}<span class="state-text-red">❌ Sikertelen</span> — {{.Error}}
|
||||
{{else if eq .Status "pending"}}<span class="state-text-yellow">⏳ Folyamatban</span>
|
||||
{{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>
|
||||
@@ -231,7 +231,7 @@ pollUntilBack();
|
||||
<div class="storage-path-info">
|
||||
<div class="storage-path-label-wrap" id="label-wrap-{{.Path}}">
|
||||
<span class="storage-path-label" id="label-display-{{.Path}}">{{.Label}}</span>
|
||||
{{if not (or .Disconnected .Decommissioned)}}<button class="btn btn-xs btn-ghost" onclick="editStorageLabel('{{.Path}}', '{{.Label}}')" title="Átnevezés">✏️</button>{{end}}
|
||||
{{if not (or .Disconnected .Decommissioned)}}<button class="btn btn-xs btn-ghost" onclick="editStorageLabel('{{.Path}}', '{{.Label}}')" title="Átnevezés"><svg class="ico ico-sm"><use href="#i-pencil"/></svg></button>{{end}}
|
||||
</div>
|
||||
<span class="storage-path-path mono">{{.Path}}</span>
|
||||
</div>
|
||||
@@ -239,10 +239,10 @@ pollUntilBack();
|
||||
{{if .Disconnected}}
|
||||
<span class="badge badge-error">Leválasztva</span>
|
||||
{{else if .Decommissioned}}
|
||||
<span class="badge state-gray">Kiváltva</span>
|
||||
<span class="tag tag-off"><span class="dot"></span>Kiváltva</span>
|
||||
{{else}}
|
||||
{{if .IsDefault}}<span class="badge state-green">Alapértelmezett</span>{{end}}
|
||||
{{if .Schedulable}}<span class="badge" style="background:rgba(0,136,204,0.15);color:var(--blue-bright)">Aktív</span>{{else}}<span class="badge state-gray">Inaktív</span>{{end}}
|
||||
{{if .IsDefault}}<span class="tag">Alapértelmezett</span>{{end}}
|
||||
{{if .Schedulable}}<span class="tag tag-run"><span class="dot"></span>Aktív</span>{{else}}<span class="tag tag-off"><span class="dot"></span>Inaktív</span>{{end}}
|
||||
{{if .IsUSB}}<span class="badge" style="background:rgba(255,165,0,0.15);color:var(--warn)">USB</span>{{end}}
|
||||
{{if not .IsMounted}}<span class="badge badge-warn">Rendszermeghajtón</span>{{end}}
|
||||
{{end}}
|
||||
@@ -283,9 +283,10 @@ pollUntilBack();
|
||||
<div class="system-info-header">
|
||||
<span class="system-info-value">{{.DiskInfo.UsedHuman}} / {{.DiskInfo.TotalHuman}}</span>
|
||||
</div>
|
||||
<div class="system-bar">
|
||||
<div class="system-bar-fill {{if ge .DiskInfo.UsedPercent 90.0}}system-bar-red{{else if ge .DiskInfo.UsedPercent 70.0}}system-bar-yellow{{else}}system-bar-green{{end}}"
|
||||
style="width:{{printf "%.0f" .DiskInfo.UsedPercent}}%"></div>
|
||||
<div class="meter {{if ge .DiskInfo.UsedPercent 90.0}}crit{{else if ge .DiskInfo.UsedPercent 70.0}}warn{{else}}nominal{{end}}">
|
||||
<div class="meter-track">
|
||||
<div class="meter-fill" style="width:{{printf "%.0f" .DiskInfo.UsedPercent}}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -458,7 +459,7 @@ pollUntilBack();
|
||||
msg.textContent = 'Csatlakoztatás folyamatban…';
|
||||
fetch('/api/storage/netstorage/add',{method:'POST',headers:Object.assign({'Content-Type':'application/json'},csrfHeaders()),body:JSON.stringify(body)})
|
||||
.then(function(r){return r.json();}).then(function(d){
|
||||
if(d.ok){ msg.textContent='Sikeres ✓'; setTimeout(function(){location.reload();},900); }
|
||||
if(d.ok){ msg.textContent='Sikeres'; setTimeout(function(){location.reload();},900); }
|
||||
else { msg.textContent='Hiba: '+(d.error||'ismeretlen'); }
|
||||
}).catch(function(e){ msg.textContent='Hiba: '+e; });
|
||||
}
|
||||
@@ -494,7 +495,7 @@ pollUntilBack();
|
||||
var job=d.data&&d.data.job;
|
||||
if(!job){ if(body) body.textContent='Nincs folyamatban migráció.'; return; }
|
||||
if(body) body.innerHTML=migRender(job);
|
||||
if(job.phase==='done'){ if(body) body.innerHTML+='<br><strong>Kész ✓</strong>'; setTimeout(function(){location.reload();},1500); return; }
|
||||
if(job.phase==='done'){ if(body) body.innerHTML+='<br><strong>Kész</strong>'; setTimeout(function(){location.reload();},1500); return; }
|
||||
if(job.phase==='aborted'){ if(body) body.innerHTML+='<br><strong style="color:var(--danger,#c0392b)">Megszakadt: '+(job.error||'')+'</strong><br>A forrás adatai érintetlenek.'; return; }
|
||||
setTimeout(tick,1500);
|
||||
}).catch(function(){ setTimeout(tick,2000); });
|
||||
@@ -539,7 +540,7 @@ window.__registeredPaths=[{{range .StoragePaths}}{{if .Path}}"{{.Path}}",{{end}}
|
||||
(function(){
|
||||
function esc(s){ return String(s==null?'':s).replace(/[&<>"]/g,function(c){return {'&':'&','<':'<','>':'>','"':'"'}[c];}); }
|
||||
function hum(b){ if(!b||b<=0) return ''; var u=['B','KB','MB','GB','TB'],i=0,v=b; while(v>=1024&&i<u.length-1){v/=1024;i++;} return (v>=10||i===0?Math.round(v):v.toFixed(1))+' '+u[i]; }
|
||||
function usageColorClass(p){ if(p>=85) return 'system-bar-red'; if(p>=70) return 'system-bar-yellow'; return 'system-bar-green'; }
|
||||
function usageColorClass(p){ if(p>=85) return 'crit'; if(p>=70) return 'warn'; return 'nominal'; }
|
||||
function classBadge(d){
|
||||
if(d.class==='fast') return '<span class="badge badge-ok">gyors</span>';
|
||||
if(d.class==='slow') return '<span class="badge badge-muted">lassú</span>';
|
||||
@@ -582,7 +583,7 @@ window.__registeredPaths=[{{range .StoragePaths}}{{if .Path}}"{{.Path}}",{{end}}
|
||||
if(!d.total_bytes || d.total_bytes<=0) return '';
|
||||
var pct = d.used_fraction ? d.used_fraction*100 : (d.used_bytes/d.total_bytes*100);
|
||||
pct = Math.max(0, Math.min(100, pct));
|
||||
return '<div class="drive-cap"><div class="system-bar"><div class="system-bar-fill '+usageColorClass(pct)+'" style="width:'+pct.toFixed(1)+'%"></div></div>'
|
||||
return '<div class="drive-cap meter '+usageColorClass(pct)+'"><div class="meter-track"><div class="meter-fill" style="width:'+pct.toFixed(1)+'%"></div></div>'
|
||||
+'<div class="drive-cap-label">'+hum(d.used_bytes)+' / '+hum(d.total_bytes)+' ('+pct.toFixed(0)+'%)</div></div>';
|
||||
}
|
||||
function actions(d, registered){
|
||||
@@ -797,7 +798,7 @@ window.__registeredPaths=[{{range .StoragePaths}}{{if .Path}}"{{.Path}}",{{end}}
|
||||
<button class="btn btn-sm btn-outline" onclick="triggerGeoSync()">Kézi szinkronizálás</button>
|
||||
<span id="geo-sync-status" class="form-hint">
|
||||
{{if .GeoLastSync}}Utolsó szinkronizálás: {{.GeoLastSync}}{{end}}
|
||||
{{if .GeoLastError}} <span class="state-text-red">{{.GeoLastError}}</span>{{end}}
|
||||
{{if .GeoLastError}} <span class="state-text-crit">{{.GeoLastError}}</span>{{end}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1054,7 +1055,7 @@ window.__registeredPaths=[{{range .StoragePaths}}{{if .Path}}"{{.Path}}",{{end}}
|
||||
var sync = d.data.last_sync || '';
|
||||
var err = d.data.last_sync_error || '';
|
||||
status.innerHTML = sync ? ('Utolsó: ' + sync.substring(0,19).replace('T',' ')) : '';
|
||||
if (err) status.innerHTML += ' <span class="state-text-red">' + escHtml(err) + '</span>';
|
||||
if (err) status.innerHTML += ' <span class="state-text-crit">' + escHtml(err) + '</span>';
|
||||
}
|
||||
});
|
||||
}, 5000);
|
||||
@@ -1332,7 +1333,7 @@ function editStorageLabel(path, currentLabel) {
|
||||
'<input type="hidden" name="storage_path" value="' + path + '">' +
|
||||
'<input type="text" name="storage_label" class="form-control" value="' + currentLabel.replace(/"/g, '"') + '" style="width:200px;padding:.3rem .5rem;font-size:.9rem" maxlength="50">' +
|
||||
'<button type="submit" class="btn btn-xs btn-primary">OK</button>' +
|
||||
'<button type="button" class="btn btn-xs btn-outline" onclick="cancelEditLabel(\'' + path + '\', \'' + currentLabel.replace(/'/g, "\\'") + '\')">✕</button>' +
|
||||
'<button type="button" class="btn btn-xs btn-outline" onclick="cancelEditLabel(\'' + path + '\', \'' + currentLabel.replace(/'/g, "\\'") + '\')">×</button>' +
|
||||
'</form>';
|
||||
wrap.querySelector('input[name=storage_label]').focus();
|
||||
}
|
||||
@@ -1439,7 +1440,7 @@ function cancelEditLabel(path, label) {
|
||||
var btn = document.createElement('button');
|
||||
btn.className = 'btn btn-xs btn-ghost';
|
||||
btn.setAttribute('title', 'Átnevezés');
|
||||
btn.textContent = '✏️';
|
||||
btn.innerHTML = '<svg class="ico ico-sm"><use href="#i-pencil"/></svg>';
|
||||
btn.addEventListener('click', function() { editStorageLabel(path, label); });
|
||||
wrap.appendChild(span);
|
||||
wrap.appendChild(document.createTextNode(' '));
|
||||
|
||||
@@ -104,7 +104,7 @@ async function submitAttach(ev){
|
||||
var r=await fetch('/api/storage/attach',{method:'POST',headers:Object.assign({'Content-Type':'application/json'},csrfHeaders()),body:JSON.stringify(body)});
|
||||
var j=await r.json();
|
||||
if(!j.ok){ throw new Error(j.error||'Hiba'); }
|
||||
out.innerHTML='<div class="alert alert-success">✅ A meghajtó sikeresen csatolva és regisztrálva: <strong class="mono">'+(j.data.where||'')+'</strong>. <a href="/settings">Vissza a Beállításokhoz →</a></div>';
|
||||
out.innerHTML='<div class="alert alert-success">A meghajtó sikeresen csatolva és regisztrálva: <strong class="mono">'+(j.data.where||'')+'</strong>. <a href="/settings">Vissza a Beállításokhoz →</a></div>';
|
||||
}catch(e){ out.innerHTML='<div class="alert alert-error">Hiba: '+e.message+'</div>'; btn.disabled=false; }
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<span class="toggle-label">Beállítás alapértelmezett adattárolóként új telepítéseknél</span>
|
||||
</label>
|
||||
<div class="alert alert-warning" id="warn-databearing" style="display:none;margin-bottom:1rem">
|
||||
⚠️ A kiválasztott meghajtó <strong>adatot tartalmaz</strong>. Az inicializálás (formázás) törli a rajta lévő
|
||||
<svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg> A kiválasztott meghajtó <strong>adatot tartalmaz</strong>. Az inicializálás (formázás) törli a rajta lévő
|
||||
összes adatot — a folytatáshoz meg kell erősítenie.
|
||||
</div>
|
||||
<div class="form-actions" style="gap:.75rem">
|
||||
@@ -144,7 +144,7 @@ async function submitInit(ev){
|
||||
|
||||
function renderConfirm(durableId, out, btn){
|
||||
var name=document.getElementById('mount-name').value;
|
||||
out.innerHTML='<div class="alert alert-warning">⚠️ A meghajtó adatot tartalmaz. A formázás <strong>véglegesen törli</strong> a rajta lévő összes adatot.</div>'
|
||||
out.innerHTML='<div class="alert alert-warning">A meghajtó adatot tartalmaz. A formázás <strong>véglegesen törli</strong> a rajta lévő összes adatot.</div>'
|
||||
+'<div class="confirm-input"><label>Megerősítéshez írja be a csatlakoztatási nevet: <strong class="mono">'+esc(name)+'</strong></label>'
|
||||
+'<input type="text" id="init-confirm-type" class="form-control" autocomplete="off" oninput="document.getElementById(\'init-confirm-go\').disabled=(this.value!==\''+esc(name)+'\')"></div>'
|
||||
+'<div class="form-actions" style="gap:.6rem;margin-top:.75rem"><button id="init-confirm-go" class="btn btn-danger-outline" disabled>Törlés és inicializálás megerősítése</button></div>'
|
||||
@@ -161,7 +161,7 @@ function renderConfirm(durableId, out, btn){
|
||||
|
||||
function finishInit(j, out){
|
||||
if(!j.ok){ out.innerHTML='<div class="alert alert-error">Hiba: '+esc(j.error||'')+'</div>'; document.getElementById('init-btn').disabled=false; return; }
|
||||
out.innerHTML='<div class="alert alert-success">✅ A meghajtó sikeresen inicializálva és regisztrálva: <strong class="mono">'+esc(j.data&&j.data.where)+'</strong>. <a href="/settings">Vissza a Beállításokhoz →</a></div>';
|
||||
out.innerHTML='<div class="alert alert-success">A meghajtó sikeresen inicializálva és regisztrálva: <strong class="mono">'+esc(j.data&&j.data.where)+'</strong>. <a href="/settings">Vissza a Beállításokhoz →</a></div>';
|
||||
}
|
||||
loadDisks();
|
||||
</script>
|
||||
|
||||
@@ -3234,3 +3234,13 @@ span.mono, .mono { font-family: var(--font-data); }
|
||||
.ico-spin { animation: ico-spin 1s linear infinite; }
|
||||
@keyframes ico-spin { to { transform: rotate(360deg); } }
|
||||
@media (prefers-reduced-motion: reduce) { .ico-spin { animation: none; } }
|
||||
|
||||
/* Login page — two-tone heading (H1 last word in blue-bright) */
|
||||
.login-title {
|
||||
font-size: 1.35rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: .25rem;
|
||||
}
|
||||
.login-title .title-accent {
|
||||
color: var(--blue-bright);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user