Part A: shared app_list_row partial — ONE row grammar on four surfaces (v0.126.0)

- templates/app_row.html: app_list_row/app_list_row_end (layout_start/_end idiom) — icon+name
  (+optional secondary) left, caller action block right; compact 44px row; logoURL→PNG→
  optional FallbackIcon→hidden onerror chain
- applied: Távoli mentés toggle list, Visszaállítás restore-to-verify + .fab lists, dashboard
  Telepített alkalmazások (state edge + data-href preserved); Alkalmazások collapsed headers
  ALIGNED (icon+name left, status dot moved right before chevron; expander untouched)
- funcmap: dict + appHref; OffboxAppRow/AppBackupRow gain Slug
- style.css: .app-row family; stack-card/stack-info/stack-logo/stack-name/stack-desc/
  stack-actions rules retired (dashboard rows now shared); .app-backup-row-header matched
  to the shared row height
- scripts/app_row_dedup_gate.py: row markup single-sourced (red-proven: pasted old
  storage-path-item block → exit 1); render tests per surface (app_row_test.go)
- NO behavior change: toggle/download/expander actions byte-identical
This commit is contained in:
2026-07-13 11:26:48 +02:00
parent 7b3e7f2e71
commit 3eacb6c326
11 changed files with 380 additions and 87 deletions
@@ -66,20 +66,15 @@
<h3>Ellenőrző visszaállítás a távoli tárolóból</h3>
<p class="form-hint" style="margin:-0.25rem 0 1rem">A távoli mentésre kijelölt alkalmazások legutóbbi pillanatképe egy külön ellenőrző mappába állítható vissza — a meglévő adatok nem változnak.</p>
{{if .OffboxToggledCount}}
<div class="storage-paths-list">
<div class="app-row-list">
{{range .OffboxApps}}
{{if .Enabled}}
<div class="storage-path-item">
<div class="storage-path-header">
<div class="storage-path-info"><span class="storage-path-label">{{.DisplayName}}</span></div>
<div class="storage-path-actions">
<form method="POST" action="/backup/offbox/restore" style="display:inline">{{$.CSRFField}}
<input type="hidden" name="app" value="{{.Name}}">
<button type="submit" class="btn btn-xs btn-outline" data-confirm="Visszaállítja a(z) {{.DisplayName}} adatait a távoli tárolóról egy ellenőrző mappába? A meglévő adatok NEM íródnak felül.">Visszaállítás (ellenőrzéshez)</button>
</form>
</div>
</div>
</div>
{{template "app_list_row" dict "Slug" .Slug "Name" .DisplayName}}
<form method="POST" action="/backup/offbox/restore" style="display:inline">{{$.CSRFField}}
<input type="hidden" name="app" value="{{.Name}}">
<button type="submit" class="btn btn-xs btn-outline" data-confirm="Visszaállítja a(z) {{.DisplayName}} adatait a távoli tárolóról egy ellenőrző mappába? A meglévő adatok NEM íródnak felül.">Visszaállítás (ellenőrzéshez)</button>
</form>
{{template "app_list_row_end"}}
{{end}}
{{end}}
</div>
@@ -101,16 +96,11 @@
<div class="form-row" style="max-width:420px"><label>Jelszavas titkosítás (opcionális)</label>
<input type="password" id="fab-dl-password" class="form-input" autocomplete="new-password" placeholder="Üresen hagyva a csomag titkosítatlan">
</div>
<div class="storage-paths-list">
<div class="app-row-list">
{{range .OffboxApps}}
<div class="storage-path-item">
<div class="storage-path-header">
<div class="storage-path-info"><span class="storage-path-label">{{.DisplayName}}</span></div>
<div class="storage-path-actions">
<button type="button" class="btn btn-xs btn-outline fab-dl-btn" data-stack="{{.Name}}" onclick="fabDownload(this)">Letöltés (.fab)</button>
</div>
</div>
</div>
{{template "app_list_row" dict "Slug" .Slug "Name" .DisplayName}}
<button type="button" class="btn btn-xs btn-outline fab-dl-btn" data-stack="{{.Name}}" onclick="fabDownload(this)">Letöltés (.fab)</button>
{{template "app_list_row_end"}}
{{end}}
</div>
<div class="schedule-actions" style="margin-top:.75rem">