11b790e314
gates / gates (push) Successful in 20s
Seven backup pages + the restore-progress JS converted against fixtures captured unconverted
(f8ebc47); recovery renders through executeTemplateLang; English retrieval claims registered;
the Fut comparison left unconverted (R-563).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
180 lines
10 KiB
HTML
180 lines
10 KiB
HTML
{{define "backups_restore_wizard"}}
|
|
{{template "layout_start" .}}
|
|
|
|
<!-- R-48: the offsite restore wizard. One entry per app on /backups/restore leads here, and the
|
|
three intents are separately-described CARDS with a consequence sentence each — never sibling
|
|
buttons whose difference is whether the data comes back. Server-rendered throughout: every step
|
|
is a real form POST to the EXISTING endpoint, so the page works with JavaScript disabled. -->
|
|
|
|
<div class="page-header">
|
|
<div style="display:flex;align-items:center;gap:.5rem">
|
|
<a href="/backups/restore" class="btn btn-sm btn-outline">{{T "backups_restore_wizard.vissza"}}</a>
|
|
<h2>{{T "backups_restore_wizard.visszaallitas"}}</h2>
|
|
</div>
|
|
<span class="domain-badge">{{.Domain}}</span>
|
|
</div>
|
|
|
|
{{template "backups_flash" .}}
|
|
{{template "restore_banner" .}}
|
|
|
|
<!-- Phase strip: the customer can see there IS a sequence, and where they are in it. The round-2
|
|
incident's second half was that the decisive step appeared only after the first was pressed,
|
|
with nothing signposting that a second step existed at all. -->
|
|
{{$phase := printf "%s" .Wizard.Phase}}
|
|
<div class="restore-wizard-phases">
|
|
<span class="restore-wizard-phase{{if eq $phase "elokeszites"}} is-current{{end}}">{{T "backups_restore_wizard.elokeszites"}}</span>
|
|
<span class="restore-wizard-phase{{if eq $phase "megerosites"}} is-current{{end}}">{{T "backups_restore_wizard.megerosites"}}</span>
|
|
<span class="restore-wizard-phase{{if eq $phase "vegrehajtas"}} is-current{{end}}">{{T "backups_restore_wizard.vegrehajtas"}}</span>
|
|
<span class="restore-wizard-phase{{if eq $phase "eredmeny"}} is-current{{end}}">{{T "backups_restore_wizard.eredmeny"}}</span>
|
|
</div>
|
|
|
|
{{with .LastResult}}
|
|
<!-- „Eredmény": the outcome of the restore that just finished, for THIS app. The redirect flash says
|
|
the same thing but does not survive a reload; this does, for restoreResultWindow. -->
|
|
<div class="settings-card">
|
|
<h3>{{T "backups_restore_wizard.eredmeny"}}</h3>
|
|
<div class="alert {{if .OK}}alert-info{{else}}alert-error{{end}}">{{.Message}}</div>
|
|
<p class="form-hint">{{if .Interrupted}}{{T "backups_restore_wizard.eszlelve"}}{{else}}{{T "backups_restore_wizard.befejezve"}}{{end}}{{T "backups_restore_wizard.ha_szeretned_alabb_ujra_indithatsz"}}</p>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if eq (printf "%s" .Wizard.Step) "execution"}}
|
|
<!-- EXECUTION — every mutation form is suppressed server-side. The manager's single-flight would
|
|
refuse them anyway; offering a control guaranteed to fail is the same dishonesty class R-48
|
|
addresses. The live progress comes from the existing restore-status poll (the banner above). -->
|
|
<div class="settings-card">
|
|
<h3>{{T "backups_restore_wizard.vegrehajtas"}}</h3>
|
|
<p>{{T "backups_restore_wizard.jelenleg_egy_mentesi_vagy_visszaallitasi"}}{{with .RunningStack}} ({{.}}){{end}}{{T "backups_restore_wizard.amig_ez_tart_uj_visszaallitas"}}</p>
|
|
<!-- R-351: this used to say the state refreshes automatically AND that you must refresh the page
|
|
when it finishes. Both cannot be true, and the second half was the one people believed. The
|
|
banner now carries the terminal result too (RestoreOpStatus.LastRecent), so the sentence can
|
|
describe what the page actually does. -->
|
|
<p class="form-hint">{{T "backups_restore_wizard.az_allapot_fent_automatikusan_frissul"}}</p>
|
|
<div class="form-actions">
|
|
<a href="/backups/restore/app?name={{.App}}" class="btn btn-sm btn-outline">{{T "backups_restore_wizard.allapot_frissitese"}}</a>
|
|
</div>
|
|
</div>
|
|
|
|
{{else if eq (printf "%s" .Wizard.Step) "prepare-confirm"}}
|
|
<!-- MEGERŐSÍTÉS — the size gate. The preparation has measured what needs downloading; the customer
|
|
confirms with the size in front of them, before any transfer starts. -->
|
|
<div class="settings-card">
|
|
<h3>{{T "backups_restore_wizard.megerosites_teljes_visszaallitas_elokesz"}}</h3>
|
|
<p>{{T "backups_restore_wizard.a_teljes_visszaallitashoz_a_mentes"}}{{with .FullPrepSize}} {{T "backups_restore_wizard.a_becsult_meret"}}{{end}}{{T "backups_restore_wizard.a_letoltes_a_meghajton_egy"}}</p>
|
|
<p class="form-hint">{{T "backups_restore_wizard.a_letoltes_a_merettol_es"}}</p>
|
|
<div class="form-actions">
|
|
<form method="POST" action="/backup/offbox/restore">{{.CSRFField}}
|
|
<input type="hidden" name="app" value="{{.App}}">
|
|
<input type="hidden" name="mode" value="full">
|
|
<input type="hidden" name="confirm" value="1">
|
|
<button type="submit" class="btn btn-primary">{{T "backups_restore_wizard.elokeszites_inditasa"}}{{with .FullPrepSize}} (~{{.}}){{end}}</button>
|
|
</form>
|
|
<a href="/backups/restore/app?name={{.App}}" class="btn btn-outline">{{T "backups_restore_wizard.megsem"}}</a>
|
|
</div>
|
|
</div>
|
|
|
|
{{else}}
|
|
<!-- INTENT — three cards, each with its own consequence sentence. Card order is deliberate:
|
|
harmless first, irreversible-looking last. -->
|
|
|
|
<div class="settings-card">
|
|
<h3>{{T "backups_restore_wizard.1_ellenorzes_kulon_mappaba_beallitasok"}}</h3>
|
|
<!-- R-204 item 3: this card's scope is stated BEFORE the choice, not only in the outcome. It
|
|
restores the recovery unit only; the customer's own files stay in the backup. Saying „a
|
|
mentés tartalma" here was how a disaster-recovery customer chose the one intent that does
|
|
not return their documents. -->
|
|
<p>{{T "backups_restore_wizard.az_alkalmazas_beallitasait_es_adatbazisa"}}</p>
|
|
<div class="form-actions">
|
|
<form method="POST" action="/backup/offbox/restore">{{.CSRFField}}
|
|
<input type="hidden" name="app" value="{{.App}}">
|
|
<input type="hidden" name="mode" value="unit">
|
|
<button type="submit" class="btn btn-outline"{{if not .Wizard.VerifyEnabled}} disabled{{end}}>{{T "backups_restore_wizard.ellenorzes_inditasa"}}</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="settings-card">
|
|
<h3>{{T "backups_restore_wizard.2_hianyzo_fajlok_visszahozasa"}}</h3>
|
|
<p>{{T "backups_restore_wizard.csak_a_hianyzo_fajlokat_masolja"}}</p>
|
|
{{if .Wizard.PlaceEnabled}}
|
|
<div class="form-actions">
|
|
<form method="POST" action="/backup/offbox/place">{{.CSRFField}}
|
|
<input type="hidden" name="app" value="{{.App}}">
|
|
<button type="submit" class="btn btn-outline">{{T "backups_restore_wizard.hianyzo_fajlok_visszahozasa"}}</button>
|
|
</form>
|
|
</div>
|
|
{{else}}
|
|
<p class="form-hint">{{T "backups_restore_wizard.ehhez_elobb_elo_kell_kesziteni"}}</p>
|
|
{{end}}
|
|
</div>
|
|
|
|
<div class="settings-card restore-danger-card">
|
|
<h3>{{T "backups_restore_wizard.3_teljes_visszaallitas_fajlok_adatbazis"}}</h3>
|
|
<p>{{T "backups_restore_wizard.a_fajlokat_a_mentes_szerinti"}}</p>
|
|
|
|
{{if .Wizard.RestoreEnabled}}
|
|
<!-- Pair honesty (R-43): what the two halves of this restore actually ARE. A restore is the one
|
|
operation whose result cannot be inspected before committing to it. -->
|
|
<div class="alert alert-info" style="margin-bottom:.75rem">
|
|
<strong>{{T "backups_restore_wizard.az_elokeszitett_mentes"}}</strong>
|
|
{{if not .Pair.DumpsAt.IsZero}}{{T "backups_restore_wizard.adatbazis_mentes_ideje"}}{{else}}{{T "backups_restore_wizard.az_adatbazis_mentes_ideje_nem"}}{{end}}
|
|
</div>
|
|
{{if .Pair.Skewed}}
|
|
<div class="alert alert-warning" style="margin-bottom:.75rem">{{T "backups_restore_wizard.az_adatbazis_mentes_regebbi"}}{{if not .Pair.DumpsAt.IsZero}} ({{fmtTime .Pair.DumpsAt}}){{end}} {{T "backups_restore_wizard.a_fajlok_es_az_adatbazis"}}</div>
|
|
{{end}}
|
|
{{if .Pair.LooksEmpty}}
|
|
<div class="alert alert-warning" style="margin-bottom:.75rem">{{T "backups_restore_wizard.a_mentett_adatbazis_uresnek_tunik"}}</div>
|
|
{{end}}
|
|
<div class="form-actions">
|
|
<form method="POST" action="/backup/offbox/reconstitute">{{.CSRFField}}
|
|
<input type="hidden" name="app" value="{{.App}}">
|
|
<input type="hidden" name="confirm" value="1">
|
|
<button type="button" class="btn btn-danger"
|
|
data-restore-app="{{.App}}"
|
|
data-restore-when="{{if not .Pair.DumpsAt.IsZero}}{{fmtTime .Pair.DumpsAt}}{{end}}"
|
|
data-restore-skewed="{{if .Pair.Skewed}}1{{end}}"
|
|
data-restore-empty="{{if .Pair.LooksEmpty}}1{{end}}"
|
|
onclick="confirmFullRestore(this)">{{T "backups_restore_wizard.teljes_visszaallitas_inditasa"}}</button>
|
|
</form>
|
|
</div>
|
|
{{else}}
|
|
<p class="form-hint">{{T "backups_restore_wizard.a_teljes_visszaallitashoz_eloszor_le"}}</p>
|
|
<div class="form-actions">
|
|
<form method="POST" action="/backup/offbox/restore">{{.CSRFField}}
|
|
<input type="hidden" name="app" value="{{.App}}">
|
|
<input type="hidden" name="mode" value="full">
|
|
<button type="submit" class="btn btn-outline"{{if not .Wizard.PrepareEnabled}} disabled{{end}}>{{T "backups_restore_wizard.teljes_visszaallitas_elokeszitese"}}</button>
|
|
</form>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
|
|
<script>
|
|
{{template "restore_banner_js"}}
|
|
|
|
/* Carried VERBATIM from backups_restore.html (R-43). The double-confirm is the good part of the old
|
|
surface — it states the DB half's age and any warning before the customer commits — so it moves
|
|
with the action rather than being rewritten. felhomConfirm is the house inline idiom, never the
|
|
OS-modal confirm() (F-11). */
|
|
function confirmFullRestore(btn){
|
|
var app = btn.getAttribute('data-restore-app') || '';
|
|
var when = btn.getAttribute('data-restore-when') || '';
|
|
var skewed = btn.getAttribute('data-restore-skewed') === '1';
|
|
var empty = btn.getAttribute('data-restore-empty') === '1';
|
|
var q = '{{T "backups_restore_wizard.teljes_visszaallitas"}} ' + app + (when ? ' {{T "backups_restore_wizard.a_mentes_ideje"}} ' + when : '') + '.';
|
|
if (skewed) { q += ' {{T "backups_restore_wizard.figyelem_a_fajlok_es_az"}}'; }
|
|
if (empty) { q += ' {{T "backups_restore_wizard.figyelem_a_mentett_adatbazis_uresnek"}}'; }
|
|
q += ' {{T "backups_restore_wizard.a_fajlok_a_mentes_szerinti"}}';
|
|
felhomConfirm(btn, q, function(){
|
|
felhomConfirm(btn, '{{T "backups_restore_wizard.utolso_megerosites_az_alkalmazas_leall"}}', function(){
|
|
var f = btn.closest('form');
|
|
if (f) { if (f.requestSubmit) f.requestSubmit(); else f.submit(); }
|
|
});
|
|
});
|
|
}
|
|
</script>
|
|
|
|
{{template "layout_end" .}}
|
|
{{end}}
|