controller: backups IA split — four sub-pages (Áttekintés /backups, Távoli mentés /backups/remote, Alkalmazások /backups/apps, Visszaállítás /backups/restore); sections MOVED verbatim (backups_split_move_check.py enforces vs df7ad37); shared data builder extracted; offbox restore-to-verify relocated to the restore page; flash redirects + tier-3 anchors + tier2 back-link retargeted

Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
This commit is contained in:
2026-07-13 09:35:01 +02:00
parent df7ad378f4
commit 0ece2ba85c
13 changed files with 1093 additions and 733 deletions
@@ -191,12 +191,18 @@ func (u *unitProvider) GetStackComposePath(string) (string, bool) { return "comp
// ---------------------------------------------------------------------------
func renderBackups(t *testing.T, data map[string]interface{}) string {
return renderBackupPage(t, "backups", data)
}
// renderBackupPage renders one of the four backups sub-page templates (v0.124.0 IA split)
// through the PRODUCTION template tree.
func renderBackupPage(t *testing.T, page string, data map[string]interface{}) string {
t.Helper()
s := testServer(t)
s.loadTemplates()
var buf bytes.Buffer
if err := s.tmpl.ExecuteTemplate(&buf, "backups", data); err != nil {
t.Fatalf("render backups: %v", err)
if err := s.tmpl.ExecuteTemplate(&buf, page, data); err != nil {
t.Fatalf("render %s: %v", page, err)
}
return buf.String()
}
@@ -227,7 +233,7 @@ func TestBackupsTemplate_Tier3Live(t *testing.T) {
LastRun: "2026-07-11T02:00:00Z", EscrowState: "escrowed",
}
data["OffboxConfigured"] = true
html := renderBackups(t, data)
html := renderBackupPage(t, "backups_apps", data)
for _, want := range []string{
"Sikeres", // active badge (LastStatus ok)
@@ -235,11 +241,19 @@ func TestBackupsTemplate_Tier3Live(t *testing.T) {
"Utolsó:", // a relative last-run time is shown
"Kikapcsolva", // radarr off row
"Bekapcsolás", // radarr enable link
`href="#offbox-section"`, // the anchor jump target
"Távoli mentés (3. mentés)", // the renamed section header
`href="/backups/remote#offbox-section"`, // the cross-page anchor jump target (IA split)
} {
if !strings.Contains(html, want) {
t.Errorf("rendered page missing %q", want)
t.Errorf("rendered apps page missing %q", want)
}
}
remoteHTML := renderBackupPage(t, "backups_remote", data)
for _, want := range []string{
"Távoli mentés (3. mentés)", // the renamed section header
`id="offbox-section"`, // the anchor target the apps-page links jump to
} {
if !strings.Contains(remoteHTML, want) {
t.Errorf("rendered remote page missing %q", want)
}
}
for _, banned := range []string{
@@ -267,7 +281,7 @@ func TestBackupsTemplate_Tier3EscrowPending(t *testing.T) {
})
data["Offbox"] = &settings.OffboxTarget{Enabled: true, Host: "nas.local", LastStatus: "ok", EscrowState: "pending"}
data["OffboxConfigured"] = true
html := renderBackups(t, data)
html := renderBackupPage(t, "backups_apps", data)
if !strings.Contains(html, "Kulcsletétre vár") {
t.Error("escrow-pending row must show 'Kulcsletétre vár'")
@@ -285,23 +299,22 @@ func TestBackupsTemplate_DBMessaging(t *testing.T) {
t.Run("embedded", func(t *testing.T) {
data := baseBackupData(nil)
data["DBSectionState"] = "embedded"
html := renderBackups(t, data)
for _, want := range []string{
"beágyazott DB-k a kötetmentésben", // stat-card sublabel
"beágyazott adatbázist használnak", // Adatbázisok empty-state explanation
} {
if !strings.Contains(html, want) {
t.Errorf("embedded page missing %q", want)
}
overviewHTML := renderBackups(t, data)
if !strings.Contains(overviewHTML, "beágyazott DB-k a kötetmentésben") { // stat-card sublabel
t.Error("embedded overview page missing the stat-card sublabel")
}
if strings.Contains(html, "Nem található adatbázis mentés.") {
appsHTML := renderBackupPage(t, "backups_apps", data)
if !strings.Contains(appsHTML, "beágyazott adatbázist használnak") { // Adatbázisok empty state
t.Error("embedded apps page missing the Adatbázisok explanation")
}
if strings.Contains(appsHTML, "Nem található adatbázis mentés.") {
t.Error("embedded box must NOT show the old bare 'not found' message")
}
})
t.Run("pending", func(t *testing.T) {
data := baseBackupData(nil)
data["DBSectionState"] = "pending"
html := renderBackups(t, data)
html := renderBackupPage(t, "backups_apps", data)
if !strings.Contains(html, "az első ütemezett mentés éjjel fut le") {
t.Error("pending page missing the 'first run tonight' message")
}
@@ -320,7 +333,7 @@ func TestBackupsTemplate_Tier2RelativeTime(t *testing.T) {
Tier2LastRun: "2026-07-10T03:30:00Z", Tier2LastStatus: "ok", Tier2StatusBadge: "Sikeres",
Tier3State: "unconfigured",
}})
html := renderBackups(t, data)
html := renderBackupPage(t, "backups_apps", data)
// The visible "Utolsó:" label must be a relative time, never the raw RFC3339. (The raw
// timestamp legitimately survives in the restore confirm() dialog — precise there by design.)
if strings.Contains(html, "Utolsó: 2026-07-10T03:30:00Z") {