From 90826dec7a09f240d67246e55d638b3ad3e6ad60 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Wed, 18 Feb 2026 13:30:21 +0100 Subject: [PATCH] v0.13.0: UI polish fixes (8 improvements) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix 1: Dashboard backup card border (verified already correct) - Fix 2: Show auto-generated env values on deploy page with copy/reveal - Fix 3: Temperature value pill for better visibility on dashboard - Fix 4: Rework dashboard backup section (remove manual trigger, add Tier 2 summary) - Fix 5: Scope HDD warning banner to dashboard and monitoring pages only - Fix 6: Move Tárhely section up in monitoring page - Fix 7: Snapshot table clarity (HOZZÁADOTT header, n/a instead of -) - Fix 8: Restructure Tároló section into tiered storage view Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 21 +++ controller/internal/web/alerts.go | 22 ++- controller/internal/web/funcmap.go | 10 ++ controller/internal/web/handlers.go | 61 ++++++++ .../internal/web/templates/backups.html | 138 +++++++++++------- .../internal/web/templates/dashboard.html | 47 ++---- controller/internal/web/templates/deploy.html | 33 +++++ controller/internal/web/templates/layout.html | 2 + .../internal/web/templates/monitoring.html | 66 ++++----- controller/internal/web/templates/style.css | 54 ++++++- 10 files changed, 328 insertions(+), 126 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56467b3..1865324 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ ## Changelog +### What was just completed (2026-02-18 session 47) +- **v0.13.0 — UI Polish Fixes (8 independent fixes):** + + **Fix 1:** backup-status-card border already correct (verified same styling as system-info-card). + + **Fix 2:** Deploy page auto-generated fields now show actual values for deployed apps (`deploy.html`, `handlers.go`). Secrets show as password fields with show/hide toggle; domain/plain values show as readonly text with copy button. JS helpers `toggleAutoField()` / `copyAutoField()` added. + + **Fix 3:** Temperature display made more prominent (`dashboard.html`, `style.css`). Dot enlarged to 11px; value wrapped in colored pill badge (`.temp-value-pill` / `.temp-pill-{green|yellow|red}`). + + **Fix 4:** Dashboard backup card reworked (`dashboard.html`, `handlers.go`). Removed "Mentés most" button and `triggerBackup()` JS. Removed "Tároló méret" line. Added Tier 2 status line (configured/total apps) + warning row for failed cross-drive backups. Handler now computes `CrossDriveTotal`, `CrossDriveConfigured`, `CrossDriveFailed`. + + **Fix 5:** HDD warning banner scoped to dashboard + monitoring pages only (`alerts.go`, `layout.html`, `funcmap.go`). Added `PageOnly []string` field to `Alert` struct. Disk-related warnings (keywords "meghajtón", "adattároló") get stable ID `"disk-not-separate"` + `PageOnly: ["dashboard", "monitoring"]`. `pageMatch()` template function added. Layout renders alerts conditionally. + + **Fix 6:** Tárhely section moved up in Rendszermonitor — now appears right after "Rendszer áttekintés", before "Távoli monitoring" (`monitoring.html`). + + **Fix 7:** Snapshot table improvements (`backups.html`, `style.css`). "MÉRET" renamed to "HOZZÁADOTT (új adat)". `–` for unavailable data replaced with `n/a` (with tooltip explaining restic limitations). New `.col-subtitle` and `.col-na` CSS classes. + + **Fix 8:** Tároló section restructured into tiers (`backups.html`, `handlers.go`, `style.css`). Tier 1 (restic local), Tier 2 (cross-drive, only shown if configured), DB dump directory + total size. Removed "Távoli másolat: Nincs beállítva" placeholder. Handler passes `DBDumpDir`, `DBDumpTotalBytes`, `Tier2Dests` (deduplicated). New `.repo-tier` / `.repo-tier-title` CSS. + + **Files modified (9):** `alerts.go`, `funcmap.go`, `handlers.go`, `templates/style.css`, `templates/dashboard.html`, `templates/backups.html`, `templates/deploy.html`, `templates/monitoring.html`, `templates/layout.html` + ### What was just completed (2026-02-18 session 46) - **v0.12.9 — Tier 2 for All Apps + Status Dot Update:** diff --git a/controller/internal/web/alerts.go b/controller/internal/web/alerts.go index 2cd6ec4..d28291e 100644 --- a/controller/internal/web/alerts.go +++ b/controller/internal/web/alerts.go @@ -3,6 +3,7 @@ package web import ( "fmt" "log" + "strings" "sync" "gitea.dooplex.hu/admin/felhom-controller/internal/backup" @@ -12,11 +13,12 @@ import ( // Alert represents a persistent dashboard alert banner. type Alert struct { - ID string // unique identifier for filtering - Level string // "error", "warning", "info" - Message string // Hungarian display text - Link string // optional link to relevant page - LinkText string // link display text + ID string // unique identifier for filtering + Level string // "error", "warning", "info" + Message string // Hungarian display text + Link string // optional link to relevant page + LinkText string // link display text + PageOnly []string // if non-empty, only show on these pages (e.g., ["dashboard", "monitoring"]) } // AlertManager generates and stores dashboard alerts from health check results. @@ -53,13 +55,19 @@ func (am *AlertManager) Refresh(report *monitor.HealthReport, cfg *config.Config // From health check warnings for _, w := range report.Warnings { - alerts = append(alerts, Alert{ + alert := Alert{ ID: "health-" + simpleHash(w), Level: "warning", Message: w, Link: "/monitoring", LinkText: "Rendszermonitor", - }) + } + // Disk-related warnings only relevant on dashboard and monitoring pages + if strings.Contains(w, "meghajtón") || strings.Contains(w, "adattároló") || strings.Contains(w, "meghajtó") { + alert.ID = "disk-not-separate" + alert.PageOnly = []string{"dashboard", "monitoring"} + } + alerts = append(alerts, alert) } // Missing ping UUIDs diff --git a/controller/internal/web/funcmap.go b/controller/internal/web/funcmap.go index c1e8df3..bedf72e 100644 --- a/controller/internal/web/funcmap.go +++ b/controller/internal/web/funcmap.go @@ -305,5 +305,15 @@ func (s *Server) templateFuncMap() template.FuncMap { } return id }, + // pageMatch returns true if currentPage is in the pages slice. + // Used to filter page-specific alerts in layout.html. + "pageMatch": func(pages []string, currentPage string) bool { + for _, p := range pages { + if p == currentPage { + return true + } + } + return false + }, } } diff --git a/controller/internal/web/handlers.go b/controller/internal/web/handlers.go index 6e72727..58149ef 100644 --- a/controller/internal/web/handlers.go +++ b/controller/internal/web/handlers.go @@ -100,6 +100,28 @@ func (s *Server) dashboardHandler(w http.ResponseWriter, _ *http.Request) { data["BackupStatus"] = fullStatus.LastBackup data["BackupRunning"] = fullStatus.Running data["BackupMaxAgeHours"] = s.cfg.Monitoring.Thresholds.BackupMaxAgeHours + + // Cross-drive summary for dashboard Tier 2 status line + crossConfigs := s.settings.GetAllCrossDriveConfigs() + crossDriveTotal := 0 + crossDriveConfigured := 0 + crossDriveFailed := 0 + for _, st := range deployedStacks { + if st.Protected { + continue + } + crossDriveTotal++ + cfg, hasCfg := crossConfigs[st.Name] + if hasCfg && cfg != nil && cfg.Enabled { + crossDriveConfigured++ + if cfg.LastStatus == "error" { + crossDriveFailed++ + } + } + } + data["CrossDriveTotal"] = crossDriveTotal + data["CrossDriveConfigured"] = crossDriveConfigured + data["CrossDriveFailed"] = crossDriveFailed } s.render(w, "dashboard", data) @@ -181,6 +203,16 @@ func (s *Server) deployHandler(w http.ResponseWriter, r *http.Request, name stri data["AppPageURL"] = s.cfg.AppPageURL(meta.Slug) data["UserFields"] = meta.UserFacingFields() data["AutoFields"] = meta.AutoGeneratedFields() + // Auto-generated field values for already-deployed apps + autoFieldValues := make(map[string]string) + if alreadyDeployed && appCfg != nil { + for _, f := range meta.AutoGeneratedFields() { + if val, ok := appCfg.Env[f.EnvVar]; ok { + autoFieldValues[f.EnvVar] = val + } + } + } + data["AutoFieldValues"] = autoFieldValues // Storage paths with free space info for deploy dropdown var deployPaths []DeployStoragePath for _, sp := range s.settings.GetSchedulableStoragePaths() { @@ -487,6 +519,35 @@ func (s *Server) backupsHandler(w http.ResponseWriter, r *http.Request) { if pw, err := s.backupMgr.GetResticPassword(); err == nil { data["ResticPassword"] = pw } + + // Tároló section: DB dump directory and total size + data["DBDumpDir"] = s.cfg.Paths.DBDumpDir + var dbDumpTotalBytes int64 + for _, f := range fullStatus.DumpFiles { + dbDumpTotalBytes += f.Size + } + data["DBDumpTotalBytes"] = dbDumpTotalBytes + + // Tároló section: deduplicated Tier 2 destination list + tier2DestMap := make(map[string]map[string]string) + for _, item := range fullStatus.CrossDriveSummary { + if item.DestPath == "" { + continue + } + if _, exists := tier2DestMap[item.DestPath]; !exists { + tier2DestMap[item.DestPath] = map[string]string{ + "Path": item.DestPath, + "Label": item.DestLabel, + "Method": item.MethodLabel, + "SizeHuman": item.SizeHuman, + } + } + } + var tier2DestList []map[string]string + for _, d := range tier2DestMap { + tier2DestList = append(tier2DestList, d) + } + data["Tier2Dests"] = tier2DestList } else { data["Backup"] = nil } diff --git a/controller/internal/web/templates/backups.html b/controller/internal/web/templates/backups.html index aa22a7e..78a58c0 100644 --- a/controller/internal/web/templates/backups.html +++ b/controller/internal/web/templates/backups.html @@ -346,7 +346,7 @@ Azonosító Időpont - Méret + Hozzáadott (új adat) Új fájl Változott @@ -356,9 +356,9 @@ {{shortID .SnapshotID}} {{fmtTime .Time}} - {{if .HasStats}}+{{.DataAdded}}{{else}}–{{end}} - {{if .HasStats}}{{.FilesNew}}{{else}}–{{end}} - {{if .HasStats}}{{.FilesChanged}}{{else}}–{{end}} + {{if .HasStats}}+{{.DataAdded}}{{else}}n/a{{end}} + {{if .HasStats}}{{.FilesNew}}{{else}}n/a{{end}} + {{if .HasStats}}{{.FilesChanged}}{{else}}n/a{{end}} {{end}} @@ -376,63 +376,101 @@

