jupyterlab-pioneer 0.1.11 → 1.0.0
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 +32 -0
- package/lib/index.d.ts +5 -1
- package/lib/index.js +33 -28
- package/lib/producer.d.ts +13 -14
- package/lib/producer.js +103 -42
- package/lib/utils.d.ts +5 -0
- package/lib/utils.js +57 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# JupyterLab Pioneer
|
|
2
2
|
|
|
3
|
+
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
4
|
+
|
|
5
|
+
[](#contributors-)
|
|
6
|
+
|
|
7
|
+
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
8
|
+
|
|
3
9
|
[](https://pypi.org/project/jupyterlab-pioneer)
|
|
4
10
|
[](https://www.npmjs.com/package/jupyterlab-pioneer)
|
|
5
11
|
|
|
@@ -180,3 +186,29 @@ folder is located. Then you can remove the symlink named `jupyterlab-pioneer` wi
|
|
|
180
186
|
### Packaging the extension
|
|
181
187
|
|
|
182
188
|
See [RELEASE](RELEASE.md)
|
|
189
|
+
|
|
190
|
+
## Contributors ✨
|
|
191
|
+
|
|
192
|
+
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
|
193
|
+
|
|
194
|
+
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
|
195
|
+
<!-- prettier-ignore-start -->
|
|
196
|
+
<!-- markdownlint-disable -->
|
|
197
|
+
<table>
|
|
198
|
+
<tbody>
|
|
199
|
+
<tr>
|
|
200
|
+
<td align="center" valign="top" width="14.28%"><a href="https://www.wumengyan.com/"><img src="https://avatars.githubusercontent.com/u/85606983?v=4?s=100" width="100px;" alt="mengyanw"/><br /><sub><b>Mengyan Wu</b></sub></a><br /><a href="https://github.com/educational-technology-collective/jupyterlab-pioneer/commits?author=mengyanw" title="Code">💻</a> <a href="#ideas-mengyanw" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-mengyanw" title="Maintenance">🚧</a> <a href="#projectManagement-mengyanw" title="Project Management">📆</a> <a href="#infra-mengyanw" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/educational-technology-collective/jupyterlab-pioneer/commits?author=mengyanw" title="Tests">⚠️</a> <a href="https://github.com/educational-technology-collective/jupyterlab-pioneer/commits?author=mengyanw" title="Documentation">📖</a></td>
|
|
201
|
+
<td align="center" valign="top" width="14.28%"><a href="http://christopherbrooks.ca"><img src="https://avatars.githubusercontent.com/u/1355641?v=4?s=100" width="100px;" alt="Christopher Brooks"/><br /><sub><b>Christopher Brooks</b></sub></a><br /><a href="#ideas-cab938" title="Ideas, Planning, & Feedback">🤔</a> <a href="#projectManagement-cab938" title="Project Management">📆</a> <a href="#infra-cab938" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
|
202
|
+
<td align="center" valign="top" width="14.28%"><a href="http://from.so/Steve_Oney"><img src="https://avatars.githubusercontent.com/u/211262?v=4?s=100" width="100px;" alt="Steve Oney"/><br /><sub><b>Steve Oney</b></sub></a><br /><a href="#ideas-soney" title="Ideas, Planning, & Feedback">🤔</a> <a href="#projectManagement-soney" title="Project Management">📆</a></td>
|
|
203
|
+
<td align="center" valign="top" width="14.28%"><a href="https://www.chrisostrouchov.com"><img src="https://avatars.githubusercontent.com/u/1740337?v=4?s=100" width="100px;" alt="Christopher Ostrouchov"/><br /><sub><b>Christopher Ostrouchov</b></sub></a><br /><a href="#ideas-costrouc" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/educational-technology-collective/jupyterlab-pioneer/commits?author=costrouc" title="Code">💻</a></td>
|
|
204
|
+
<td align="center" valign="top" width="14.28%"><a href="https://iamit.in"><img src="https://avatars.githubusercontent.com/u/5647941?v=4?s=100" width="100px;" alt="Amit Kumar"/><br /><sub><b>Amit Kumar</b></sub></a><br /><a href="#infra-aktech" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
|
205
|
+
</tr>
|
|
206
|
+
</tbody>
|
|
207
|
+
</table>
|
|
208
|
+
|
|
209
|
+
<!-- markdownlint-restore -->
|
|
210
|
+
<!-- prettier-ignore-end -->
|
|
211
|
+
|
|
212
|
+
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
|
213
|
+
|
|
214
|
+
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
package/lib/index.d.ts
CHANGED
|
@@ -4,17 +4,21 @@ import { Token } from '@lumino/coreutils';
|
|
|
4
4
|
import { Exporter } from './types';
|
|
5
5
|
export declare const IJupyterLabPioneer: Token<IJupyterLabPioneer>;
|
|
6
6
|
export interface IJupyterLabPioneer {
|
|
7
|
+
exporters: Exporter[];
|
|
7
8
|
/**
|
|
8
9
|
* Send event data to exporters defined in the configuration file.
|
|
9
10
|
*
|
|
10
11
|
* @param {NotebookPanel} notebookPanel The notebook panel the extension currently listens to.
|
|
11
12
|
* @param {Object} eventDetail An object containing event details.
|
|
12
13
|
* @param {Exporter} exporter The exporter configuration.
|
|
13
|
-
* @param {Boolean
|
|
14
|
+
* @param {Boolean} logWholeNotebook A boolean indicating whether to log the entire notebook or not.
|
|
14
15
|
*/
|
|
15
16
|
publishEvent(notebookPanel: NotebookPanel, eventDetail: Object, exporter: Exporter, logWholeNotebook?: Boolean): Promise<void>;
|
|
16
17
|
}
|
|
17
18
|
declare class JupyterLabPioneer implements IJupyterLabPioneer {
|
|
19
|
+
exporters: Exporter[];
|
|
20
|
+
constructor();
|
|
21
|
+
loadExporters(notebookPanel: NotebookPanel): Promise<void>;
|
|
18
22
|
publishEvent(notebookPanel: NotebookPanel, eventDetail: Object, exporter: Exporter, logWholeNotebook?: Boolean): Promise<void>;
|
|
19
23
|
}
|
|
20
24
|
declare const plugin: JupyterFrontEndPlugin<JupyterLabPioneer>;
|
package/lib/index.js
CHANGED
|
@@ -1,10 +1,37 @@
|
|
|
1
1
|
import { INotebookTracker } from '@jupyterlab/notebook';
|
|
2
|
+
import { IMainMenu } from '@jupyterlab/mainmenu';
|
|
2
3
|
import { Token } from '@lumino/coreutils';
|
|
3
4
|
import { requestAPI } from './handler';
|
|
4
5
|
import { producerCollection } from './producer';
|
|
6
|
+
import { sendInfoNotification, addInfoToHelpMenu } from './utils';
|
|
5
7
|
const PLUGIN_ID = 'jupyterlab-pioneer:plugin';
|
|
6
8
|
export const IJupyterLabPioneer = new Token(PLUGIN_ID);
|
|
7
9
|
class JupyterLabPioneer {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.exporters = [];
|
|
12
|
+
}
|
|
13
|
+
async loadExporters(notebookPanel) {
|
|
14
|
+
var _a;
|
|
15
|
+
const config = (await requestAPI('config'));
|
|
16
|
+
const activeEvents = config.activeEvents;
|
|
17
|
+
const exporters = ((_a = notebookPanel.content.model) === null || _a === void 0 ? void 0 : _a.getMetadata('exporters')) || config.exporters; // The exporters configuration in the notebook metadata overrides the configuration in the configuration file "jupyter_jupyterlab_pioneer_config.py"
|
|
18
|
+
const processedExporters = activeEvents && activeEvents.length
|
|
19
|
+
? exporters.map(e => {
|
|
20
|
+
if (!e.activeEvents) {
|
|
21
|
+
e.activeEvents = activeEvents;
|
|
22
|
+
return e;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return e;
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
: exporters.filter(e => e.activeEvents && e.activeEvents.length);
|
|
29
|
+
// Exporters without specifying the corresponding activeEvents will use the global activeEvents configuration.
|
|
30
|
+
// When the global activeEvents configuration is null, exporters that do not have corresponding activeEvents will be ignored.
|
|
31
|
+
console.log(processedExporters);
|
|
32
|
+
this.exporters = processedExporters;
|
|
33
|
+
sendInfoNotification(processedExporters, true);
|
|
34
|
+
}
|
|
8
35
|
async publishEvent(notebookPanel, eventDetail, exporter, logWholeNotebook) {
|
|
9
36
|
var _a, _b;
|
|
10
37
|
if (!notebookPanel) {
|
|
@@ -31,41 +58,19 @@ class JupyterLabPioneer {
|
|
|
31
58
|
const plugin = {
|
|
32
59
|
id: PLUGIN_ID,
|
|
33
60
|
autoStart: true,
|
|
34
|
-
requires: [INotebookTracker],
|
|
61
|
+
requires: [INotebookTracker, IMainMenu],
|
|
35
62
|
provides: IJupyterLabPioneer,
|
|
36
|
-
activate: async (app, notebookTracker) => {
|
|
63
|
+
activate: async (app, notebookTracker, mainMenu) => {
|
|
37
64
|
const version = await requestAPI('version');
|
|
38
65
|
console.log(`${PLUGIN_ID}: ${version}`);
|
|
39
|
-
const config = (await requestAPI('config'));
|
|
40
66
|
const pioneer = new JupyterLabPioneer();
|
|
67
|
+
addInfoToHelpMenu(app, mainMenu, version);
|
|
41
68
|
notebookTracker.widgetAdded.connect(async (_, notebookPanel) => {
|
|
42
|
-
var _a;
|
|
43
69
|
await notebookPanel.revealed;
|
|
44
70
|
await notebookPanel.sessionContext.ready;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const processedExporters = activeEvents && activeEvents.length
|
|
49
|
-
? exporters.map(e => {
|
|
50
|
-
if (!e.activeEvents) {
|
|
51
|
-
e.activeEvents = activeEvents;
|
|
52
|
-
return e;
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
return e;
|
|
56
|
-
}
|
|
57
|
-
})
|
|
58
|
-
: exporters.filter(e => e.activeEvents && e.activeEvents.length);
|
|
59
|
-
// Exporters without specifying the corresponding activeEvents will use the global activeEvents configuration.
|
|
60
|
-
// When the global activeEvents configuration is null, exporters that do not have corresponding activeEvents will be ignored.
|
|
61
|
-
console.log(processedExporters);
|
|
62
|
-
processedExporters.forEach(exporter => {
|
|
63
|
-
producerCollection.forEach(producer => {
|
|
64
|
-
var _a;
|
|
65
|
-
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(producer.id)) {
|
|
66
|
-
new producer().listen(notebookPanel, pioneer, exporter);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
71
|
+
await pioneer.loadExporters(notebookPanel);
|
|
72
|
+
producerCollection.forEach(producer => {
|
|
73
|
+
new producer().listen(notebookPanel, pioneer);
|
|
69
74
|
});
|
|
70
75
|
});
|
|
71
76
|
return pioneer;
|
package/lib/producer.d.ts
CHANGED
|
@@ -1,58 +1,57 @@
|
|
|
1
1
|
import { NotebookPanel } from '@jupyterlab/notebook';
|
|
2
2
|
import { IJupyterLabPioneer } from './index';
|
|
3
|
-
import { Exporter } from './types';
|
|
4
3
|
export declare class ActiveCellChangeEventProducer {
|
|
5
4
|
static id: string;
|
|
6
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
5
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
7
6
|
}
|
|
8
7
|
export declare class CellAddEventProducer {
|
|
9
8
|
static id: string;
|
|
10
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
9
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
11
10
|
}
|
|
12
11
|
export declare class CellEditEventProducer {
|
|
13
12
|
static id: string;
|
|
14
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
13
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
15
14
|
}
|
|
16
15
|
export declare class CellExecuteEventProducer {
|
|
17
16
|
static id: string;
|
|
18
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
17
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
19
18
|
}
|
|
20
19
|
export declare class CellRemoveEventProducer {
|
|
21
20
|
static id: string;
|
|
22
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
21
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
23
22
|
}
|
|
24
23
|
export declare class ClipboardCopyEventProducer {
|
|
25
24
|
static id: string;
|
|
26
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
25
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
27
26
|
}
|
|
28
27
|
export declare class ClipboardCutEventProducer {
|
|
29
28
|
static id: string;
|
|
30
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
29
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
31
30
|
}
|
|
32
31
|
export declare class ClipboardPasteEventProducer {
|
|
33
32
|
static id: string;
|
|
34
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
33
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
35
34
|
}
|
|
36
35
|
export declare class NotebookHiddenEventProducer {
|
|
37
36
|
static id: string;
|
|
38
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
37
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
39
38
|
}
|
|
40
39
|
export declare class NotebookOpenEventProducer {
|
|
41
40
|
static id: string;
|
|
42
41
|
private produced;
|
|
43
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
42
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): Promise<void>;
|
|
44
43
|
}
|
|
45
44
|
export declare class NotebookSaveEventProducer {
|
|
46
45
|
static id: string;
|
|
47
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
46
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
48
47
|
}
|
|
49
48
|
export declare class NotebookScrollEventProducer {
|
|
50
49
|
static id: string;
|
|
51
50
|
private timeout;
|
|
52
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
51
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
53
52
|
}
|
|
54
53
|
export declare class NotebookVisibleEventProducer {
|
|
55
54
|
static id: string;
|
|
56
|
-
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer
|
|
55
|
+
listen(notebookPanel: NotebookPanel, pioneer: IJupyterLabPioneer): void;
|
|
57
56
|
}
|
|
58
57
|
export declare const producerCollection: (typeof ActiveCellChangeEventProducer)[];
|
package/lib/producer.js
CHANGED
|
@@ -2,9 +2,8 @@ import { NotebookActions } from '@jupyterlab/notebook';
|
|
|
2
2
|
import { EditorView } from '@codemirror/view';
|
|
3
3
|
import { requestAPI } from './handler';
|
|
4
4
|
class ActiveCellChangeEventProducer {
|
|
5
|
-
listen(notebookPanel, pioneer
|
|
5
|
+
listen(notebookPanel, pioneer) {
|
|
6
6
|
notebookPanel.content.activeCellChanged.connect(async (_, cell) => {
|
|
7
|
-
var _a, _b;
|
|
8
7
|
if (cell && notebookPanel.content.widgets) {
|
|
9
8
|
const activatedCell = {
|
|
10
9
|
id: cell === null || cell === void 0 ? void 0 : cell.model.id,
|
|
@@ -17,7 +16,12 @@ class ActiveCellChangeEventProducer {
|
|
|
17
16
|
cells: [activatedCell] // activated cell
|
|
18
17
|
}
|
|
19
18
|
};
|
|
20
|
-
|
|
19
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
20
|
+
var _a, _b, _c;
|
|
21
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(ActiveCellChangeEventProducer.id)) {
|
|
22
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == ActiveCellChangeEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
21
25
|
}
|
|
22
26
|
});
|
|
23
27
|
}
|
|
@@ -25,10 +29,9 @@ class ActiveCellChangeEventProducer {
|
|
|
25
29
|
ActiveCellChangeEventProducer.id = 'ActiveCellChangeEvent';
|
|
26
30
|
export { ActiveCellChangeEventProducer };
|
|
27
31
|
class CellAddEventProducer {
|
|
28
|
-
listen(notebookPanel, pioneer
|
|
32
|
+
listen(notebookPanel, pioneer) {
|
|
29
33
|
var _a;
|
|
30
34
|
(_a = notebookPanel.content.model) === null || _a === void 0 ? void 0 : _a.cells.changed.connect(async (_, args) => {
|
|
31
|
-
var _a, _b;
|
|
32
35
|
if (args.type === 'add') {
|
|
33
36
|
const addedCell = {
|
|
34
37
|
id: args.newValues[0].id,
|
|
@@ -41,7 +44,12 @@ class CellAddEventProducer {
|
|
|
41
44
|
cells: [addedCell]
|
|
42
45
|
}
|
|
43
46
|
};
|
|
44
|
-
|
|
47
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
48
|
+
var _a, _b, _c;
|
|
49
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellAddEventProducer.id)) {
|
|
50
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == CellAddEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
45
53
|
}
|
|
46
54
|
});
|
|
47
55
|
}
|
|
@@ -49,10 +57,10 @@ class CellAddEventProducer {
|
|
|
49
57
|
CellAddEventProducer.id = 'CellAddEvent';
|
|
50
58
|
export { CellAddEventProducer };
|
|
51
59
|
class CellEditEventProducer {
|
|
52
|
-
listen(notebookPanel, pioneer
|
|
60
|
+
listen(notebookPanel, pioneer) {
|
|
53
61
|
var _a, _b;
|
|
54
62
|
const sendDoc = async (_, cell) => {
|
|
55
|
-
var _a, _b
|
|
63
|
+
var _a, _b;
|
|
56
64
|
await (cell === null || cell === void 0 ? void 0 : cell.ready); // wait until cell is ready, to prevent errors when creating new cells
|
|
57
65
|
const editor = cell === null || cell === void 0 ? void 0 : cell.editor;
|
|
58
66
|
const event = {
|
|
@@ -63,7 +71,12 @@ class CellEditEventProducer {
|
|
|
63
71
|
doc: (_b = (_a = editor === null || editor === void 0 ? void 0 : editor.state) === null || _a === void 0 ? void 0 : _a.doc) === null || _b === void 0 ? void 0 : _b.toJSON() // send entire cell content if this is a new cell
|
|
64
72
|
}
|
|
65
73
|
};
|
|
66
|
-
|
|
74
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
75
|
+
var _a, _b, _c;
|
|
76
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellEditEventProducer.id)) {
|
|
77
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == CellEditEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
67
80
|
};
|
|
68
81
|
const addDocChangeListener = async (cell) => {
|
|
69
82
|
await (cell === null || cell === void 0 ? void 0 : cell.ready); // wait until cell is ready, to prevent errors when creating new cells
|
|
@@ -78,8 +91,13 @@ class CellEditEventProducer {
|
|
|
78
91
|
changes: v.changes.toJSON() // send changes
|
|
79
92
|
}
|
|
80
93
|
};
|
|
81
|
-
|
|
82
|
-
|
|
94
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
95
|
+
var _a;
|
|
96
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellEditEventProducer.id)) {
|
|
97
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, false // do not log whole notebook for doc changes
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
83
101
|
}
|
|
84
102
|
}));
|
|
85
103
|
};
|
|
@@ -99,9 +117,8 @@ class CellEditEventProducer {
|
|
|
99
117
|
CellEditEventProducer.id = 'CellEditEvent';
|
|
100
118
|
export { CellEditEventProducer };
|
|
101
119
|
class CellExecuteEventProducer {
|
|
102
|
-
listen(notebookPanel, pioneer
|
|
120
|
+
listen(notebookPanel, pioneer) {
|
|
103
121
|
NotebookActions.executed.connect(async (_, args) => {
|
|
104
|
-
var _a, _b;
|
|
105
122
|
if (notebookPanel.content === args.notebook) {
|
|
106
123
|
const executedCell = {
|
|
107
124
|
id: args.cell.model.id,
|
|
@@ -116,7 +133,12 @@ class CellExecuteEventProducer {
|
|
|
116
133
|
kernelError: args.success ? null : args.error
|
|
117
134
|
}
|
|
118
135
|
};
|
|
119
|
-
|
|
136
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
137
|
+
var _a, _b, _c;
|
|
138
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellExecuteEventProducer.id)) {
|
|
139
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == CellExecuteEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
120
142
|
}
|
|
121
143
|
});
|
|
122
144
|
}
|
|
@@ -124,10 +146,9 @@ class CellExecuteEventProducer {
|
|
|
124
146
|
CellExecuteEventProducer.id = 'CellExecuteEvent';
|
|
125
147
|
export { CellExecuteEventProducer };
|
|
126
148
|
class CellRemoveEventProducer {
|
|
127
|
-
listen(notebookPanel, pioneer
|
|
149
|
+
listen(notebookPanel, pioneer) {
|
|
128
150
|
var _a;
|
|
129
151
|
(_a = notebookPanel.content.model) === null || _a === void 0 ? void 0 : _a.cells.changed.connect(async (_, args) => {
|
|
130
|
-
var _a, _b;
|
|
131
152
|
if (args.type === 'remove') {
|
|
132
153
|
const removedCell = {
|
|
133
154
|
index: args.oldIndex
|
|
@@ -139,7 +160,12 @@ class CellRemoveEventProducer {
|
|
|
139
160
|
cells: [removedCell]
|
|
140
161
|
}
|
|
141
162
|
};
|
|
142
|
-
|
|
163
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
164
|
+
var _a, _b, _c;
|
|
165
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellRemoveEventProducer.id)) {
|
|
166
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == CellRemoveEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
143
169
|
}
|
|
144
170
|
});
|
|
145
171
|
}
|
|
@@ -147,9 +173,9 @@ class CellRemoveEventProducer {
|
|
|
147
173
|
CellRemoveEventProducer.id = 'CellRemoveEvent';
|
|
148
174
|
export { CellRemoveEventProducer };
|
|
149
175
|
class ClipboardCopyEventProducer {
|
|
150
|
-
listen(notebookPanel, pioneer
|
|
176
|
+
listen(notebookPanel, pioneer) {
|
|
151
177
|
notebookPanel.node.addEventListener('copy', async () => {
|
|
152
|
-
var _a, _b
|
|
178
|
+
var _a, _b;
|
|
153
179
|
const cell = {
|
|
154
180
|
id: (_a = notebookPanel.content.activeCell) === null || _a === void 0 ? void 0 : _a.model.id,
|
|
155
181
|
index: notebookPanel.content.widgets.findIndex(value => value === notebookPanel.content.activeCell)
|
|
@@ -163,16 +189,21 @@ class ClipboardCopyEventProducer {
|
|
|
163
189
|
selection: text
|
|
164
190
|
}
|
|
165
191
|
};
|
|
166
|
-
|
|
192
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
193
|
+
var _a, _b, _c;
|
|
194
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellRemoveEventProducer.id)) {
|
|
195
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == ClipboardCopyEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
167
198
|
});
|
|
168
199
|
}
|
|
169
200
|
}
|
|
170
201
|
ClipboardCopyEventProducer.id = 'ClipboardCopyEvent';
|
|
171
202
|
export { ClipboardCopyEventProducer };
|
|
172
203
|
class ClipboardCutEventProducer {
|
|
173
|
-
listen(notebookPanel, pioneer
|
|
204
|
+
listen(notebookPanel, pioneer) {
|
|
174
205
|
notebookPanel.node.addEventListener('cut', async () => {
|
|
175
|
-
var _a, _b
|
|
206
|
+
var _a, _b;
|
|
176
207
|
const cell = {
|
|
177
208
|
id: (_a = notebookPanel.content.activeCell) === null || _a === void 0 ? void 0 : _a.model.id,
|
|
178
209
|
index: notebookPanel.content.widgets.findIndex(value => value === notebookPanel.content.activeCell)
|
|
@@ -186,16 +217,21 @@ class ClipboardCutEventProducer {
|
|
|
186
217
|
selection: text
|
|
187
218
|
}
|
|
188
219
|
};
|
|
189
|
-
|
|
220
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
221
|
+
var _a, _b, _c;
|
|
222
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellRemoveEventProducer.id)) {
|
|
223
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == ClipboardCutEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
190
226
|
});
|
|
191
227
|
}
|
|
192
228
|
}
|
|
193
229
|
ClipboardCutEventProducer.id = 'ClipboardCutEvent';
|
|
194
230
|
export { ClipboardCutEventProducer };
|
|
195
231
|
class ClipboardPasteEventProducer {
|
|
196
|
-
listen(notebookPanel, pioneer
|
|
232
|
+
listen(notebookPanel, pioneer) {
|
|
197
233
|
notebookPanel.node.addEventListener('paste', async (e) => {
|
|
198
|
-
var _a
|
|
234
|
+
var _a;
|
|
199
235
|
const cell = {
|
|
200
236
|
id: (_a = notebookPanel.content.activeCell) === null || _a === void 0 ? void 0 : _a.model.id,
|
|
201
237
|
index: notebookPanel.content.widgets.findIndex(value => value === notebookPanel.content.activeCell)
|
|
@@ -209,16 +245,20 @@ class ClipboardPasteEventProducer {
|
|
|
209
245
|
selection: text
|
|
210
246
|
}
|
|
211
247
|
};
|
|
212
|
-
|
|
248
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
249
|
+
var _a, _b, _c;
|
|
250
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellRemoveEventProducer.id)) {
|
|
251
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == ClipboardPasteEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
213
254
|
});
|
|
214
255
|
}
|
|
215
256
|
}
|
|
216
257
|
ClipboardPasteEventProducer.id = 'ClipboardPasteEvent';
|
|
217
258
|
export { ClipboardPasteEventProducer };
|
|
218
259
|
class NotebookHiddenEventProducer {
|
|
219
|
-
listen(notebookPanel, pioneer
|
|
260
|
+
listen(notebookPanel, pioneer) {
|
|
220
261
|
document.addEventListener('visibilitychange', async (e) => {
|
|
221
|
-
var _a, _b;
|
|
222
262
|
if (document.visibilityState === 'hidden' &&
|
|
223
263
|
document.contains(notebookPanel.node)) {
|
|
224
264
|
const event = {
|
|
@@ -226,7 +266,12 @@ class NotebookHiddenEventProducer {
|
|
|
226
266
|
eventTime: Date.now(),
|
|
227
267
|
eventInfo: null
|
|
228
268
|
};
|
|
229
|
-
|
|
269
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
270
|
+
var _a, _b, _c;
|
|
271
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellRemoveEventProducer.id)) {
|
|
272
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == NotebookHiddenEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
230
275
|
}
|
|
231
276
|
});
|
|
232
277
|
}
|
|
@@ -237,8 +282,7 @@ class NotebookOpenEventProducer {
|
|
|
237
282
|
constructor() {
|
|
238
283
|
this.produced = false;
|
|
239
284
|
}
|
|
240
|
-
async listen(notebookPanel, pioneer
|
|
241
|
-
var _a, _b;
|
|
285
|
+
async listen(notebookPanel, pioneer) {
|
|
242
286
|
if (!this.produced) {
|
|
243
287
|
const event = {
|
|
244
288
|
eventName: NotebookOpenEventProducer.id,
|
|
@@ -247,24 +291,33 @@ class NotebookOpenEventProducer {
|
|
|
247
291
|
environ: await requestAPI('environ')
|
|
248
292
|
}
|
|
249
293
|
};
|
|
250
|
-
|
|
251
|
-
|
|
294
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
295
|
+
var _a, _b, _c;
|
|
296
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellRemoveEventProducer.id)) {
|
|
297
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == NotebookOpenEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
298
|
+
this.produced = true;
|
|
299
|
+
}
|
|
300
|
+
});
|
|
252
301
|
}
|
|
253
302
|
}
|
|
254
303
|
}
|
|
255
304
|
NotebookOpenEventProducer.id = 'NotebookOpenEvent';
|
|
256
305
|
export { NotebookOpenEventProducer };
|
|
257
306
|
class NotebookSaveEventProducer {
|
|
258
|
-
listen(notebookPanel, pioneer
|
|
307
|
+
listen(notebookPanel, pioneer) {
|
|
259
308
|
notebookPanel.context.saveState.connect(async (_, saveState) => {
|
|
260
|
-
var _a, _b;
|
|
261
309
|
if (saveState.match('completed')) {
|
|
262
310
|
const event = {
|
|
263
311
|
eventName: NotebookSaveEventProducer.id,
|
|
264
312
|
eventTime: Date.now(),
|
|
265
313
|
eventInfo: null
|
|
266
314
|
};
|
|
267
|
-
|
|
315
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
316
|
+
var _a, _b, _c;
|
|
317
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellRemoveEventProducer.id)) {
|
|
318
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == NotebookSaveEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
268
321
|
}
|
|
269
322
|
});
|
|
270
323
|
}
|
|
@@ -293,9 +346,8 @@ class NotebookScrollEventProducer {
|
|
|
293
346
|
constructor() {
|
|
294
347
|
this.timeout = 0;
|
|
295
348
|
}
|
|
296
|
-
listen(notebookPanel, pioneer
|
|
349
|
+
listen(notebookPanel, pioneer) {
|
|
297
350
|
notebookPanel.content.node.addEventListener('scroll', async (e) => {
|
|
298
|
-
var _a, _b;
|
|
299
351
|
e.stopPropagation();
|
|
300
352
|
clearTimeout(this.timeout);
|
|
301
353
|
await new Promise(resolve => (this.timeout = window.setTimeout(resolve, 1500))); // wait 1.5 seconds before preceding
|
|
@@ -306,16 +358,20 @@ class NotebookScrollEventProducer {
|
|
|
306
358
|
cells: getVisibleCells(notebookPanel)
|
|
307
359
|
}
|
|
308
360
|
};
|
|
309
|
-
|
|
361
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
362
|
+
var _a, _b, _c;
|
|
363
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(CellRemoveEventProducer.id)) {
|
|
364
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == NotebookScrollEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
310
367
|
});
|
|
311
368
|
}
|
|
312
369
|
}
|
|
313
370
|
NotebookScrollEventProducer.id = 'NotebookScrollEvent';
|
|
314
371
|
export { NotebookScrollEventProducer };
|
|
315
372
|
class NotebookVisibleEventProducer {
|
|
316
|
-
listen(notebookPanel, pioneer
|
|
373
|
+
listen(notebookPanel, pioneer) {
|
|
317
374
|
document.addEventListener('visibilitychange', async () => {
|
|
318
|
-
var _a, _b;
|
|
319
375
|
if (document.visibilityState === 'visible' &&
|
|
320
376
|
document.contains(notebookPanel.node)) {
|
|
321
377
|
const event = {
|
|
@@ -325,7 +381,12 @@ class NotebookVisibleEventProducer {
|
|
|
325
381
|
cells: getVisibleCells(notebookPanel)
|
|
326
382
|
}
|
|
327
383
|
};
|
|
328
|
-
|
|
384
|
+
pioneer.exporters.forEach(async (exporter) => {
|
|
385
|
+
var _a, _b, _c;
|
|
386
|
+
if ((_a = exporter.activeEvents) === null || _a === void 0 ? void 0 : _a.map(o => o.name).includes(NotebookVisibleEventProducer.id)) {
|
|
387
|
+
await pioneer.publishEvent(notebookPanel, event, exporter, (_c = (_b = exporter.activeEvents) === null || _b === void 0 ? void 0 : _b.find(o => o.name == NotebookVisibleEventProducer.id)) === null || _c === void 0 ? void 0 : _c.logWholeNotebook);
|
|
388
|
+
}
|
|
389
|
+
});
|
|
329
390
|
}
|
|
330
391
|
});
|
|
331
392
|
}
|
package/lib/utils.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { JupyterFrontEnd } from '@jupyterlab/application';
|
|
2
|
+
import { IMainMenu } from '@jupyterlab/mainmenu';
|
|
3
|
+
import { Exporter } from './types';
|
|
4
|
+
export declare const sendInfoNotification: (exporters: Exporter[], isGlobal: boolean) => void;
|
|
5
|
+
export declare const addInfoToHelpMenu: (app: JupyterFrontEnd, mainMenu: IMainMenu, version: string) => void;
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Dialog, showDialog, Notification } from '@jupyterlab/apputils';
|
|
3
|
+
export const sendInfoNotification = (exporters, isGlobal) => {
|
|
4
|
+
const exporterMessage = exporters
|
|
5
|
+
.map(each => { var _a; return ((_a = each.args) === null || _a === void 0 ? void 0 : _a.id) || each.type; })
|
|
6
|
+
.join(' & ');
|
|
7
|
+
let message;
|
|
8
|
+
if (isGlobal && exporterMessage) {
|
|
9
|
+
message = `Telemetry data is being logged to ${exporterMessage} through jupyterlab-pioneer. \n See Help menu -> JupyterLab Pioneer for more details.`;
|
|
10
|
+
}
|
|
11
|
+
else if (isGlobal && !exporterMessage) {
|
|
12
|
+
message = `Telemetry data is being logged through jupyterlab-pioneer. \n See Help menu -> JupyterLab Pioneer for more details.`;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
message = `Embedded telemetry settings loaded. Telemetry data is being logged to ${exporterMessage} now.`;
|
|
16
|
+
}
|
|
17
|
+
Notification.info(message, { autoClose: 20000 });
|
|
18
|
+
};
|
|
19
|
+
export const addInfoToHelpMenu = (app, mainMenu, version) => {
|
|
20
|
+
// Add extension info to help menu
|
|
21
|
+
app.commands.addCommand('help:pioneer', {
|
|
22
|
+
label: 'JupyterLab Pioneer',
|
|
23
|
+
execute: () => {
|
|
24
|
+
// Create the header of the dialog
|
|
25
|
+
const title = (React.createElement("span", { className: "jp-About-header" },
|
|
26
|
+
"JupyterLab Pioneer",
|
|
27
|
+
React.createElement("div", { className: "jp-About-header-info" },
|
|
28
|
+
React.createElement("span", { className: "jp-About-version-info" },
|
|
29
|
+
React.createElement("span", { className: "jp-About-version" },
|
|
30
|
+
"Version ",
|
|
31
|
+
version)))));
|
|
32
|
+
// Create the body of the dialog
|
|
33
|
+
const contributorsURL = 'https://github.com/educational-technology-collective/jupyterlab-pioneer/graphs/contributors';
|
|
34
|
+
const docURL = 'https://jupyterlab-pioneer.readthedocs.io/en/latest/';
|
|
35
|
+
const gitURL = 'https://github.com/educational-technology-collective/jupyterlab-pioneer';
|
|
36
|
+
const externalLinks = (React.createElement("span", { className: "jp-About-externalLinks" },
|
|
37
|
+
React.createElement("a", { href: contributorsURL, target: "_blank", rel: "noopener noreferrer", className: "jp-Button-flat" }, "CONTRIBUTOR LIST"),
|
|
38
|
+
React.createElement("a", { href: docURL, target: "_blank", rel: "noopener noreferrer", className: "jp-Button-flat" }, "DOCUMENTATION"),
|
|
39
|
+
React.createElement("a", { href: gitURL, target: "_blank", rel: "noopener noreferrer", className: "jp-Button-flat" }, "GITHUB REPO")));
|
|
40
|
+
const copyright = (React.createElement("span", { className: "jp-About-copyright" }, "\u00A9 2023 Educational Technology Collective"));
|
|
41
|
+
const body = (React.createElement("div", { className: "jp-About-body" },
|
|
42
|
+
externalLinks,
|
|
43
|
+
copyright));
|
|
44
|
+
return showDialog({
|
|
45
|
+
title,
|
|
46
|
+
body,
|
|
47
|
+
buttons: [
|
|
48
|
+
Dialog.createButton({
|
|
49
|
+
label: 'Dismiss',
|
|
50
|
+
className: 'jp-About-button jp-mod-reject jp-mod-styled'
|
|
51
|
+
})
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
mainMenu.helpMenu.addGroup([{ command: 'help:pioneer' }]);
|
|
57
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jupyterlab-pioneer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "A JupyterLab extension.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -55,7 +55,9 @@
|
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"@jupyterlab/application": "^4.0.0",
|
|
58
|
+
"@jupyterlab/apputils": "^4.1.9",
|
|
58
59
|
"@jupyterlab/coreutils": "^6.0.0",
|
|
60
|
+
"@jupyterlab/mainmenu": "^4.0.9",
|
|
59
61
|
"@jupyterlab/notebook": "^4.0.5",
|
|
60
62
|
"@jupyterlab/services": "^7.0.0"
|
|
61
63
|
},
|