dashboard: theme all remaining dialogs (replace native confirm/alert/prompt)
Follow-up to the themed-modal component: route every remaining native browser dialog through modal.js so nothing falls back to the OS chrome. - modal.js: add themedPrompt (input dialog) + themedToast (non-blocking transient notification, info/error/ok) alongside openDialog/themedConfirm. - Migrate call sites: bindAsyncForms confirm/prompt/alerts (common.js), the answer-validation alert (call.js), the M0V3 reparent confirm + action toasts (tabs.js), and the schedule form/cancel/fire confirms + validation and error alerts (schedules.js). - UX: blocking modal for confirms/prompts; non-blocking toast for transient errors + validation. Destructive confirms keep the danger styling. - CSS for the toast stack + prompt input. common.js <-> modal.js is a safe deferred import cycle (usage is call-time only); esbuild bundles it clean.
This commit is contained in:
parent
ff3317eb20
commit
7c2de690ec
6 changed files with 141 additions and 32 deletions
|
|
@ -18,7 +18,7 @@ import {
|
|||
makePathLink, appendText, appendLinkified,
|
||||
openStream, renderServerWarnings, bindAsyncForms,
|
||||
} from './common.js';
|
||||
import { themedConfirm } from './modal.js';
|
||||
import { themedConfirm, themedToast } from './modal.js';
|
||||
import { createTabStrip } from '@hive/shared/tabs.js';
|
||||
import {
|
||||
containersState, syncContainersFromSnapshot,
|
||||
|
|
@ -295,10 +295,10 @@ window.marked = marked;
|
|||
|| (resp.status >= 200 && resp.status < 400);
|
||||
if (!ok) {
|
||||
const text = await resp.text().catch(() => '');
|
||||
alert('action failed: ' + resp.status + (text ? '\n\n' + text : ''));
|
||||
themedToast('action failed: ' + resp.status + (text ? '\n\n' + text : ''), { type: 'error' });
|
||||
}
|
||||
} catch (err) {
|
||||
alert('action failed: ' + err);
|
||||
themedToast('action failed: ' + err, { type: 'error' });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1056,7 +1056,7 @@ window.marked = marked;
|
|||
const promptMsg = names.length === 1
|
||||
? `move ${names[0]} → ${newParentLabel}?`
|
||||
: `move ${names.length} agents (${names.join(', ')}) → ${newParentLabel}?`;
|
||||
if (!confirm(promptMsg)) {
|
||||
if (!(await themedConfirm({ message: promptMsg, danger: true }))) {
|
||||
sel.selectedIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1105,7 +1105,7 @@ window.marked = marked;
|
|||
sel.disabled = false;
|
||||
sel.selectedIndex = 0;
|
||||
if (failures.length) {
|
||||
alert(`M0V3 completed with ${failures.length} failure${failures.length === 1 ? '' : 's'}:\n\n` + failures.join('\n'));
|
||||
themedToast(`M0V3 completed with ${failures.length} failure${failures.length === 1 ? '' : 's'}:\n\n` + failures.join('\n'), { type: 'error' });
|
||||
}
|
||||
});
|
||||
wrap.append(sel);
|
||||
|
|
@ -1216,7 +1216,7 @@ window.marked = marked;
|
|||
btn.disabled = false;
|
||||
btn.innerHTML = original;
|
||||
if (failures.length) {
|
||||
alert(`${label} completed with ${failures.length} failure${failures.length === 1 ? '' : 's'}:\n\n` + failures.join('\n'));
|
||||
themedToast(`${label} completed with ${failures.length} failure${failures.length === 1 ? '' : 's'}:\n\n` + failures.join('\n'), { type: 'error' });
|
||||
}
|
||||
// Container-lifecycle events (ContainerStateChanged /
|
||||
// ContainerRemoved / RebuildQueueChanged) flow over the existing
|
||||
|
|
|
|||
Loading…
Reference in a new issue