Skip to content

Commit 819a859

Browse files
committed
Add "View details" dialog for long notifications
1 parent f34af06 commit 819a859

3 files changed

Lines changed: 90 additions & 1 deletion

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { Notification, showDialog, Dialog } from '@jupyterlab/apputils';
2+
import { Widget } from '@lumino/widgets';
3+
4+
const MAX_VISIBLE_CHARS = 140;
5+
const VIEW_DETAILS_LABEL = 'View details';
6+
7+
function toPlainText(value: unknown): string {
8+
try {
9+
return typeof value === 'string' ? value : JSON.stringify(value, null, 2);
10+
} catch {
11+
return String(value ?? '');
12+
}
13+
}
14+
15+
function createViewDetailsAction(fullMessage: string, dialogTitle = 'Details'): Notification.IAction {
16+
return {
17+
label: VIEW_DETAILS_LABEL,
18+
caption: 'Show full message',
19+
callback: async () => {
20+
const dialogBody = new Widget();
21+
dialogBody.addClass('xircuits-notification-details');
22+
23+
const pre = document.createElement('pre');
24+
pre.textContent = fullMessage;
25+
dialogBody.node.appendChild(pre);
26+
27+
const copyButton = Dialog.createButton({ label: 'Copy' });
28+
const closeButton = Dialog.okButton({ label: 'Close' });
29+
30+
const result = await showDialog({
31+
title: dialogTitle,
32+
body: dialogBody,
33+
buttons: [copyButton, closeButton]
34+
});
35+
36+
if (result.button.label === 'Copy') {
37+
await navigator.clipboard.writeText(fullMessage);
38+
}
39+
}
40+
};
41+
}
42+
43+
function ensureViewDetailsAction(
44+
messageText: string,
45+
options: any = {},
46+
title?: string
47+
): any {
48+
if (messageText.length <= MAX_VISIBLE_CHARS) return options;
49+
const actions = [...(options.actions ?? [])];
50+
if (!actions.some((a: any) => a?.label === VIEW_DETAILS_LABEL)) {
51+
actions.push(createViewDetailsAction(messageText, title));
52+
}
53+
return { ...options, actions };
54+
}
55+
56+
export function augmentNotifications(): void {
57+
const NotificationObj: any = Notification as any;
58+
if (NotificationObj.__xircuitsAugmented) return;
59+
60+
const wrap = (method: 'error' | 'warning' | 'info' | 'success') => {
61+
const original = NotificationObj[method]?.bind(Notification);
62+
if (!original) return;
63+
64+
NotificationObj[method] = (...args: any[]) => {
65+
const [rawMessage, rawOptions] = args;
66+
const text = toPlainText(rawMessage);
67+
const options = ensureViewDetailsAction(text, rawOptions);
68+
return original(text, options);
69+
};
70+
};
71+
72+
['error', 'warning', 'info', 'success'].forEach(wrap);
73+
NotificationObj.__xircuitsAugmented = true;
74+
}

src/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import { commandIDs } from "./commands/CommandIDs";
3434
import { IEditorTracker } from '@jupyterlab/fileeditor';
3535
import { IMainMenu } from '@jupyterlab/mainmenu';
3636
import { handleInstall } from './context-menu/TrayContextMenu';
37-
37+
import { augmentNotifications } from './helpers/notificationAugmentor';
3838
import { installComponentPreview } from './component_info_sidebar/previewHelper';
3939
const FACTORY = 'Xircuits editor';
4040

@@ -80,6 +80,9 @@ const xircuits: JupyterFrontEndPlugin<void> = {
8080

8181
console.log('Xircuits is activated!');
8282

83+
// Add "View details" to long notifications
84+
augmentNotifications();
85+
8386
// Creating the widget factory to register it so the document manager knows about
8487
// our new DocumentWidget
8588
const widgetFactory = new XircuitsFactory({

style/base.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,18 @@ body.light-mode jp-button[title="Toggle Light/Dark Mode"] .moon { visibility:
158158

159159
body.light-mode jp-button[title="Toggle Light/Dark Mode"] .sun { visibility: visible; }
160160

161+
.xircuits-notification-details {
162+
max-height: 60vh;
163+
overflow: auto;
164+
padding: 0.25rem;
165+
}
161166

167+
.xircuits-notification-details pre {
168+
white-space: pre-wrap;
169+
word-break: break-word;
170+
margin: 0;
171+
font-family: var(--jp-code-font-family);
172+
font-size: var(--jp-code-font-size);
173+
}
162174

163175

0 commit comments

Comments
 (0)