Change : Backup pick

This commit is contained in:
2026-06-21 00:20:37 +01:00
parent c3e3a3b28c
commit bf9c4a01b2
3 changed files with 219 additions and 24 deletions

View File

@@ -113,11 +113,48 @@
</div>
</div>
<div class="form-section">
<div class="form-section-title">STEP 3 — SELECT APPS TO RESTORE</div>
<p style="color:var(--text3); font-size:12px; margin-bottom:10px;">
All apps are restored by default. Uncheck the ones you don't want touched —
only the checked apps will be restored, and they're force-restored even if
currently running and healthy.
</p>
<div id="apps-checkbox-group" style="display:flex; flex-wrap:wrap; gap:8px;">
<label class="radio-card small" style="cursor:pointer;">
<input type="checkbox" value="frappe" checked style="margin-right:6px;">
<span>🧾 Frappe / ERPNext</span>
</label>
<label class="radio-card small" style="cursor:pointer;">
<input type="checkbox" value="odoo" checked style="margin-right:6px;">
<span>🟣 Odoo</span>
</label>
<label class="radio-card small" style="cursor:pointer;">
<input type="checkbox" value="nextcloud" checked style="margin-right:6px;">
<span>☁️ Nextcloud</span>
</label>
<label class="radio-card small" style="cursor:pointer;">
<input type="checkbox" value="mautic" checked style="margin-right:6px;">
<span>📣 Mautic</span>
</label>
<label class="radio-card small" style="cursor:pointer;">
<input type="checkbox" value="n8n" checked style="margin-right:6px;">
<span>🔁 n8n</span>
</label>
</div>
<div style="margin-top:10px; display:flex; gap:8px;">
<button type="button" class="btn btn-sm" onclick="nvSetAllApps(true)">Select All</button>
<button type="button" class="btn btn-sm" onclick="nvSetAllApps(false)">Select None</button>
</div>
</div>
<div class="form-section">
<button class="btn btn-danger btn-lg" onclick="nvLaunchRestore()" id="restore-btn">
<i class="fas fa-play"></i> Start Restore
</button>
<p style="color:var(--text3); font-size:12px; margin-top:8px;">⚠ Healthy running containers are skipped.</p>
<p style="color:var(--text3); font-size:12px; margin-top:8px;" id="restore-warning-text">
⚠ Full restore (all apps checked): healthy running containers are skipped.
</p>
</div>
</div>
@@ -182,11 +219,48 @@ function nvGetSelection() {
return { source, file, key };
}
// ── App selection (Step 3) ────────────────────────────────────────────────────
function nvGetAppsCheckboxes() {
return Array.from(document.querySelectorAll('#apps-checkbox-group input[type="checkbox"]'));
}
// Returns [] when every app is checked (= full restore, no filter needed),
// otherwise returns the list of explicitly checked app keys.
function nvGetSelectedApps() {
const boxes = nvGetAppsCheckboxes();
const checked = boxes.filter(b => b.checked).map(b => b.value);
return checked.length === boxes.length ? [] : checked;
}
function nvSetAllApps(state) {
nvGetAppsCheckboxes().forEach(b => b.checked = state);
nvUpdateRestoreWarning();
}
function nvUpdateRestoreWarning() {
const selected = nvGetSelectedApps();
const el = document.getElementById('restore-warning-text');
if (selected.length === 0) {
el.textContent = '⚠ Full restore (all apps checked): healthy running containers are skipped.';
} else {
el.textContent = `⚠ Selective restore: only ${selected.join(', ')} will be touched — forced even if currently healthy.`;
}
}
document.addEventListener('change', (e) => {
if (e.target.closest('#apps-checkbox-group')) nvUpdateRestoreWarning();
});
// ── Launch restore ────────────────────────────────────────────────────────────
async function nvLaunchRestore() {
const { source, file, key } = nvGetSelection();
if (!file) { alert('Please select a backup file.'); return; }
const appsCheckboxes = nvGetAppsCheckboxes();
const checkedCount = appsCheckboxes.filter(b => b.checked).length;
if (checkedCount === 0) { alert('Select at least one app to restore.'); return; }
const selectedApps = nvGetSelectedApps();
const target = document.querySelector('input[name="restore_target"]:checked')?.value || 'local';
const authMethod = document.querySelector('input[name="auth_method"]:checked')?.value || 'key';
@@ -194,6 +268,7 @@ async function nvLaunchRestore() {
backup_source: source,
backup_file: file,
cloud_key: key,
apps: selectedApps,
target,
remote_ip: document.getElementById('remote-ip')?.value || '',
remote_port: document.getElementById('remote-port')?.value || '22',
@@ -211,9 +286,12 @@ async function nvLaunchRestore() {
btn.disabled = true;
wrapper.style.display = '';
const scopeMsg = selectedApps.length
? `🎯 Restoring only: ${selectedApps.join(', ')}`
: '🚀 Starting full restore…';
logEl.innerHTML = source === 'cloud'
? '<div style="color:var(--accent2)">☁️ Downloading backup from R2, please wait…</div>'
: '<div style="color:var(--accent2)">🚀 Starting restore…</div>';
? `<div style="color:var(--accent2)">☁️ Downloading backup from R2, please wait…</div><div style="color:var(--accent2)">${scopeMsg}</div>`
: `<div style="color:var(--accent2)">${scopeMsg}</div>`;
badge.textContent = 'Running…';
badge.style.cssText = 'background:rgba(59,130,246,0.15);color:var(--accent2);';