Tároló

-
-
- Helyszín: - {{.Backup.RepoPath}} (helyi) + + +
+

1. mentés — Helyi mentés (restic)

+
+
+ Helyszín: + {{.Backup.RepoPath}} (helyi SSD) +
+ {{if .Backup.RepoStats}} +
+ Méret: + {{.Backup.RepoStats.TotalSize}} +
+
+ Pillanatképek: + {{.Backup.RepoStats.SnapshotCount}} +
+ {{end}} +
+ Integritás: + + {{if .Backup.LastCheckTime.IsZero}} + Még nem ellenőrzött + {{else if .Backup.LastCheckOK}} + Rendben ({{fmtTime .Backup.LastCheckTime}}) + {{else}} + Hiba ({{fmtTime .Backup.LastCheckTime}}) + {{end}} + +
- {{if .Backup.RepoStats}} -
- Méret: - {{.Backup.RepoStats.TotalSize}} -
-
- Pillanatképek: - {{.Backup.RepoStats.SnapshotCount}} + + + {{if $.ResticPassword}} +
+ Titkosítási kulcs: +
+ + + +
+
+ Mentse el biztonságos helyre! A kulcs nélkül a biztonsági mentések NEM állíthatók vissza. +
{{end}} -
- Integritás: - - {{if .Backup.LastCheckTime.IsZero}} - Még nem ellenőrzött - {{else if .Backup.LastCheckOK}} - Rendben ({{fmtTime .Backup.LastCheckTime}}) - {{else}} - Hiba ({{fmtTime .Backup.LastCheckTime}}) + +
+ Mentett útvonalak (forrás): +
    + {{range .Backup.BackupPaths}} +
  • {{.}}
  • {{end}} - +
