v0.9.0: Storage paths registry, per-app HDD_PATH resolution, storage management UI

- Fix backup toggles not appearing (read each app's own HDD_PATH from app.yaml)
- Storage paths registry in settings.json with auto-discovery from deployed apps
- Settings page "Adattárolók" section with disk usage, add/remove/default/schedulable
- Deploy page path field as dropdown of registered storage paths
- Health check storage monitoring (mount point, disk usage alerts)
- Mount-point validation utilities (Linux syscall + cross-platform stubs)
- Controller docker-compose mount changed to /mnt:/mnt:rw for multi-storage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-17 09:04:28 +01:00
parent 465dec443f
commit aca3b8680a
17 changed files with 963 additions and 33 deletions
@@ -63,6 +63,104 @@
</div>
</div>
<!-- Section: Storage Paths -->
<div class="settings-card">
<h3>Adattárolók</h3>
<p class="settings-card-desc">Külső meghajtók kezelése alkalmazásadatok tárolásához.</p>
{{if .StorageError}}<div class="alert alert-error">{{.StorageError}}</div>{{end}}
{{if .StoragePaths}}
<div class="storage-paths-list">
{{range .StoragePaths}}
<div class="storage-path-item">
<div class="storage-path-header">
<div class="storage-path-info">
<span class="storage-path-label">{{.Label}}</span>
<span class="storage-path-path mono">{{.Path}}</span>
</div>
<div class="storage-path-badges">
{{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(--accent-light)">Aktív</span>{{else}}<span class="badge state-gray">Inaktív</span>{{end}}
{{if not .IsMounted}}<span class="badge state-red">Nincs csatolva!</span>{{end}}
</div>
</div>
<div class="storage-path-details">
{{if .DiskInfo}}
<div class="storage-path-disk">
<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>
</div>
{{end}}
<div class="storage-path-meta">
<span class="form-hint">{{.AppCount}} alkalmazás használja</span>
</div>
</div>
<div class="storage-path-actions">
{{if not .IsDefault}}
<form method="POST" action="/settings/storage/default" style="display:inline">
<input type="hidden" name="storage_path" value="{{.Path}}">
<button type="submit" class="btn btn-xs btn-outline">Alapértelmezett</button>
</form>
{{end}}
{{if .Schedulable}}
<form method="POST" action="/settings/storage/schedulable" style="display:inline">
<input type="hidden" name="storage_path" value="{{.Path}}">
<input type="hidden" name="schedulable" value="false">
<button type="submit" class="btn btn-xs btn-outline">Letiltás</button>
</form>
{{else}}
<form method="POST" action="/settings/storage/schedulable" style="display:inline">
<input type="hidden" name="storage_path" value="{{.Path}}">
<input type="hidden" name="schedulable" value="true">
<button type="submit" class="btn btn-xs btn-outline">Engedélyezés</button>
</form>
{{end}}
{{if and (not .IsDefault) (eq .AppCount 0)}}
<form method="POST" action="/settings/storage/remove" style="display:inline"
onsubmit="return confirm('Biztosan eltávolítja a(z) {{.Path}} adattárolót?')">
<input type="hidden" name="storage_path" value="{{.Path}}">
<button type="submit" class="btn btn-xs btn-danger-outline">Eltávolítás</button>
</form>
{{end}}
</div>
</div>
{{end}}
</div>
{{else}}
<div class="empty-state" style="padding:1.5rem">
Nincs regisztrált adattároló. Adjon hozzá egyet az alábbi űrlappal.
</div>
{{end}}
<details class="storage-add-details">
<summary class="btn btn-sm btn-outline" style="margin-top:1rem;cursor:pointer">Új adattároló hozzáadása</summary>
<form method="POST" action="/settings/storage/add" class="storage-add-form">
<div class="form-group">
<label for="storage_path">Elérési út</label>
<input type="text" id="storage_path" name="storage_path" class="form-control"
placeholder="/mnt/hdd_1" required>
<span class="form-hint">Pl. /mnt/hdd_1 — a meghajtónak már csatolva kell lennie</span>
</div>
<div class="form-group">
<label for="storage_label">Megnevezés (opcionális)</label>
<input type="text" id="storage_label" name="storage_label" class="form-control"
placeholder="Külső HDD 1TB">
</div>
<label class="toggle" style="margin-bottom:1rem">
<input type="checkbox" name="storage_default" value="true">
<span class="toggle-label">Legyen alapértelmezett új telepítéseknél</span>
</label>
<button type="submit" class="btn btn-primary">Hozzáadás</button>
</form>
</details>
</div>
<!-- Section B: Password Change -->
<div class="settings-card">
<h3>Jelszó módosítás</h3>