jupyterlab_notifications_extension 1.1.26 → 1.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -11
- package/lib/index.js +14 -14
- package/package.json +1 -1
- package/src/index.ts +35 -21
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ Interactive dialog with message input, type selection, auto-close timing, and ac
|
|
|
29
29
|
- Programmatic command API for extensions and automation
|
|
30
30
|
- Five notification types (info, success, warning, error, in-progress)
|
|
31
31
|
- Configurable auto-close with millisecond precision or manual dismiss
|
|
32
|
-
-
|
|
32
|
+
- Action buttons with optional JupyterLab command execution
|
|
33
33
|
- Broadcast delivery via 30-second polling
|
|
34
34
|
- In-memory queue cleared after delivery
|
|
35
35
|
|
|
@@ -77,13 +77,15 @@ Send notifications to JupyterLab. Requires authentication via `Authorization: to
|
|
|
77
77
|
|
|
78
78
|
**Action Button Schema**:
|
|
79
79
|
|
|
80
|
-
| Field | Type | Required | Default | Description
|
|
81
|
-
| ------------- | ------ | -------- | ----------- |
|
|
82
|
-
| `label` | string | Yes | - | Button text
|
|
83
|
-
| `caption` | string | No | `""` | Tooltip text
|
|
84
|
-
| `displayType` | string | No | `"default"` | Visual style: `default`, `accent`, `warn`, `link`
|
|
80
|
+
| Field | Type | Required | Default | Description |
|
|
81
|
+
| ------------- | ------ | -------- | ----------- | ---------------------------------------------------------------- |
|
|
82
|
+
| `label` | string | Yes | - | Button text |
|
|
83
|
+
| `caption` | string | No | `""` | Tooltip text |
|
|
84
|
+
| `displayType` | string | No | `"default"` | Visual style: `default`, `accent`, `warn`, `link` |
|
|
85
|
+
| `commandId` | string | No | - | JupyterLab command ID to execute (e.g., `filebrowser:open-path`) |
|
|
86
|
+
| `args` | object | No | `{}` | Arguments passed to the command |
|
|
85
87
|
|
|
86
|
-
Note:
|
|
88
|
+
Note: Clicking any button dismisses the notification. If `commandId` is provided, the specified JupyterLab command executes before dismissal.
|
|
87
89
|
|
|
88
90
|
**Response** (200 OK):
|
|
89
91
|
|
|
@@ -119,12 +121,27 @@ await app.commands.execute('jupyterlab-notifications:send', {
|
|
|
119
121
|
autoClose: 3000
|
|
120
122
|
});
|
|
121
123
|
|
|
122
|
-
// With
|
|
124
|
+
// With dismiss button
|
|
123
125
|
await app.commands.execute('jupyterlab-notifications:send', {
|
|
124
126
|
message: 'Error processing data',
|
|
125
127
|
type: 'error',
|
|
126
128
|
autoClose: false,
|
|
127
|
-
actions: [{ label: '
|
|
129
|
+
actions: [{ label: 'Dismiss', displayType: 'default' }]
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Action button that executes a JupyterLab command
|
|
133
|
+
await app.commands.execute('jupyterlab-notifications:send', {
|
|
134
|
+
message: 'New notebook available',
|
|
135
|
+
type: 'info',
|
|
136
|
+
autoClose: false,
|
|
137
|
+
actions: [
|
|
138
|
+
{
|
|
139
|
+
label: 'Open Notebook',
|
|
140
|
+
commandId: 'filebrowser:open-path',
|
|
141
|
+
args: { path: '/notebooks/example.ipynb' },
|
|
142
|
+
displayType: 'accent'
|
|
143
|
+
}
|
|
144
|
+
]
|
|
128
145
|
});
|
|
129
146
|
```
|
|
130
147
|
|
|
@@ -135,8 +152,6 @@ The `jupyterlab-notify` command is installed with the extension:
|
|
|
135
152
|
```bash
|
|
136
153
|
# Basic notification (auto-detects URL from running servers)
|
|
137
154
|
jupyterlab-notify -m "Deployment complete" -t success
|
|
138
|
-
# Output: URL: http://127.0.0.1:8888/jupyterhub/user/alice | Type: success
|
|
139
|
-
# Notification sent: notif_1765552893662_0
|
|
140
155
|
|
|
141
156
|
# With explicit URL (e.g., JupyterHub)
|
|
142
157
|
jupyterlab-notify --url "http://127.0.0.1:8888/jupyterhub/user/alice" -m "Hello"
|
|
@@ -144,6 +159,13 @@ jupyterlab-notify --url "http://127.0.0.1:8888/jupyterhub/user/alice" -m "Hello"
|
|
|
144
159
|
# Persistent warning (no auto-close)
|
|
145
160
|
jupyterlab-notify -m "System maintenance in 1 hour" -t warning --no-auto-close
|
|
146
161
|
|
|
162
|
+
# With dismiss button
|
|
163
|
+
jupyterlab-notify -m "Task complete" --action "Dismiss"
|
|
164
|
+
|
|
165
|
+
# Action button that executes a JupyterLab command
|
|
166
|
+
jupyterlab-notify -m "New file available" --action "Open File" \
|
|
167
|
+
--cmd "filebrowser:open-path" --command-args '{"path": "/notebooks/example.ipynb"}'
|
|
168
|
+
|
|
147
169
|
# Silent mode (notification center only, no toast)
|
|
148
170
|
jupyterlab-notify -m "Background task finished" --auto-close 0
|
|
149
171
|
```
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ICommandPalette, Dialog } from '@jupyterlab/apputils';
|
|
1
|
+
import { ICommandPalette, Dialog, Notification } from '@jupyterlab/apputils';
|
|
2
2
|
import { Widget } from '@lumino/widgets';
|
|
3
3
|
import { requestAPI } from './request';
|
|
4
4
|
/**
|
|
@@ -14,7 +14,7 @@ async function fetchAndDisplayNotifications(app) {
|
|
|
14
14
|
if (response.notifications && response.notifications.length > 0) {
|
|
15
15
|
console.log(`Received ${response.notifications.length} notification(s) from server`);
|
|
16
16
|
response.notifications.forEach(notif => {
|
|
17
|
-
// Build options object
|
|
17
|
+
// Build options object with explicit type
|
|
18
18
|
const options = {
|
|
19
19
|
autoClose: notif.autoClose
|
|
20
20
|
};
|
|
@@ -22,27 +22,27 @@ async function fetchAndDisplayNotifications(app) {
|
|
|
22
22
|
if (notif.data !== undefined) {
|
|
23
23
|
options.data = notif.data;
|
|
24
24
|
}
|
|
25
|
-
// Build actions array if present
|
|
25
|
+
// Build actions array if present
|
|
26
26
|
if (notif.actions && notif.actions.length > 0) {
|
|
27
27
|
options.actions = notif.actions.map(action => ({
|
|
28
28
|
label: action.label,
|
|
29
29
|
caption: action.caption || '',
|
|
30
30
|
displayType: action.displayType || 'default',
|
|
31
31
|
callback: () => {
|
|
32
|
-
|
|
32
|
+
// If commandId provided, execute the command
|
|
33
|
+
if (action.commandId) {
|
|
34
|
+
app.commands
|
|
35
|
+
.execute(action.commandId, action.args)
|
|
36
|
+
.catch(err => {
|
|
37
|
+
console.error(`Failed to execute command '${action.commandId}':`, err);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// Default: button click dismisses notification (built-in behavior)
|
|
33
41
|
}
|
|
34
42
|
}));
|
|
35
43
|
}
|
|
36
|
-
// Display notification using
|
|
37
|
-
|
|
38
|
-
.execute('apputils:notify', {
|
|
39
|
-
message: notif.message,
|
|
40
|
-
type: notif.type,
|
|
41
|
-
options: options
|
|
42
|
-
})
|
|
43
|
-
.catch(err => {
|
|
44
|
-
console.error('Failed to display notification:', err);
|
|
45
|
-
});
|
|
44
|
+
// Display notification using Notification manager directly
|
|
45
|
+
Notification.manager.notify(notif.message, notif.type, options);
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jupyterlab_notifications_extension",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.27",
|
|
4
4
|
"description": "Jupyterlab extension to receive and display notifications in the main panel. Those can be from the jupyterjub administrator or from other places.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
package/src/index.ts
CHANGED
|
@@ -3,11 +3,26 @@ import {
|
|
|
3
3
|
JupyterFrontEndPlugin
|
|
4
4
|
} from '@jupyterlab/application';
|
|
5
5
|
|
|
6
|
-
import { ICommandPalette, Dialog } from '@jupyterlab/apputils';
|
|
6
|
+
import { ICommandPalette, Dialog, Notification } from '@jupyterlab/apputils';
|
|
7
7
|
import { Widget } from '@lumino/widgets';
|
|
8
|
+
import {
|
|
9
|
+
ReadonlyJSONValue,
|
|
10
|
+
ReadonlyPartialJSONObject
|
|
11
|
+
} from '@lumino/coreutils';
|
|
8
12
|
|
|
9
13
|
import { requestAPI } from './request';
|
|
10
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Action interface for notifications
|
|
17
|
+
*/
|
|
18
|
+
interface INotificationAction {
|
|
19
|
+
label: string;
|
|
20
|
+
caption?: string;
|
|
21
|
+
displayType?: 'default' | 'accent' | 'warn' | 'link';
|
|
22
|
+
commandId?: string;
|
|
23
|
+
args?: ReadonlyPartialJSONObject;
|
|
24
|
+
}
|
|
25
|
+
|
|
11
26
|
/**
|
|
12
27
|
* Notification interface matching backend payload
|
|
13
28
|
*/
|
|
@@ -17,12 +32,8 @@ interface INotificationData {
|
|
|
17
32
|
type: 'default' | 'info' | 'success' | 'warning' | 'error' | 'in-progress';
|
|
18
33
|
autoClose: number | false;
|
|
19
34
|
createdAt: number;
|
|
20
|
-
actions?:
|
|
21
|
-
|
|
22
|
-
caption?: string;
|
|
23
|
-
displayType?: 'default' | 'accent' | 'warn' | 'link';
|
|
24
|
-
}>;
|
|
25
|
-
data?: any;
|
|
35
|
+
actions?: INotificationAction[];
|
|
36
|
+
data?: ReadonlyJSONValue;
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
/**
|
|
@@ -47,8 +58,8 @@ async function fetchAndDisplayNotifications(
|
|
|
47
58
|
);
|
|
48
59
|
|
|
49
60
|
response.notifications.forEach(notif => {
|
|
50
|
-
// Build options object
|
|
51
|
-
const options:
|
|
61
|
+
// Build options object with explicit type
|
|
62
|
+
const options: Notification.IOptions<ReadonlyJSONValue> = {
|
|
52
63
|
autoClose: notif.autoClose
|
|
53
64
|
};
|
|
54
65
|
|
|
@@ -57,28 +68,31 @@ async function fetchAndDisplayNotifications(
|
|
|
57
68
|
options.data = notif.data;
|
|
58
69
|
}
|
|
59
70
|
|
|
60
|
-
// Build actions array if present
|
|
71
|
+
// Build actions array if present
|
|
61
72
|
if (notif.actions && notif.actions.length > 0) {
|
|
62
73
|
options.actions = notif.actions.map(action => ({
|
|
63
74
|
label: action.label,
|
|
64
75
|
caption: action.caption || '',
|
|
65
76
|
displayType: action.displayType || 'default',
|
|
66
77
|
callback: () => {
|
|
67
|
-
|
|
78
|
+
// If commandId provided, execute the command
|
|
79
|
+
if (action.commandId) {
|
|
80
|
+
app.commands
|
|
81
|
+
.execute(action.commandId, action.args)
|
|
82
|
+
.catch(err => {
|
|
83
|
+
console.error(
|
|
84
|
+
`Failed to execute command '${action.commandId}':`,
|
|
85
|
+
err
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// Default: button click dismisses notification (built-in behavior)
|
|
68
90
|
}
|
|
69
91
|
}));
|
|
70
92
|
}
|
|
71
93
|
|
|
72
|
-
// Display notification using
|
|
73
|
-
|
|
74
|
-
.execute('apputils:notify', {
|
|
75
|
-
message: notif.message,
|
|
76
|
-
type: notif.type,
|
|
77
|
-
options: options
|
|
78
|
-
})
|
|
79
|
-
.catch(err => {
|
|
80
|
-
console.error('Failed to display notification:', err);
|
|
81
|
-
});
|
|
94
|
+
// Display notification using Notification manager directly
|
|
95
|
+
Notification.manager.notify(notif.message, notif.type, options);
|
|
82
96
|
});
|
|
83
97
|
}
|
|
84
98
|
} catch (reason) {
|