- - {{if $.ResticPassword}} -
- Titkosítási kulcs: -
- - - -
-
- Mentse el biztonságos helyre! A kulcs nélkül a biztonsági mentések NEM állíthatók vissza. + + {{if .Tier2Dests}} +
+

2. mentés — Másodlagos másolat

+ {{range .Tier2Dests}} +
+
+ Cél: + {{index . "Path"}}{{if index . "Label"}} ({{index . "Label"}}){{end}} +
+
+ Módszer: + {{index . "Method"}} +
+ {{if index . "SizeHuman"}} +
+ Méret: + {{index . "SizeHuman"}} +
+ {{end}}
+ {{end}}
{{end}} -
- Mentett útvonalak: -
    - {{range .Backup.BackupPaths}} -
  • {{.}}
  • - {{end}} -
-
-
- Távoli másolat: -
- Nincs beállítva - (B2/S3/SFTP támogatás hamarosan) + +
+

Adatbázis mentések

+
+
+ Mappa: + {{.DBDumpDir}} +
+
+ Fájlok: + {{if .Backup.DumpFiles}}{{len .Backup.DumpFiles}} dump fájl{{if gt .DBDumpTotalBytes 0}} — {{fmtBytes .DBDumpTotalBytes}}{{end}}{{else}}Nincs dump fájl{{end}} +
diff --git a/controller/internal/web/templates/dashboard.html b/controller/internal/web/templates/dashboard.html index 83f0add..9b40b10 100644 --- a/controller/internal/web/templates/dashboard.html +++ b/controller/internal/web/templates/dashboard.html @@ -49,7 +49,7 @@ Hőmérséklet - {{fmtTemp .SystemInfo.TemperatureCelsius}} + {{fmtTemp .SystemInfo.TemperatureCelsius}}
@@ -106,17 +106,24 @@ {{len .DBDumpStatus.Results}} mentve
{{end}} - {{if .BackupStatus}}{{if .BackupStatus.RepoStats}} + {{if gt .CrossDriveTotal 0}}
- Tároló méret: - {{.BackupStatus.RepoStats.TotalSize}} ({{.BackupStatus.RepoStats.SnapshotCount}} pillanatkép) + 2. mentés: + + {{if eq .CrossDriveConfigured 0}} + ⚠ Nincs beállítva + {{else}} + {{.CrossDriveConfigured}} / {{.CrossDriveTotal}} alk. + {{end}} +
- {{end}}{{end}} -
- + {{end}} + {{if gt .CrossDriveFailed 0}} +
+ Figyelmeztetés: + ⚠ {{.CrossDriveFailed}} 2. mentés sikertelen
+ {{end}}
{{end}} @@ -163,28 +170,6 @@ {{end}}
- {{template "layout_end" .}} {{end}} diff --git a/controller/internal/web/templates/deploy.html b/controller/internal/web/templates/deploy.html index 6653883..ab57262 100644 --- a/controller/internal/web/templates/deploy.html +++ b/controller/internal/web/templates/deploy.html @@ -255,9 +255,26 @@

