Fix relative-time error and improve global error handler (#37241)
1. Fixes: #37239 2. Enhance global error message to show stack trace on click --------- Signed-off-by: silverwind <me@silverwind.io> Signed-off-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -6,25 +6,36 @@ export function errorMessage(err: unknown): string {
|
||||
return (err as Error)?.message || String(err);
|
||||
}
|
||||
|
||||
export function showGlobalErrorMessage(msg: string, msgType: Intent = 'error') {
|
||||
const msgContainer = document.querySelector('.page-content') ?? document.body;
|
||||
if (!msgContainer) {
|
||||
export function showGlobalErrorMessage(msg: string, msgType: Intent = 'error', details?: string) {
|
||||
const parentContainer = document.querySelector('.page-content') ?? document.body;
|
||||
if (!parentContainer) {
|
||||
alert(`${msgType}: ${msg}`);
|
||||
return;
|
||||
}
|
||||
const msgCompact = msg.replace(/\W/g, '').trim(); // compact the message to a data attribute to avoid too many duplicated messages
|
||||
let msgDiv = msgContainer.querySelector<HTMLDivElement>(`.js-global-error[data-global-error-msg-compact="${msgCompact}"]`);
|
||||
if (!msgDiv) {
|
||||
// compact the message to a data attribute to avoid too many duplicated messages
|
||||
const msgCompact = `${msgType}-${msg.trim()}`.replace(/[^-\w\u{80}-\u{10FFFF}]+/gu, '');
|
||||
let msgContainer = parentContainer.querySelector<HTMLDivElement>(`.js-global-error[data-global-error-msg-compact="${msgCompact}"]`);
|
||||
if (!msgContainer) {
|
||||
const el = document.createElement('div');
|
||||
el.innerHTML = html`<div class="ui container js-global-error tw-my-[--page-spacing]"><div class="ui ${msgType} message tw-text-center tw-whitespace-pre-line"></div></div>`;
|
||||
msgDiv = el.childNodes[0] as HTMLDivElement;
|
||||
el.innerHTML = html`<div class="ui container js-global-error tw-my-[--page-spacing]"><details class="ui ${msgType} message"><summary></summary></details></div>`;
|
||||
msgContainer = el.childNodes[0] as HTMLDivElement;
|
||||
}
|
||||
|
||||
// merge duplicated messages into "the message (count)" format
|
||||
const msgCount = Number(msgDiv.getAttribute(`data-global-error-msg-count`)) + 1;
|
||||
msgDiv.setAttribute(`data-global-error-msg-compact`, msgCompact);
|
||||
msgDiv.setAttribute(`data-global-error-msg-count`, msgCount.toString());
|
||||
msgDiv.querySelector('.ui.message')!.textContent = msg + (msgCount > 1 ? ` (${msgCount})` : '');
|
||||
msgContainer.prepend(msgDiv);
|
||||
const msgCount = Number(msgContainer.getAttribute(`data-global-error-msg-count`)) + 1;
|
||||
msgContainer.setAttribute(`data-global-error-msg-compact`, msgCompact);
|
||||
msgContainer.setAttribute(`data-global-error-msg-count`, msgCount.toString());
|
||||
|
||||
const msgElem = msgContainer.querySelector('details')!;
|
||||
const msgSummary = msgElem.querySelector('summary')!;
|
||||
msgSummary.textContent = msg + (msgCount > 1 ? ` (${msgCount})` : '');
|
||||
if (details) {
|
||||
let msgDetailsPre = msgElem.querySelector('pre');
|
||||
if (!msgDetailsPre) msgDetailsPre = document.createElement('pre');
|
||||
msgDetailsPre.textContent = details;
|
||||
msgElem.append(msgDetailsPre);
|
||||
}
|
||||
parentContainer.prepend(msgContainer);
|
||||
}
|
||||
|
||||
// Detect whether an error originated from Gitea's own scripts, not from
|
||||
@@ -53,9 +64,9 @@ export function processWindowErrorEvent({error, reason, message, type, filename,
|
||||
// Filter out errors from browser extensions or other non-Gitea scripts.
|
||||
if (!isGiteaError(filename ?? '', err?.stack ?? '')) return;
|
||||
|
||||
let msg = err?.message ?? message;
|
||||
if (lineno) msg += ` (${filename} @ ${lineno}:${colno})`;
|
||||
const dot = msg.endsWith('.') ? '' : '.';
|
||||
const renderedType = type === 'unhandledrejection' ? 'promise rejection' : type;
|
||||
showGlobalErrorMessage(`JavaScript ${renderedType}: ${msg}${dot} Open browser console to see more details.`);
|
||||
let msg = err?.message ?? message;
|
||||
if (!err?.stack && lineno) msg += ` (${filename} @ ${lineno}:${colno})`;
|
||||
const dot = msg.endsWith('.') ? '' : '.';
|
||||
showGlobalErrorMessage(`JavaScript ${renderedType}: ${msg}${dot} Open browser console to see more details.`, 'error', err?.stack);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user