ui: toast per-type durations, Details modal for long errors, concise acme.sh failure summary
This commit is contained in:
@@ -3,10 +3,38 @@
|
||||
*
|
||||
* ToastContainer component that renders queued toast notifications.
|
||||
* Uses the toast/dismissToast state from api.js.
|
||||
*
|
||||
* Long messages (>200 chars or containing newlines) render compact —
|
||||
* first line with an ellipsis — plus a "Details" button that opens a
|
||||
* modal with the full text. Dismissal is only via the × button;
|
||||
* hovering the toast pauses its auto-dismiss timer.
|
||||
*/
|
||||
|
||||
import { h } from '../vdom.js';
|
||||
import { _toasts, dismissToast } from '../api.js';
|
||||
import { openModal } from './modal.js';
|
||||
|
||||
/** Messages longer than this (or containing newlines) render compact. */
|
||||
const _LONG_MESSAGE_CHARS = 200;
|
||||
|
||||
function _isLong(message) {
|
||||
return message.length > _LONG_MESSAGE_CHARS || message.includes('\n');
|
||||
}
|
||||
|
||||
function _firstLine(message) {
|
||||
return message.split('\n')[0].trim();
|
||||
}
|
||||
|
||||
function _showDetails(t) {
|
||||
openModal(
|
||||
h('div', null,
|
||||
h('h2', { class: 'modal-title' }, 'Details'),
|
||||
h('div', { class: 'modal-body' },
|
||||
h('pre', { class: 'toast-details-msg' }, t.message),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render all pending toast notifications.
|
||||
@@ -24,19 +52,26 @@ export function ToastContainer() {
|
||||
};
|
||||
|
||||
return h('div', { class: 'toast' },
|
||||
..._toasts.map(t =>
|
||||
h('div', {
|
||||
..._toasts.map(t => {
|
||||
const long = _isLong(t.message);
|
||||
return h('div', {
|
||||
class: `toast-message ${clsMap[t.type] || clsMap.info}`,
|
||||
'on:click': () => dismissToast(t.id),
|
||||
'on:mouseover': () => { t.hovered = true; },
|
||||
'on:mouseout': () => { t.hovered = false; },
|
||||
},
|
||||
h('span', { class: 'toast-text' }, t.message),
|
||||
h('span', { class: 'toast-text' + (long ? ' toast-text-long' : '') },
|
||||
long ? _firstLine(t.message) : t.message),
|
||||
h('div', { class: 'toast-actions' },
|
||||
long ? h('button', {
|
||||
class: 'toast-btn toast-details',
|
||||
'on:click': (e) => { e.stopPropagation(); _showDetails(t); },
|
||||
}, 'Details') : null,
|
||||
h('button', {
|
||||
class: 'toast-btn toast-close',
|
||||
'on:click': (e) => { e.stopPropagation(); dismissToast(t.id); },
|
||||
}, '\u00d7'),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user