Automatikusan generált értékek

Ezek az értékek automatikusan létrejönnek a telepítéskor.

+ {{$autoValues := .AutoFieldValues}} + {{$isDeployed := .AlreadyDeployed}} {{range .AutoFields}} + {{$val := index $autoValues .EnvVar}}
+ {{if and $isDeployed $val}} + {{if eq .Type "secret"}} +
+ + + +
+ {{else}} +
+ + +
+ {{end}} + {{end}} ✓ Automatikusan generálva
{{end}} @@ -438,6 +455,22 @@ document.addEventListener('DOMContentLoaded', function() { if (sel) checkStorageSpace(sel); }); +function toggleAutoField(fieldId, btn) { + var el = document.getElementById(fieldId); + if (!el) return; + el.type = el.type === 'password' ? 'text' : 'password'; + btn.textContent = el.type === 'password' ? 'Megjelenítés' : 'Elrejtés'; +} +function copyAutoField(fieldId, btn) { + var el = document.getElementById(fieldId); + if (!el) return; + navigator.clipboard.writeText(el.value).then(function() { + var orig = btn.textContent; + btn.textContent = 'Másolva!'; + setTimeout(function() { btn.textContent = orig; }, 2000); + }); +} + function generatePassword(fieldId) { const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; let pass = ''; diff --git a/controller/internal/web/templates/layout.html b/controller/internal/web/templates/layout.html index 590c3cb..0af9623 100644 --- a/controller/internal/web/templates/layout.html +++ b/controller/internal/web/templates/layout.html @@ -31,12 +31,14 @@ {{if .Alerts}}
{{range .Alerts}} + {{if or (not .PageOnly) (pageMatch .PageOnly $.Page)}}
{{if eq .Level "error"}}🔴{{else if eq .Level "warning"}}🟡{{else}}ℹ️{{end}} {{.Message}} {{if .Link}}{{.LinkText}} →{{end}}
{{end}} + {{end}}
{{end}} {{end}} diff --git a/controller/internal/web/templates/monitoring.html b/controller/internal/web/templates/monitoring.html index 048f984..62c7421 100644 --- a/controller/internal/web/templates/monitoring.html +++ b/controller/internal/web/templates/monitoring.html @@ -36,7 +36,36 @@
- + +
+

Tárhely

+
+ {{with .SystemInfo}} +
+
+ SSD (/) + {{fmtGB .DiskUsedGB}} / {{fmtGB .DiskTotalGB}} ({{printf "%.0f" .DiskPercent}}%) +
+
+
+
+
+ {{if .HDDConfigured}} +
+
+ Külső HDD + {{fmtGB .HDDUsedGB}} / {{fmtGB .HDDTotalGB}} ({{printf "%.0f" .HDDPercent}}%) +
+
+
+
+
+ {{end}} + {{end}} +
+
+ +

Távoli monitoring

{{if not .MonitoringEnabled}} @@ -67,7 +96,7 @@ {{end}}
- +

Rendszer metrikák

@@ -102,7 +131,7 @@
- +

Alkalmazás erőforrások

@@ -120,7 +149,7 @@
- + - -
-

Tárhely

-
- {{with .SystemInfo}} -
-
- SSD (/) - {{fmtGB .DiskUsedGB}} / {{fmtGB .DiskTotalGB}} ({{printf "%.0f" .DiskPercent}}%) -
-
-
-
-
- {{if .HDDConfigured}} -
-
- Külső HDD - {{fmtGB .HDDUsedGB}} / {{fmtGB .HDDTotalGB}} ({{printf "%.0f" .HDDPercent}}%) -
-
-
-
-
- {{end}} - {{end}} -
-
-