Report failures where the operator can still see them
The 55 alert() calls carried the same suppression as the confirms, and go wrong in the worse direction: a silenced confirm makes a button do nothing, while a silenced alert lets the action run and says nothing about it failing. vvAlert returns a promise nobody has to await, so these converted by rename with no caller becoming async. The icon is inferred from the message rather than asked of fifty call sites, and an explicit type still wins.
This commit is contained in:
@@ -147,7 +147,19 @@ function vvConfirm(text, opts) {
|
||||
}
|
||||
|
||||
// Telling the operator something, with no question attached. Returns a promise so a caller can
|
||||
// sequence on it, but nothing has to await it.
|
||||
// sequence on it, but nothing has to await it — which is what let the fifty-odd alert() sites
|
||||
// become this by rename alone, with no function above them turning async.
|
||||
//
|
||||
// The icon is read off the message when the caller does not say. Almost every one of these
|
||||
// reports a failure — "Save failed: …", "Error: …" — and asking fifty call sites to each classify
|
||||
// themselves would mean fifty chances to disagree about what counts as an error. The caller can
|
||||
// still pass type explicitly and that always wins.
|
||||
function vvAlertType(text) {
|
||||
const s = String(text ?? '');
|
||||
if (/\b(fail|failed|error|denied|invalid|refused|cannot|could not|unable)\b/i.test(s)) return 'error';
|
||||
if (/\b(warn|warning|already|must be)\b/i.test(s)) return 'warning';
|
||||
return 'info';
|
||||
}
|
||||
function vvAlert(text, opts) {
|
||||
const o = opts || {};
|
||||
return new Promise(function (resolve) {
|
||||
@@ -155,7 +167,7 @@ function vvAlert(text, opts) {
|
||||
swal({
|
||||
title: o.title || '',
|
||||
text: String(text ?? ''),
|
||||
type: o.type || 'info',
|
||||
type: o.type || vvAlertType(text),
|
||||
confirmButtonText: o.confirmText || 'OK',
|
||||
}, function (ok) { resolve(true); });
|
||||
});
|
||||
|
||||
@@ -649,7 +649,7 @@ function _addToGroupModal(uid) {
|
||||
const user = _users.find(u => u.id === uid);
|
||||
const userGids= new Set((user?.groups||[]).map(g => g.id));
|
||||
const available = _groups.filter(g => !userGids.has(g.id));
|
||||
if (!available.length) { alert('User is already in all groups.'); return; }
|
||||
if (!available.length) { vvAlert('User is already in all groups.'); return; }
|
||||
const opts = available.map(g => `<option value="${g.id}">${_esc(g.displayName)}</option>`).join('');
|
||||
_modal(`<h3>Add to Group</h3>
|
||||
<div class="vv-au-field">
|
||||
@@ -936,7 +936,7 @@ document.getElementById('vv-au-panel-acl').addEventListener('click', async e =>
|
||||
btn.disabled = true; btn.textContent = 'Saving…';
|
||||
_post({ action:'authelia_save', rules: JSON.stringify(_rules), default_policy: dp }, r => {
|
||||
btn.disabled = false; btn.textContent = 'Save & Restart Authelia';
|
||||
if (!r.ok) { alert('Save failed: ' + (r.error||'unknown error')); return; }
|
||||
if (!r.ok) { vvAlert('Save failed: ' + (r.error||'unknown error')); return; }
|
||||
// brief visual confirmation
|
||||
btn.textContent = 'Saved ✓';
|
||||
setTimeout(() => { btn.textContent = 'Save & Restart Authelia'; }, 2000);
|
||||
|
||||
@@ -369,7 +369,7 @@ function _doRestart(name) {
|
||||
function _doStartStop(name, start) {
|
||||
_actApi({action: start ? 'start' : 'stop', name}, data => {
|
||||
if (data.ok) setTimeout(_reload, 800);
|
||||
else alert((start ? 'Start' : 'Stop') + ' failed: ' + (data.output || data.error || '?'));
|
||||
else vvAlert((start ? 'Start' : 'Stop') + ' failed: ' + (data.output || data.error || '?'));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -378,7 +378,7 @@ function _doPullRebuild(name) {
|
||||
if (data.ok && data.job_id) {
|
||||
_startJob(name, data.job_id);
|
||||
} else {
|
||||
alert('Update failed: ' + (data.error || '?'));
|
||||
vvAlert('Update failed: ' + (data.error || '?'));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -478,7 +478,7 @@ function _bindEvents() {
|
||||
el.disabled = true; el.style.opacity = '0.5';
|
||||
_api({action:'rename_folder',folder_id:fid,name}, r => {
|
||||
el.disabled = false; el.style.opacity = '';
|
||||
if (r.ok) _reload(); else { alert('Rename failed: '+(r.error||'?')); el.value = f?.name ?? name; }
|
||||
if (r.ok) _reload(); else { vvAlert('Rename failed: '+(r.error||'?')); el.value = f?.name ?? name; }
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -490,14 +490,14 @@ function _bindEvents() {
|
||||
const fid = el.dataset.deleteFolder;
|
||||
const f = (_data.folders||[]).find(x=>x.id===fid);
|
||||
if (!f || !await vvConfirm(`Delete "${f.name}"? Containers will be ungrouped.`)) return;
|
||||
_api({action:'delete_folder',folder_id:fid}, r => { if(r.ok) _reload(); else alert('Delete failed: '+(r.error||'?')); });
|
||||
_api({action:'delete_folder',folder_id:fid}, r => { if(r.ok) _reload(); else vvAlert('Delete failed: '+(r.error||'?')); });
|
||||
});
|
||||
});
|
||||
|
||||
// New folder
|
||||
document.getElementById('vv-dk-add-folder')?.addEventListener('click', async () => {
|
||||
const name = await vvPrompt('New folder name:');
|
||||
if (name?.trim()) _api({action:'create_folder',name:name.trim()}, r => { if(r.ok) _reload(); else alert(r.error); });
|
||||
if (name?.trim()) _api({action:'create_folder',name:name.trim()}, r => { if(r.ok) _reload(); else vvAlert(r.error); });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -527,11 +527,11 @@ function _showPopover(x, y) {
|
||||
const name = await vvPrompt('New folder name:');
|
||||
if (!name?.trim()) return;
|
||||
_api({action:'create_folder',name:name.trim()}, r => {
|
||||
if (!r.ok) { alert(r.error); return; }
|
||||
if (!r.ok) { vvAlert(r.error); return; }
|
||||
_api({action:'move_container',container:_popTarget.container,folder_id:r.id}, r2 => { if(r2.ok) _reload(); });
|
||||
});
|
||||
} else {
|
||||
_api({action:'move_container',container:_popTarget.container,folder_id:fid}, r => { if(r.ok) _reload(); else alert(r.error); });
|
||||
_api({action:'move_container',container:_popTarget.container,folder_id:fid}, r => { if(r.ok) _reload(); else vvAlert(r.error); });
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -555,12 +555,12 @@ document.getElementById('vv-dk-edit-toggle').addEventListener('click', function(
|
||||
});
|
||||
|
||||
function _syncC2J() {
|
||||
_api({action:'sync_conf_to_json'}, r => { if(r.ok) _reload(); else alert(r.error); });
|
||||
_api({action:'sync_conf_to_json'}, r => { if(r.ok) _reload(); else vvAlert(r.error); });
|
||||
}
|
||||
document.getElementById('vv-dk-sync-c2j').addEventListener('click', _syncC2J);
|
||||
document.getElementById('vv-dk-sync-j2c').addEventListener('click', async () => {
|
||||
if (!await vvConfirm('Overwrite conf map with current JSON state?')) return;
|
||||
_api({action:'sync_json_to_conf'}, r => { if(r.ok) _reload(); else alert(r.error); });
|
||||
_api({action:'sync_json_to_conf'}, r => { if(r.ok) _reload(); else vvAlert(r.error); });
|
||||
});
|
||||
|
||||
// ── Load ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -2636,14 +2636,14 @@ async function vvDockerAction(action, name, webui) {
|
||||
// The endpoint reports refusals as ok:false with a reason — container not found, a non-zero
|
||||
// docker exit. Discarding that made a failed stop look exactly like a successful one, since
|
||||
// the card it would have changed is redrawn from a payload either way.
|
||||
if (!d || !d.ok) alert('Container ' + action + ' failed: ' + ((d && (d.error || d.output)) || 'unknown error'));
|
||||
if (!d || !d.ok) vvAlert('Container ' + action + ' failed: ' + ((d && (d.error || d.output)) || 'unknown error'));
|
||||
vvDfActive = null;
|
||||
// The endpoint drops the monitor cache on success, and this poll asks for a live collection
|
||||
// besides — either alone is enough, but between them the card cannot redraw itself from a
|
||||
// payload assembled before the action happened.
|
||||
setTimeout(() => vvPollMonitor(true), 1500);
|
||||
})
|
||||
.catch(() => alert('Container ' + action + ' failed: request error'));
|
||||
.catch(() => vvAlert('Container ' + action + ' failed: request error'));
|
||||
}
|
||||
|
||||
function vvRenderDockerFolders(data) {
|
||||
|
||||
@@ -215,12 +215,12 @@ function vvApiKey(btn) {
|
||||
if (d.ok) {
|
||||
if (_vvPtReload) _vvPtReload();
|
||||
} else {
|
||||
alert('Failed: ' + (d.error ?? 'Unknown error'));
|
||||
vvAlert('Failed: ' + (d.error ?? 'Unknown error'));
|
||||
btn.disabled = false; btn.textContent = origText;
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
alert('Error: ' + e);
|
||||
vvAlert('Error: ' + e);
|
||||
btn.disabled = false; btn.textContent = origText;
|
||||
});
|
||||
}
|
||||
@@ -230,8 +230,8 @@ async function vvPtPhase2(btn, hostId) {
|
||||
btn.disabled = true;
|
||||
btn.textContent = '⟳ Starting…';
|
||||
_vvPtRun('Partnership/partnership_onboard.sh', '--phase2-only')
|
||||
.then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => alert('Error: ' + e))
|
||||
.then(d => { if (!d.ok) vvAlert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => vvAlert('Error: ' + e))
|
||||
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Run Phase 2 Manually'; }, 3000));
|
||||
}
|
||||
|
||||
@@ -240,8 +240,8 @@ async function vvPtOnboard(btn) {
|
||||
btn.disabled = true;
|
||||
btn.textContent = '⟳ Starting…';
|
||||
_vvPtRun('Partnership/partnership_onboard.sh')
|
||||
.then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => alert('Error: ' + e))
|
||||
.then(d => { if (!d.ok) vvAlert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => vvAlert('Error: ' + e))
|
||||
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Onboard (Mirror)'; }, 4000));
|
||||
}
|
||||
|
||||
@@ -250,8 +250,8 @@ async function vvPtPushConf(btn, hostId) {
|
||||
btn.disabled = true;
|
||||
btn.textContent = '⟳ Pushing…';
|
||||
_vvPtRun('Partnership/partnership_onboard.sh', '--phase1-only --skip-ssh')
|
||||
.then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => alert('Error: ' + e))
|
||||
.then(d => { if (!d.ok) vvAlert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => vvAlert('Error: ' + e))
|
||||
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Push Conf (key installed)'; }, 4000));
|
||||
}
|
||||
|
||||
@@ -260,8 +260,8 @@ async function vvPtLocalSetup(btn) {
|
||||
btn.disabled = true;
|
||||
btn.textContent = '⟳ Running…';
|
||||
_vvPtRun('Partnership/partnership_manager.sh', '--onboard --local-only')
|
||||
.then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => alert('Error: ' + e))
|
||||
.then(d => { if (!d.ok) vvAlert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => vvAlert('Error: ' + e))
|
||||
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Complete HOST1 Setup'; }, 4000));
|
||||
}
|
||||
|
||||
@@ -270,8 +270,8 @@ async function vvPtCancel(btn, hostId) {
|
||||
btn.disabled = true;
|
||||
btn.textContent = '⟳ Cancelling…';
|
||||
_vvPtRun('Partnership/onboard_cancel.sh', '--direction=both')
|
||||
.then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => alert('Error: ' + e))
|
||||
.then(d => { if (!d.ok) vvAlert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => vvAlert('Error: ' + e))
|
||||
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '✕ Cancel'; }, 4000));
|
||||
}
|
||||
|
||||
@@ -279,8 +279,8 @@ async function vvPtDeleteH1(btn, hostId) {
|
||||
if (!await vvConfirm(`Remove HOST1's key from ${hostId}?\n\n• Deletes local SSH key pair\n• Removes it from ${hostId}'s authorized_keys\n• Clears phase state`)) return;
|
||||
btn.disabled = true; btn.textContent = '⟳ Removing…';
|
||||
_vvPtRun('Partnership/onboard_cancel.sh', '--direction=h1')
|
||||
.then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => alert('Error: ' + e))
|
||||
.then(d => { if (!d.ok) vvAlert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => vvAlert('Error: ' + e))
|
||||
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '✕ Remove HOST1 key'; }, 4000));
|
||||
}
|
||||
|
||||
@@ -288,8 +288,8 @@ async function vvPtDeleteH2(btn, hostId) {
|
||||
if (!await vvConfirm(`Remove ${hostId}'s key from HOST1?\n\n• Removes ${hostId}'s public key from HOST1's authorized_keys\n• ${hostId} will no longer be able to SSH into HOST1`)) return;
|
||||
btn.disabled = true; btn.textContent = '⟳ Removing…';
|
||||
_vvPtRun('Partnership/onboard_cancel.sh', '--direction=h2')
|
||||
.then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => alert('Error: ' + e))
|
||||
.then(d => { if (!d.ok) vvAlert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => vvAlert('Error: ' + e))
|
||||
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = `✕ Remove ${hostId} key`; }, 4000));
|
||||
}
|
||||
|
||||
@@ -299,8 +299,8 @@ async function vvPtOffboard(btn) {
|
||||
btn.disabled = true;
|
||||
btn.textContent = '⟳ Starting…';
|
||||
_vvPtRun('Partnership/partnership_offboard.sh')
|
||||
.then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => alert('Error: ' + e))
|
||||
.then(d => { if (!d.ok) vvAlert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => vvAlert('Error: ' + e))
|
||||
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '▶ Offboard'; }, 4000));
|
||||
}
|
||||
|
||||
@@ -311,8 +311,8 @@ async function vvPtTransfer(btn, token) {
|
||||
btn.disabled = true;
|
||||
btn.textContent = '⟳ Transferring…';
|
||||
_vvPtRun('Partnership/partnership_transfer.sh', '--confirm=' + token)
|
||||
.then(d => { if (!d.ok) alert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => alert('Error: ' + e))
|
||||
.then(d => { if (!d.ok) vvAlert('Failed: ' + (d.error ?? 'Unknown error')); })
|
||||
.catch(e => vvAlert('Error: ' + e))
|
||||
.finally(() => setTimeout(() => { btn.disabled = false; btn.textContent = '⇄ Transfer Ownership'; }, 4000));
|
||||
}
|
||||
|
||||
@@ -349,9 +349,9 @@ function vvPtToggleSync(el, varName, enabled) {
|
||||
.then(r => r.json())
|
||||
.then(d => {
|
||||
if (d.ok) { if (_vvPtReload) _vvPtReload(); }
|
||||
else { alert('Failed: ' + (d.error ?? 'Unknown error')); el.style.pointerEvents = ''; el.style.opacity = ''; }
|
||||
else { vvAlert('Failed: ' + (d.error ?? 'Unknown error')); el.style.pointerEvents = ''; el.style.opacity = ''; }
|
||||
})
|
||||
.catch(e => { alert('Error: ' + e); el.style.pointerEvents = ''; el.style.opacity = ''; });
|
||||
.catch(e => { vvAlert('Error: ' + e); el.style.pointerEvents = ''; el.style.opacity = ''; });
|
||||
}
|
||||
|
||||
// ── Host Settings ─────────────────────────────────────────────────────────────
|
||||
@@ -407,10 +407,10 @@ async function vvPtSaveHosts(btn) {
|
||||
setTimeout(() => { btn.textContent = 'Save'; btn.style.display = 'none'; }, 2000);
|
||||
} else {
|
||||
btn.textContent = 'Save';
|
||||
alert('Save failed: ' + (d.error ?? 'Unknown error'));
|
||||
vvAlert('Save failed: ' + (d.error ?? 'Unknown error'));
|
||||
}
|
||||
})
|
||||
.catch(e => { btn.disabled = false; btn.textContent = 'Save'; alert('Error: ' + e); });
|
||||
.catch(e => { btn.disabled = false; btn.textContent = 'Save'; vvAlert('Error: ' + e); });
|
||||
}
|
||||
|
||||
// ── Array settings cards ───────────────────────────────────────────────────────
|
||||
@@ -507,10 +507,10 @@ async function vvPtSaveArrays(btn) {
|
||||
setTimeout(() => _vvInitArrayCards(), 600);
|
||||
} else {
|
||||
btn.textContent = 'Save Changes';
|
||||
alert('Save failed: ' + (d.error ?? 'Unknown error'));
|
||||
vvAlert('Save failed: ' + (d.error ?? 'Unknown error'));
|
||||
}
|
||||
})
|
||||
.catch(e => { btn.disabled = false; btn.textContent = 'Save Changes'; alert('Error: ' + e); });
|
||||
.catch(e => { btn.disabled = false; btn.textContent = 'Save Changes'; vvAlert('Error: ' + e); });
|
||||
}
|
||||
|
||||
// ── Settings panel ─────────────────────────────────────────────────────────────
|
||||
@@ -620,10 +620,10 @@ async function vvPtSaveSettings(btn) {
|
||||
setTimeout(() => { btn.textContent = 'Save Changes'; btn.style.display = 'none'; }, 2000);
|
||||
} else {
|
||||
btn.textContent = 'Save Changes';
|
||||
alert('Save failed: ' + (d.error ?? 'Unknown error'));
|
||||
vvAlert('Save failed: ' + (d.error ?? 'Unknown error'));
|
||||
}
|
||||
})
|
||||
.catch(e => { btn.disabled = false; btn.textContent = 'Save Changes'; alert('Error: ' + e); });
|
||||
.catch(e => { btn.disabled = false; btn.textContent = 'Save Changes'; vvAlert('Error: ' + e); });
|
||||
}
|
||||
|
||||
// ── Private page logic ─────────────────────────────────────────────────────────
|
||||
|
||||
@@ -1755,9 +1755,9 @@ function vvMsRun() {
|
||||
const flags = Array.from(document.querySelectorAll('#vv-ms-card input[data-flag]:checked'))
|
||||
.map(el => el.dataset.flag).join(' ');
|
||||
|
||||
if (!local) { alert('Enter a local source path.'); return; }
|
||||
if (!slot) { alert('Select a remote server.'); return; }
|
||||
if (!rpath) { alert('Enter a remote destination path.'); return; }
|
||||
if (!local) { vvAlert('Enter a local source path.'); return; }
|
||||
if (!slot) { vvAlert('Select a remote server.'); return; }
|
||||
if (!rpath) { vvAlert('Enter a remote destination path.'); return; }
|
||||
|
||||
const btn = document.getElementById('vv-ms-run-btn');
|
||||
const stat = document.getElementById('vv-ms-run-status');
|
||||
|
||||
@@ -1917,7 +1917,7 @@ async function vvSaveScript() {
|
||||
const name = document.getElementById('vv-editor-name').value.trim();
|
||||
const content = document.getElementById('vv-editor-body').value;
|
||||
if (!name || !/^[a-zA-Z0-9_\-]+$/.test(name)) {
|
||||
alert('Name must be letters, numbers, _ or - only (no spaces, no .sh)');
|
||||
vvAlert('Name must be letters, numbers, _ or - only (no spaces, no .sh)');
|
||||
return;
|
||||
}
|
||||
if (!await vvConfirm('Save changes to "' + name + '.sh"?')) return;
|
||||
@@ -1926,7 +1926,7 @@ async function vvSaveScript() {
|
||||
btn.textContent = 'Saving…';
|
||||
vvPost('/plugins/varaverk/api/script.php', {name, content})
|
||||
.then(d => {
|
||||
if (!d.ok) { alert('Save failed: ' + (d.error ?? 'Unknown error')); btn.disabled = false; btn.textContent = 'Save Script'; return; }
|
||||
if (!d.ok) { vvAlert('Save failed: ' + (d.error ?? 'Unknown error')); btn.disabled = false; btn.textContent = 'Save Script'; return; }
|
||||
localStorage.setItem('vv-last-job', d.id);
|
||||
window.location.reload();
|
||||
})
|
||||
@@ -1942,7 +1942,7 @@ async function vvDeleteScript() {
|
||||
btn.textContent = 'Deleting…';
|
||||
vvPost('/plugins/varaverk/api/script.php', {action: 'delete', name})
|
||||
.then(d => {
|
||||
if (!d.ok) { alert('Delete failed: ' + (d.error ?? 'Unknown error')); btn.disabled = false; btn.textContent = '\u{1F5D1} Delete'; return; }
|
||||
if (!d.ok) { vvAlert('Delete failed: ' + (d.error ?? 'Unknown error')); btn.disabled = false; btn.textContent = '\u{1F5D1} Delete'; return; }
|
||||
localStorage.removeItem('vv-last-job');
|
||||
window.location.reload();
|
||||
})
|
||||
@@ -2119,16 +2119,16 @@ async function _vvImpDoImport() {
|
||||
vvPost('/plugins/varaverk/api/import_script.php', {action: 'import', path: _vvImpSelected})
|
||||
.then(d => {
|
||||
if (!d.ok) {
|
||||
alert('Import failed: ' + (d.error || 'Unknown error'));
|
||||
vvAlert('Import failed: ' + (d.error || 'Unknown error'));
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'Import';
|
||||
return;
|
||||
}
|
||||
if (d.warning) alert(d.warning);
|
||||
if (d.warning) vvAlert(d.warning);
|
||||
window.location.reload();
|
||||
})
|
||||
.catch(e => {
|
||||
alert('Import failed: ' + e);
|
||||
vvAlert('Import failed: ' + e);
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'Import';
|
||||
});
|
||||
@@ -2270,7 +2270,7 @@ async function vvSaveConf() {
|
||||
setTimeout(() => { btn.textContent = 'Save Config'; }, 2500);
|
||||
} else {
|
||||
btn.textContent = 'Save Config';
|
||||
alert('Save failed: ' + (d.error ?? 'Unknown error'));
|
||||
vvAlert('Save failed: ' + (d.error ?? 'Unknown error'));
|
||||
}
|
||||
})
|
||||
.catch(() => { btn.disabled = false; btn.textContent = 'Save Config'; });
|
||||
@@ -3503,7 +3503,7 @@ async function vvSaveRawConf() {
|
||||
btn.disabled = false;
|
||||
if (!d.ok) {
|
||||
btn.textContent = 'Save Conf';
|
||||
alert('Save failed: ' + (d.error ?? 'Unknown error'));
|
||||
vvAlert('Save failed: ' + (d.error ?? 'Unknown error'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4772,7 +4772,7 @@ async function _vvFolderDrop(e) {
|
||||
|
||||
if (!r.ok) {
|
||||
oldParent.appendChild(srcEl);
|
||||
alert('Failed to save folder assignment.');
|
||||
vvAlert('Failed to save folder assignment.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4921,12 +4921,12 @@ function vvNewFolder() {
|
||||
async function _vvDoCreateFolder(name, wrap) {
|
||||
if (!name) return;
|
||||
const folders = vvGetCurrentFolders();
|
||||
if (folders[name] !== undefined) { alert(`Folder "${name}" already exists.`); return; }
|
||||
if (folders[name] !== undefined) { vvAlert(`Folder "${name}" already exists.`); return; }
|
||||
folders[name] = [];
|
||||
const r = await vvPost('/plugins/varaverk/api/savefolders.php', {
|
||||
folders: JSON.stringify(folders)
|
||||
}).then(r => r.json()).catch(() => ({ ok: false }));
|
||||
if (!r.ok) { alert('Failed to create folder.'); return; }
|
||||
if (!r.ok) { vvAlert('Failed to create folder.'); return; }
|
||||
wrap.remove();
|
||||
// Add folder group to DOM
|
||||
const customChildren = document.getElementById('vv-custom-children');
|
||||
|
||||
Reference in New Issue
Block a user