v0.13.0 UI Polish Fixes
This commit is contained in:
@@ -11,7 +11,7 @@ Creating a business (Felhom) for home-server deployment for Hungarian customers.
|
||||
Compose stacks on customer hardware via a Hungarian-language web dashboard.
|
||||
|
||||
See `controller/README.md` for full architecture and status (update after each session, keep track of how different functions/features operate, like backup, monitoring, storage handling, app management, user settings, update workflow, notification system, etc-etc...).
|
||||
See `CHANGELOG.md` for recent work (update after each session).
|
||||
See `CHANGELOG.md` for recent work (update after each session — see "Working with CHANGELOG.md" below).
|
||||
See `CONTEXT.md` for current project state, decisions and roadmap (update after each session).
|
||||
See `TASK.md` for the current task to implement (if it exists).
|
||||
|
||||
@@ -253,6 +253,14 @@ Key patterns used in `internal/stacks/`:
|
||||
7. Mealie image has no wget/curl — use Python TCP socket check for healthcheck; set `start_period: 60s` for DB migration time
|
||||
8. Always verify container images have the healthcheck tool (`wget`, `curl`, etc.) before using it — Alpine has BusyBox wget, Python images have `python3`
|
||||
|
||||
## Working with CHANGELOG.md
|
||||
|
||||
**DO NOT read the full file** — it is large (29K+ tokens) and will waste context or fail.
|
||||
|
||||
- **At session start:** Do NOT read CHANGELOG.md. Use `CONTEXT.md` and `controller/README.md` for current state.
|
||||
- **To add a new entry:** Read only the top ~30 lines (`limit: 30`) to see the format and insertion point, then use Edit to insert the new entry after line 1 (`## Changelog`).
|
||||
- **To check history:** Use Grep to search for specific topics instead of reading the file.
|
||||
|
||||
## End-of-session checklist
|
||||
|
||||
Before ending a session, always:
|
||||
|
||||
@@ -1,404 +1,211 @@
|
||||
# TASK.md — Tier 2 for All Apps + Status Dot Update (v0.12.9)
|
||||
# TASK.md — v0.13.0 UI Polish Fixes
|
||||
|
||||
## Prompt (copy-paste this into Claude Code)
|
||||
**Version:** v0.13.0
|
||||
**Type:** UI polish — 8 independent fixes
|
||||
**Files likely affected:** `dashboard.html`, `backups.html`, `deploy.html`, `monitoring.html`, `style.css`, `handlers.go`, `alerts.go`
|
||||
|
||||
```
|
||||
Read TASK.md for the full plan. Apply all code changes described, then build and deploy.
|
||||
After all fixes are done:
|
||||
1. Run `go build ./...` and `go vet ./...` from the controller/ directory — fix any errors
|
||||
2. Update CHANGELOG.md with a new entry at the top (session 46, v0.12.9)
|
||||
3. Commit, build, and deploy following the workflow in CLAUDE.md
|
||||
```
|
||||
Read `CLAUDE.md`, `controller/README.md`, and `CONTEXT.md` before starting.
|
||||
|
||||
---
|
||||
|
||||
## Context and Goals
|
||||
## Fix 1: Dashboard backup card missing border
|
||||
|
||||
Currently Tier 2 (cross-drive backup) is only available for apps with HDD data (Immich,
|
||||
Paperless-ngx, etc.). Apps without HDD data (Mealie, Gokapi, etc.) cannot configure Tier 2
|
||||
at all — the config section is hidden, the code rejects empty mounts, and the UI shows them
|
||||
as "auto" (gray dot).
|
||||
**Problem:** The "Biztonsági mentés" card on the Vezérlőpult page has no visible border/box, unlike all other sections on the page (stats-grid, system-info-card, stack-list). It looks out of place.
|
||||
|
||||
**Problem:** These apps have only 1 tier of protection. If the primary drive fails, their DB
|
||||
and config are lost. The customer should be able to configure Tier 2 for ANY app.
|
||||
**Solution:** The `.backup-status-card` in `dashboard.html` needs the same card styling as `.system-info-card` — a border, background, and border-radius consistent with the dark card style used throughout the UI.
|
||||
|
||||
**Changes in this version:**
|
||||
|
||||
1. **Tier 2 for all apps** — Remove all HDD-only gates. Non-HDD apps back up config + DB
|
||||
dumps to the secondary drive (small, but protects against drive failure).
|
||||
2. **Status dot update** — Remove "auto" (gray). All apps start as yellow (1 tier only).
|
||||
Green requires 2+ tiers with successful backups.
|
||||
3. **Tier 3 placeholder** — Show a disabled "3. mentés" row in the UI (future: remote backup).
|
||||
4. **Deploy page** — Show cross-drive config form for ALL deployed apps, not just HDD ones.
|
||||
|
||||
**What non-HDD apps back up in Tier 2:**
|
||||
- App with DB (e.g., Mealie): `_config/` + `_db/mealie_postgres.sql`
|
||||
- App without DB (e.g., Gokapi): `_config/` only
|
||||
- Small files — seconds to rsync/restic, but provides drive-failure protection.
|
||||
**Where:**
|
||||
- `style.css`: Check if `.backup-status-card` already has card-like styling. If not, add `border: 1px solid var(--border)`, `background: var(--card-bg)`, `border-radius: 12px`, `padding` — match whatever `.system-info-card` or `.monitor-card` uses.
|
||||
|
||||
---
|
||||
|
||||
## Fix 1: Remove empty-mounts gate from RunAppBackup
|
||||
## Fix 2: Show auto-generated env values on deploy page
|
||||
|
||||
**File:** `internal/backup/crossdrive.go`
|
||||
**Problem:** When an app is already deployed, auto-generated values (Domain, DB password, etc.) only show a label + "✓ Automatikusan generálva" green badge. The actual values are hidden. Users need to see what was generated (e.g., to configure DNS, or to log into the app's DB).
|
||||
|
||||
In `RunAppBackup()`, the code currently errors out when no HDD mounts exist (lines 98–103):
|
||||
**Solution:** Show the actual values in read-only fields. Passwords should be masked by default with a show/hide toggle (eye icon button), like the restic password on the backup page. Non-secret values (like Domain) should be shown in plain text.
|
||||
|
||||
```go
|
||||
// CURRENT CODE — DELETE these 4 lines:
|
||||
mounts := r.stackProvider.GetStackHDDMounts(stackName)
|
||||
if len(mounts) == 0 {
|
||||
r.updateStatus(stackName, "error", "no HDD data paths found for this app", time.Since(start), "")
|
||||
return fmt.Errorf("no HDD data paths found for %s", stackName)
|
||||
}
|
||||
```
|
||||
**Where:**
|
||||
- `deploy.html`: In the "Automatikusan generált értékek" section, replace the simple badge-only display with actual field values. For each auto field:
|
||||
- If the field type is `password` or the key contains `PASSWORD`/`SECRET`/`KEY`: render a read-only `<input type="password">` with a toggle-visibility button (eye icon). Use the same pattern as the restic password field in `backups.html` ("Megjelenítés" / "Elrejtés" toggle button).
|
||||
- Otherwise (domain, non-secret values): render a read-only `<input type="text">` showing the value, plus a "Másolás" (copy) button.
|
||||
- Keep the "✓ Automatikusan generálva" badge too, but next to the field, not replacing it.
|
||||
- `handlers.go` (`deployHandler`): The auto field values need to be passed to the template. Currently `AutoFields` comes from `meta.AutoGeneratedFields()`. Check if the values are already populated from `app.yaml` for deployed apps. If not, read them from the stack's `.env` file or `app.yaml` `env_values` map. The values must be available in the template data.
|
||||
- `style.css`: Add styling for the auto-field display (read-only input + button group), keeping it consistent with the rest of the deploy form.
|
||||
|
||||
**Replace with:**
|
||||
|
||||
```go
|
||||
// Resolve HDD mounts for this app (may be empty for config-only apps)
|
||||
mounts := r.stackProvider.GetStackHDDMounts(stackName)
|
||||
```
|
||||
|
||||
**Why this works:** The rest of the function already handles empty mounts correctly:
|
||||
- Safety overlap check: empty loop = no overlap → passes
|
||||
- `runRsyncBackup`: mount loop doesn't execute, but DB + config copy still runs
|
||||
- `runResticBackup`: no mount paths appended, but config dir + DB dump dir still included
|
||||
- Size calculation: destDir exists and can be measured even without mount data
|
||||
**Important:** Only show values for already-deployed apps. For new deployments (not yet deployed), keep the current behavior (just show the badge, since values haven't been generated yet).
|
||||
|
||||
---
|
||||
|
||||
## Fix 2: Update status dot logic + remove HasHDDData gates from handlers.go
|
||||
## Fix 3: Temperature value not visible enough on dashboard
|
||||
|
||||
**File:** `internal/web/handlers.go`
|
||||
**Problem:** The temperature display in the system info card blends into the heading text. The small colored dot + number isn't prominent enough.
|
||||
|
||||
### 2a: Update `AppBackupRow` struct comments
|
||||
**Solution:** Make the temperature more visually distinct:
|
||||
- Increase the font size of the temperature value (make it match the other metric values like memory/CPU percentages)
|
||||
- Add a background pill/badge around the temperature value with a subtle color matching the status (green/yellow/red background with low opacity)
|
||||
- Keep the colored dot but make it slightly larger
|
||||
|
||||
In the `AppBackupRow` struct, update the Tier 2 comment:
|
||||
|
||||
```go
|
||||
// Tier 2: Cross-drive backup (configurable for all apps)
|
||||
```
|
||||
|
||||
(Remove the old "(only for apps with HDD data)" comment.)
|
||||
|
||||
### 2b: Rewrite `buildAppBackupRows` status + Tier2 section
|
||||
|
||||
Replace the current status + Tier2 block (lines 605–672):
|
||||
|
||||
**CURRENT CODE:**
|
||||
```go
|
||||
// Default status = auto (no user data, just config)
|
||||
row.Status = "auto"
|
||||
row.StatusText = "Automatikus mentés"
|
||||
|
||||
if app.HasHDDData {
|
||||
cfg, hasCfg := crossConfigs[app.StackName]
|
||||
// ... full Tier2 block ...
|
||||
}
|
||||
```
|
||||
|
||||
**REPLACE WITH:**
|
||||
```go
|
||||
// Status dot — start as yellow (1 tier only)
|
||||
row.Status = "yellow"
|
||||
row.StatusText = "Csak helyi mentés (1 szint)"
|
||||
|
||||
cfg, hasCfg := crossConfigs[app.StackName]
|
||||
|
||||
if !hasCfg || cfg == nil || !cfg.Enabled {
|
||||
// Only Tier 1 — no second copy
|
||||
row.Tier2Configured = false
|
||||
} else {
|
||||
row.Tier2Configured = true
|
||||
row.Tier2Method = cfg.Method
|
||||
row.Tier2MethodLabel = cfg.Method // "rsync" or "restic"
|
||||
row.Tier2Browsable = cfg.Method == "rsync"
|
||||
row.Tier2Dest = destLabels[cfg.DestinationPath]
|
||||
if row.Tier2Dest == "" {
|
||||
row.Tier2Dest = cfg.DestinationPath
|
||||
}
|
||||
switch cfg.Schedule {
|
||||
case "daily":
|
||||
row.Tier2Schedule = "Naponta"
|
||||
case "weekly":
|
||||
row.Tier2Schedule = "Hetente"
|
||||
default:
|
||||
row.Tier2Schedule = cfg.Schedule
|
||||
}
|
||||
if cfg.LastRun != "" {
|
||||
if t, err := time.Parse(time.RFC3339, cfg.LastRun); err == nil {
|
||||
row.Tier2LastRun = t.In(loc).Format("01-02 15:04")
|
||||
}
|
||||
}
|
||||
row.Tier2LastStatus = cfg.LastStatus
|
||||
row.Tier2LastError = cfg.LastError
|
||||
row.Tier2SizeHuman = cfg.LastSizeHuman
|
||||
switch cfg.LastStatus {
|
||||
case "ok":
|
||||
row.Tier2StatusBadge = "Sikeres"
|
||||
row.Status = "green"
|
||||
row.StatusText = "Mentés rendben"
|
||||
case "error":
|
||||
row.Tier2StatusBadge = "Hiba"
|
||||
// Status stays yellow
|
||||
row.StatusText = "Utolsó mentés sikertelen"
|
||||
case "running":
|
||||
row.Tier2StatusBadge = "Fut..."
|
||||
default:
|
||||
row.Tier2StatusBadge = "—"
|
||||
// Tier2 configured but never run — stay yellow
|
||||
}
|
||||
|
||||
// Destination health check — can downgrade green to yellow/red
|
||||
if cfg.DestinationPath != "" {
|
||||
if err := s.crossDriveRunner.ValidateDestination(cfg.DestinationPath); err != nil {
|
||||
if strings.Contains(err.Error(), "does not exist") || strings.Contains(err.Error(), "not writable") {
|
||||
row.Status = "red"
|
||||
row.StatusText = "Mentési cél nem elérhető"
|
||||
} else if row.Status != "red" {
|
||||
row.Status = "yellow"
|
||||
row.StatusText = "Figyelmeztetés"
|
||||
}
|
||||
row.Warnings = append(row.Warnings, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note: `s.crossDriveRunner` is used instead of `s.crossDrive` — verify the field name
|
||||
in `server.go` and use whatever the actual field is called. (The current code at the
|
||||
old line 657 shows `s.crossDriveRunner.ValidateDestination`.)
|
||||
|
||||
### 2c: Remove HasHDDData gate from cross-drive summary builder
|
||||
|
||||
In `backupsHandler`, the cross-drive summary loop (around line 409) has:
|
||||
|
||||
```go
|
||||
for _, app := range fullStatus.AppDataInfo {
|
||||
if !app.HasHDDData {
|
||||
continue
|
||||
}
|
||||
```
|
||||
|
||||
**Remove** the `if !app.HasHDDData { continue }` — all apps participate in cross-drive summary.
|
||||
|
||||
### 2d: Update the top-level warning logic
|
||||
|
||||
The "NoUserDataBackupWarning" check (around line 473) uses `HasHDDData` — **keep this as-is**.
|
||||
This warning is specifically about user data (photos, documents) being at risk, which only
|
||||
applies to HDD apps. The status dot change already incentivizes Tier 2 for all apps.
|
||||
**Where:**
|
||||
- `dashboard.html`: The temperature is in the `.system-info-item` for "HŐMÉRSÉKLET". Ensure the value part (`{{fmtTemp ...}}°C`) has a dedicated class for styling.
|
||||
- `style.css`: Add/modify the temperature display class. Consider a colored background pill like: `background: rgba(35,134,54,0.15); padding: 2px 8px; border-radius: 4px;` (with color varying by temp status). The dot should be ~10-12px instead of 8px.
|
||||
|
||||
---
|
||||
|
||||
## Fix 3: Update backup page template
|
||||
## Fix 4: Rework dashboard backup section — remove button, show compact info + warnings
|
||||
|
||||
**File:** `internal/web/templates/backups.html`
|
||||
**Problem:** After the backup architecture overhaul, having a "Mentés most" button on the dashboard is unnecessary — backups run automatically on schedule. The dashboard should show a compact status summary with potential warnings, linking to the detailed backup page for settings and manual triggers.
|
||||
|
||||
### 3a: Remove HasHDDData gate on Tier 2 row
|
||||
**Solution:** Replace the current backup card content with a compact summary:
|
||||
- **Status line:** "Utolsó mentés:" + timestamp (colored green if recent, yellow if >24h old, red if >48h or failed) — keep this
|
||||
- **DB line:** "Adatbázisok:" + count — keep this
|
||||
- **NEW — Tier 2 status line:** Show count of apps with Tier 2 configured vs total deployed apps. E.g., "2. mentés: 3 / 5 alkalmazás". If zero configured, show a yellow warning: "⚠ Nincs 2. mentés beállítva"
|
||||
- **NEW — Warnings:** If any cross-drive backup has failed status, show a compact red warning line
|
||||
- **Remove** the "Mentés most" button entirely
|
||||
- **Remove** the "Tároló méret" line (that detail belongs on the backup page)
|
||||
- The card title "Biztonsági mentés" should remain a clickable link to `/backups`
|
||||
|
||||
**Find** (around line 284):
|
||||
```html
|
||||
{{if .HasHDDData}}
|
||||
<div class="backup-layer-row">
|
||||
<span class="tier-label">2. mentés</span>
|
||||
```
|
||||
|
||||
**Remove** the `{{if .HasHDDData}}` opening and its matching `{{end}}` (around line 313).
|
||||
The Tier 2 row should always be shown for all apps.
|
||||
|
||||
### 3b: Update header meta badges
|
||||
|
||||
**Find** (around line 256–261):
|
||||
```html
|
||||
{{if .HasHDDData}}
|
||||
{{if .StorageLabel}}<span class="meta-badge meta-badge-storage">{{.StorageLabel}}</span>{{end}}
|
||||
<span class="mono app-backup-size" style="font-size:.8rem">{{.HDDSizeHuman}}</span>
|
||||
{{else}}
|
||||
<span class="meta-badge">Auto</span>
|
||||
{{end}}
|
||||
```
|
||||
|
||||
**Replace with:**
|
||||
```html
|
||||
{{if .HasHDDData}}
|
||||
{{if .StorageLabel}}<span class="meta-badge meta-badge-storage">{{.StorageLabel}}</span>{{end}}
|
||||
<span class="mono app-backup-size" style="font-size:.8rem">{{.HDDSizeHuman}}</span>
|
||||
{{else}}
|
||||
<span class="meta-badge">Konfig{{if .HasDB}} + DB{{end}}</span>
|
||||
{{end}}
|
||||
```
|
||||
|
||||
This shows what type of data the app has (instead of meaningless "Auto").
|
||||
|
||||
### 3c: Add Tier 3 placeholder row
|
||||
|
||||
After the Tier 2 `</div>` (the closing div of the tier-2 backup-layer-row), add:
|
||||
|
||||
```html
|
||||
<!-- Tier 3: Remote backup (future) -->
|
||||
<div class="backup-layer-row" style="opacity:.5">
|
||||
<span class="tier-label">3. mentés</span>
|
||||
<span class="layer-badge" style="background:var(--bg-tertiary);color:var(--text-muted)">Hamarosan</span>
|
||||
<span class="tier-location">távoli (offsite)</span>
|
||||
<span class="tier-contents" style="font-style:normal;color:var(--text-muted)">B2 / S3 / SFTP — hamarosan elérhető</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 3d: Update "Run all" button text
|
||||
|
||||
**Find** (around line 328):
|
||||
```html
|
||||
<button class="btn btn-sm btn-outline" onclick="triggerAllCrossDrive(this)">Összes HDD mentés futtatása most</button>
|
||||
```
|
||||
|
||||
**Replace with:**
|
||||
```html
|
||||
<button class="btn btn-sm btn-outline" onclick="triggerAllCrossDrive(this)">Összes 2. mentés futtatása most</button>
|
||||
```
|
||||
**Where:**
|
||||
- `dashboard.html`: Modify the `.backup-status-card` content. Remove `triggerBackup()` JS function and the button. Add Tier 2 summary line.
|
||||
- `handlers.go` (`dashboardHandler`): Add data for Tier 2 summary. You can derive this from the cross-drive configs: count apps with `Enabled: true` in their cross-drive settings, and count those with last status "ok" vs "error". Pass something like `CrossDriveTotal`, `CrossDriveConfigured`, `CrossDriveOK`, `CrossDriveFailed` to the template.
|
||||
- `style.css`: Minor adjustments if needed for the warning line styling.
|
||||
|
||||
---
|
||||
|
||||
## Fix 4: Deploy page — show cross-drive config for all deployed apps
|
||||
## Fix 5: HDD warning banner — only on Vezérlőpult and Rendszermonitor
|
||||
|
||||
**File:** `internal/web/templates/deploy.html`
|
||||
**Problem:** The yellow "Az adattároló nem külön meghajtón van" warning banner appears on ALL pages via `layout.html`. This is overkill for pages like Alkalmazások or Beállítások, and it cannot be dismissed.
|
||||
|
||||
### 4a: Remove StorageInfo gate from cross-drive section
|
||||
**Solution:** Show this specific warning only on the Vezérlőpult (dashboard) and Rendszermonitor (monitoring) pages, positioned under the system drive usage bar rather than at the very top.
|
||||
|
||||
The cross-drive backup config section is currently double-gated (lines 95–220):
|
||||
**Implementation approach:**
|
||||
|
||||
The alert system already supports filtering via `GetAlerts(excludeIDs ...string)`. The disk/HDD-related warnings come from `report.Warnings` and get hashed IDs like `"health-XXXXXXXX"`.
|
||||
|
||||
1. In `alerts.go` `Refresh()`: Tag disk-related warnings with a stable, recognizable ID prefix. When generating alerts from `report.Warnings`, check if the warning text contains HDD/disk keywords (like "adattároló", "meghajtó", "nem külön meghajtón") and give those a stable ID like `"disk-not-separate"` instead of the hash-based `"health-XXXXXXXX"`.
|
||||
2. Also add a `PageOnly []string` field to the `Alert` struct so the layout can conditionally render them.
|
||||
|
||||
**Recommended approach:** Add a `PageOnly []string` field to `Alert`. In `Refresh()`, set `PageOnly: []string{"dashboard", "monitoring"}` for disk warnings. In `layout.html`, wrap each alert render with a page check:
|
||||
|
||||
```html
|
||||
{{if .AlreadyDeployed}}
|
||||
{{if .StorageInfo}} ← THIS IS THE GATE — remove it
|
||||
<div class="deploy-cross-drive">
|
||||
...
|
||||
</div>
|
||||
{{end}} ← remove matching end
|
||||
{{end}}
|
||||
{{range .Alerts}}
|
||||
{{if or (not .PageOnly) (pageMatch .PageOnly $.Page)}}
|
||||
<div class="alert-banner alert-banner-{{.Level}}">...</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
```
|
||||
|
||||
**Change to** (keep only the AlreadyDeployed gate):
|
||||
Add a `pageMatch` template function in `funcmap.go` that checks if a string is in a slice. The `.Page` value is already set by `baseData()`.
|
||||
|
||||
```html
|
||||
{{if .AlreadyDeployed}}
|
||||
<div class="deploy-cross-drive">
|
||||
...
|
||||
</div>
|
||||
{{end}}
|
||||
```
|
||||
|
||||
### 4b: Update section text for generality
|
||||
|
||||
**Find** (line 109):
|
||||
```html
|
||||
<p style="font-weight:500;margin-bottom:1rem">Másolat másik meghajtóra (felhasználói adatok):</p>
|
||||
```
|
||||
|
||||
**Replace with:**
|
||||
```html
|
||||
<p style="font-weight:500;margin-bottom:1rem">2. mentés — másolat másik meghajtóra:</p>
|
||||
```
|
||||
|
||||
**Find** (line 214–216):
|
||||
```html
|
||||
<div class="form-hint" style="margin-top:.75rem;color:var(--text-muted)">
|
||||
A cél meghajtó legyen más fizikai eszköz, mint az alkalmazás adattárolója.
|
||||
</div>
|
||||
```
|
||||
|
||||
**Replace with:**
|
||||
```html
|
||||
<div class="form-hint" style="margin-top:.75rem;color:var(--text-muted)">
|
||||
A cél meghajtó legyen más fizikai eszköz a meghibásodás elleni védelem érdekében.
|
||||
</div>
|
||||
```
|
||||
**Where:**
|
||||
- `alerts.go`: Add `PageOnly []string` to `Alert` struct. In `Refresh()`, set `PageOnly: []string{"dashboard", "monitoring"}` for disk-related warnings (detect by checking if the warning message contains "meghajtó" or "adattároló" keywords, or better: use a dedicated health-check category if available).
|
||||
- `layout.html`: Add the `pageMatch` filter around alert rendering.
|
||||
- `funcmap.go`: Add `"pageMatch"` template function.
|
||||
|
||||
---
|
||||
|
||||
## Summary of all changes
|
||||
## Fix 6: Move Tárhely section higher on Rendszermonitor page
|
||||
|
||||
| Fix | What | File(s) |
|
||||
|-----|------|---------|
|
||||
| 1 | Remove `len(mounts) == 0` error gate | `crossdrive.go` |
|
||||
| 2a | Update `AppBackupRow` Tier2 comment | `handlers.go` |
|
||||
| 2b | Rewrite status + Tier2 block (remove HasHDDData gate, new dot logic) | `handlers.go` |
|
||||
| 2c | Remove HasHDDData gate from cross-drive summary | `handlers.go` |
|
||||
| 3a | Remove `{{if .HasHDDData}}` around Tier 2 row | `backups.html` |
|
||||
| 3b | Update meta badges ("Auto" → "Konfig + DB") | `backups.html` |
|
||||
| 3c | Add Tier 3 placeholder row | `backups.html` |
|
||||
| 3d | Rename "Összes HDD mentés" → "Összes 2. mentés" | `backups.html` |
|
||||
| 4a | Remove `{{if .StorageInfo}}` gate from cross-drive section | `deploy.html` |
|
||||
| 4b | Update cross-drive section text for generality | `deploy.html` |
|
||||
**Problem:** The storage (Tárhely) section is the very last section on the monitoring page, below all CPU/memory/temperature charts. Storage is basic system info that should be visible without scrolling past graphs.
|
||||
|
||||
## Files to modify (4)
|
||||
**Solution:** Move the Tárhely section to be right after "Rendszer áttekintés" — before "Távoli monitoring" and before all the charts.
|
||||
|
||||
1. `internal/backup/crossdrive.go` — Fix 1
|
||||
2. `internal/web/handlers.go` — Fix 2a + 2b + 2c
|
||||
3. `internal/web/templates/backups.html` — Fix 3a + 3b + 3c + 3d
|
||||
4. `internal/web/templates/deploy.html` — Fix 4a + 4b
|
||||
**Where:**
|
||||
- `monitoring.html`: Cut the entire `<!-- Section 5: Storage -->` block (the `.monitor-card` with `<h3>Tárhely</h3>`) and paste it right after the "Rendszer áttekintés" section (the first `.monitor-card`), before "Távoli monitoring".
|
||||
|
||||
## Status dot logic after fix
|
||||
---
|
||||
|
||||
| Dot color | Meaning |
|
||||
|-----------|---------|
|
||||
| Green | 2+ tiers with successful backups + destination healthy |
|
||||
| Yellow | Only 1 tier, or Tier 2 failing, or Tier 2 configured but never run |
|
||||
| Red | Tier 2 destination blocked/inaccessible |
|
||||
## Fix 7: Snapshot table — show 0 instead of "-", add clarity to column headers
|
||||
|
||||
**"auto" (gray) is removed.** Every app now shows yellow or better.
|
||||
**Problem:** In the Pillanatképek table on the backup page, all detail columns (Méret, Új fájl, Változott) show "–" (dash) which reads as "not available" or "unknown". If there's genuinely no change, it should show `0`.
|
||||
|
||||
## Architecture after fix
|
||||
Also, "Méret" is ambiguous — is it total snapshot size or incremental size (data added)?
|
||||
|
||||
```
|
||||
Per-app Tier 2 availability:
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ App type │ Tier 1 │ Tier 2 (new) │
|
||||
│───────────────────│───────────────────│──────────────────│
|
||||
│ HDD + DB │ Config+DB+Data │ Config+DB+Data │
|
||||
│ HDD, no DB │ Config+Data │ Config+Data │
|
||||
│ DB, no HDD │ Config+DB │ Config+DB (new!) │
|
||||
│ Config only │ Config │ Config (new!) │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
**Solution:**
|
||||
- Rename column headers for clarity:
|
||||
- "MÉRET" → "HOZZÁADOTT" (data added by this snapshot), or keep "MÉRET" but add "(új adat)" subtitle
|
||||
- Add a tooltip or subtitle to make meaning clear
|
||||
- Show `0` instead of `–` for zero values. Show `–` only when the data is truly unavailable (nil/missing from restic output).
|
||||
- For "Új fájl" and "Változott": show `0` when the count is zero, not `–`.
|
||||
|
||||
UI per-app display after fix:
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 🟢 Immich Külső tárhely (hdd_1) 63.9 MB │
|
||||
│ 1. mentés Auto helyi 02-18 03:00 ✓ DB+Konfig+Adatok │
|
||||
│ 2. mentés rsync → hdd_1 Naponta Sikeres 📁 │
|
||||
│ 3. mentés Hamarosan távoli (offsite) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 🟡 Mealie Konfig + DB │
|
||||
│ 1. mentés Auto helyi 02-18 03:00 ✓ DB+Konfig │
|
||||
│ 2. mentés ✓ 1. mentés auto ⚠ Nincs 2. másolat │
|
||||
│ 3. mentés Hamarosan távoli (offsite) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 🟡 Gokapi Konfig │
|
||||
│ 1. mentés Auto helyi 02-18 03:00 ✓ Konfig │
|
||||
│ 2. mentés ⚠ Nincs 2. másolat [Beállítás →] │
|
||||
│ 3. mentés Hamarosan távoli (offsite) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
**Where:**
|
||||
- `backups.html`: Update the Pillanatképek table headers and cell rendering logic.
|
||||
- Check the `Snapshot` struct in the backup package and how it's populated — the fields for size/files_new/files_changed may already exist but are zero-valued, or they may be genuinely absent from the restic output.
|
||||
- If restic's `snapshots` command doesn't provide per-snapshot stats (it doesn't — you need `restic stats` or `restic diff`), document this limitation clearly. At minimum:
|
||||
- Change `–` to `0` for fields that have a zero value (not nil/missing)
|
||||
- Keep `–` only for genuinely unavailable data
|
||||
- Update column header for clarity
|
||||
|
||||
## Post-fix checklist
|
||||
**Note on restic data:** `restic snapshots --json` returns hostname, paths, time, tags, tree hash — but NOT size/files stats. Getting per-snapshot size requires `restic stats <snapshot-id>` (expensive per snapshot). Consider:
|
||||
- Running `restic stats latest` during the nightly backup and caching the result
|
||||
- Or accepting that individual snapshot sizes aren't available and removing the misleading columns
|
||||
- At minimum, make the display honest: if data isn't collected, show "n/a" with a tooltip explaining why, rather than `–`
|
||||
|
||||
- [ ] `go build ./...` passes
|
||||
- [ ] `go vet ./...` passes
|
||||
- [ ] Verify no references to old "auto" status remain in handlers.go
|
||||
- [ ] Verify no template references to removed `{{if .HasHDDData}}` gate on Tier 2
|
||||
- [ ] Update `CHANGELOG.md` — session 46, version **v0.12.9**:
|
||||
- Tier 2 cross-drive backup now configurable for ALL apps (not just HDD apps)
|
||||
- Non-HDD apps back up config + DB dumps to secondary drive
|
||||
- Status dot: removed "auto" (gray) — all apps start yellow, green requires 2+ tiers
|
||||
- Tier 3 placeholder row shown in UI
|
||||
- Deploy page: cross-drive config form visible for all deployed apps
|
||||
- Updated button text "Összes 2. mentés futtatása most"
|
||||
- [ ] Commit, build on 192.168.0.180, deploy on 192.168.0.162
|
||||
- [ ] Verify with `docker ps` and `docker logs`
|
||||
- [ ] After deploy, verify:
|
||||
- Immich: green dot (Tier 2 configured + successful backup)
|
||||
- Mealie: yellow dot with "Csak helyi mentés (1 szint)"
|
||||
- Mealie: Tier 2 row shown with "⚠ Nincs 2. másolat" + "Beállítás →" link
|
||||
- Mealie deploy page: cross-drive config form visible
|
||||
- Configure Tier 2 for Mealie → run manual backup → verify dot turns green
|
||||
- Tier 3 placeholder row shown for all apps (grayed out "Hamarosan")
|
||||
- Gokapi: yellow dot, Tier 2 configurable
|
||||
---
|
||||
|
||||
## Fix 8: Tároló section — show all backup storage locations
|
||||
|
||||
**Problem:** The Tároló section at the bottom of the Biztonsági mentés page only shows a single restic repository path (`/srv/backups/restic-repo`). With the new tiered backup architecture, backups are saved to multiple locations:
|
||||
- **Tier 1 (restic):** `/srv/backups/restic-repo` (SSD, local)
|
||||
- **Tier 2 (cross-drive):** rsync/restic to secondary drive (e.g., `/mnt/hdd_1/backups/rsync/`)
|
||||
- **DB dumps:** `/srv/backups/db-dumps/`
|
||||
|
||||
Also, `/srv/` is the Filebrowser root, not the actual host path. If showing the Filebrowser-accessible path, label it clearly.
|
||||
|
||||
**Solution:** Restructure the Tároló section into subsections per storage tier:
|
||||
|
||||
1. **1. mentés — Helyi mentés (restic):**
|
||||
- Path: the restic repo path (current display)
|
||||
- Size, snapshot count, integrity (current display)
|
||||
- Encryption key (current display)
|
||||
- Backed-up paths list (current display)
|
||||
|
||||
2. **2. mentés — Másodlagos másolat:** (only shown if any app has Tier 2 configured)
|
||||
- Destination path(s) — from cross-drive configs (may be multiple if different apps target different drives)
|
||||
- Method per destination (rsync or restic)
|
||||
- Total size per destination (if calculable via `du -sh`)
|
||||
|
||||
3. **Adatbázis mentések:**
|
||||
- Path: DB dump directory
|
||||
- File count and total size from `DumpFiles` data already available in the handler
|
||||
|
||||
4. **Mentett útvonalak:** Keep the current list but restructure:
|
||||
- Group by what's in Tier 1 (restic paths) vs what's additionally in Tier 2
|
||||
- Make it clear these are the source paths being backed up, not the backup destinations
|
||||
|
||||
**Where:**
|
||||
- `backups.html`: Restructure the `.repo-card` section. Split into subsections with clear tier headings. Keep the restic key/password display under Tier 1.
|
||||
- `handlers.go` (`backupsHandler`): Pass additional template data:
|
||||
- Cross-drive destination paths and their stats (from `CrossDriveSummary` which is already computed)
|
||||
- DB dump directory path and stats (path is in `cfg.Paths.DBDumpDir`, file count/size from `DumpFiles`)
|
||||
- Deduplicated list of Tier 2 destinations across all apps
|
||||
|
||||
---
|
||||
|
||||
## Implementation order (suggested)
|
||||
|
||||
These fixes are independent. Suggested grouping by complexity:
|
||||
|
||||
**Quick (template/CSS only):**
|
||||
1. Fix 1 — backup card border
|
||||
2. Fix 3 — temperature visibility
|
||||
3. Fix 6 — move Tárhely section
|
||||
|
||||
**Medium (template + minor handler):**
|
||||
4. Fix 7 — snapshot table display
|
||||
5. Fix 5 — warning banner scope
|
||||
|
||||
**Larger (template + handler logic):**
|
||||
6. Fix 2 — show auto-generated env values
|
||||
7. Fix 4 — dashboard backup section rework
|
||||
8. Fix 8 — Tároló section restructure
|
||||
|
||||
## Build & deploy
|
||||
|
||||
After all fixes, bump version to **v0.13.0**, then follow the standard build workflow in `CLAUDE.md`:
|
||||
1. `git add -A && git commit && git push`
|
||||
2. Build on 192.168.0.180
|
||||
3. Deploy on 192.168.0.162
|
||||
4. Verify
|
||||
|
||||
Update `CHANGELOG.md`, `CONTEXT.md`, and `controller/README.md` at the end.
|
||||
|
||||
Reference in New Issue
Block a user