@jupyter/collaboration-extension 1.0.0-alpha.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 ADDED
@@ -0,0 +1,3 @@
1
+ # @jupyter/collaboration-extension
2
+
3
+ A JupyterLab package which provides a set of plugins for Real Time Collaboration.
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * @module collaboration-extension
4
+ */
5
+ import { JupyterFrontEndPlugin } from '@jupyterlab/application';
6
+ import { IAwareness, IUserMenu } from '@jupyter/collaboration';
7
+ /**
8
+ * Jupyter plugin providing the IUserMenu.
9
+ */
10
+ export declare const userMenuPlugin: JupyterFrontEndPlugin<IUserMenu>;
11
+ /**
12
+ * Jupyter plugin adding the IUserMenu to the menu bar if collaborative flag enabled.
13
+ */
14
+ export declare const menuBarPlugin: JupyterFrontEndPlugin<void>;
15
+ /**
16
+ * Jupyter plugin creating a global awareness for RTC.
17
+ */
18
+ export declare const rtcGlobalAwarenessPlugin: JupyterFrontEndPlugin<IAwareness>;
19
+ /**
20
+ * Jupyter plugin adding the RTC information to the application left panel if collaborative flag enabled.
21
+ */
22
+ export declare const rtcPanelPlugin: JupyterFrontEndPlugin<void>;
@@ -0,0 +1,131 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+ /**
4
+ * @packageDocumentation
5
+ * @module collaboration-extension
6
+ */
7
+ import { PageConfig } from '@jupyterlab/coreutils';
8
+ import { DOMUtils } from '@jupyterlab/apputils';
9
+ import { AwarenessMock, CollaboratorsPanel, IGlobalAwareness, IUserMenu, RendererUserMenu, UserInfoPanel, UserMenu } from '@jupyter/collaboration';
10
+ import { SidePanel, usersIcon } from '@jupyterlab/ui-components';
11
+ import { MenuBar } from '@lumino/widgets';
12
+ import { URLExt } from '@jupyterlab/coreutils';
13
+ import { ServerConnection } from '@jupyterlab/services';
14
+ import { IStateDB } from '@jupyterlab/statedb';
15
+ import { ITranslator } from '@jupyterlab/translation';
16
+ import * as Y from 'yjs';
17
+ import { Awareness } from 'y-protocols/awareness';
18
+ import { WebsocketProvider } from 'y-websocket';
19
+ /**
20
+ * Jupyter plugin providing the IUserMenu.
21
+ */
22
+ export const userMenuPlugin = {
23
+ id: '@jupyter/collaboration-extension:userMenu',
24
+ autoStart: true,
25
+ requires: [],
26
+ provides: IUserMenu,
27
+ activate: (app) => {
28
+ const { commands } = app;
29
+ const { user } = app.serviceManager;
30
+ return new UserMenu({ commands, user });
31
+ }
32
+ };
33
+ /**
34
+ * Jupyter plugin adding the IUserMenu to the menu bar if collaborative flag enabled.
35
+ */
36
+ export const menuBarPlugin = {
37
+ id: '@jupyter/collaboration-extension:userMenuBar',
38
+ autoStart: true,
39
+ requires: [IUserMenu],
40
+ activate: async (app, menu) => {
41
+ const { shell } = app;
42
+ const { user } = app.serviceManager;
43
+ if (PageConfig.getOption('collaborative') !== 'true') {
44
+ return;
45
+ }
46
+ const menuBar = new MenuBar({
47
+ forceItemsPosition: {
48
+ forceX: false,
49
+ forceY: false
50
+ },
51
+ renderer: new RendererUserMenu(user)
52
+ });
53
+ menuBar.id = 'jp-UserMenu';
54
+ user.userChanged.connect(() => menuBar.update());
55
+ menuBar.addMenu(menu);
56
+ shell.add(menuBar, 'top', { rank: 1000 });
57
+ }
58
+ };
59
+ /**
60
+ * Jupyter plugin creating a global awareness for RTC.
61
+ */
62
+ export const rtcGlobalAwarenessPlugin = {
63
+ id: '@jupyter/collaboration-extension:rtcGlobalAwareness',
64
+ autoStart: true,
65
+ requires: [IStateDB],
66
+ provides: IGlobalAwareness,
67
+ activate: (app, state) => {
68
+ const { user } = app.serviceManager;
69
+ const ydoc = new Y.Doc();
70
+ if (PageConfig.getOption('collaborative') !== 'true') {
71
+ return new AwarenessMock(ydoc);
72
+ }
73
+ const awareness = new Awareness(ydoc);
74
+ const server = ServerConnection.makeSettings();
75
+ const url = URLExt.join(server.wsUrl, 'api/yjs');
76
+ new WebsocketProvider(url, 'JupyterLab:globalAwareness', ydoc, {
77
+ awareness: awareness
78
+ });
79
+ const userChanged = () => {
80
+ awareness.setLocalStateField('user', user.identity);
81
+ };
82
+ if (user.isReady) {
83
+ userChanged();
84
+ }
85
+ user.ready.then(userChanged).catch(e => console.error(e));
86
+ user.userChanged.connect(userChanged);
87
+ state.changed.connect(async () => {
88
+ var _a, _b;
89
+ const data = await state.toJSON();
90
+ const current = ((_b = (_a = data['layout-restorer:data']) === null || _a === void 0 ? void 0 : _a.main) === null || _b === void 0 ? void 0 : _b.current) || '';
91
+ if (current.startsWith('editor') || current.startsWith('notebook')) {
92
+ awareness.setLocalStateField('current', current);
93
+ }
94
+ else {
95
+ awareness.setLocalStateField('current', null);
96
+ }
97
+ });
98
+ return awareness;
99
+ }
100
+ };
101
+ /**
102
+ * Jupyter plugin adding the RTC information to the application left panel if collaborative flag enabled.
103
+ */
104
+ export const rtcPanelPlugin = {
105
+ id: '@jupyter/collaboration-extension:rtcPanel',
106
+ autoStart: true,
107
+ requires: [IGlobalAwareness, ITranslator],
108
+ activate: (app, awareness, translator) => {
109
+ if (PageConfig.getOption('collaborative') !== 'true') {
110
+ return;
111
+ }
112
+ const { user } = app.serviceManager;
113
+ const trans = translator.load('jupyterlab');
114
+ const userPanel = new SidePanel();
115
+ userPanel.id = DOMUtils.createDomID();
116
+ userPanel.title.icon = usersIcon;
117
+ userPanel.title.caption = trans.__('Collaboration');
118
+ userPanel.addClass('jp-RTCPanel');
119
+ app.shell.add(userPanel, 'left', { rank: 300 });
120
+ const currentUserPanel = new UserInfoPanel(user);
121
+ currentUserPanel.title.label = trans.__('User info');
122
+ currentUserPanel.title.caption = trans.__('User information');
123
+ userPanel.addWidget(currentUserPanel);
124
+ const fileopener = (path) => {
125
+ void app.commands.execute('docmanager:open', { path });
126
+ };
127
+ const collaboratorsPanel = new CollaboratorsPanel(user, awareness, fileopener);
128
+ collaboratorsPanel.title.label = trans.__('Online Collaborators');
129
+ userPanel.addWidget(collaboratorsPanel);
130
+ }
131
+ };
@@ -0,0 +1,6 @@
1
+ import { JupyterFrontEndPlugin } from '@jupyterlab/application';
2
+ import { IDefaultFileBrowser } from '@jupyterlab/filebrowser';
3
+ /**
4
+ * The default file browser factory provider.
5
+ */
6
+ export declare const defaultFileBrowser: JupyterFrontEndPlugin<IDefaultFileBrowser>;
@@ -0,0 +1,79 @@
1
+ import { ILabShell, IRouter, JupyterFrontEnd } from '@jupyterlab/application';
2
+ import { IDefaultFileBrowser, IFileBrowserFactory } from '@jupyterlab/filebrowser';
3
+ import { YDrive } from '@jupyter/docprovider';
4
+ /**
5
+ * The command IDs used by the file browser plugin.
6
+ */
7
+ var CommandIDs;
8
+ (function (CommandIDs) {
9
+ CommandIDs.openPath = 'filebrowser:open-path';
10
+ })(CommandIDs || (CommandIDs = {}));
11
+ /**
12
+ * The default file browser factory provider.
13
+ */
14
+ export const defaultFileBrowser = {
15
+ id: '@jupyter/collaboration-extension:defaultFileBrowser',
16
+ provides: IDefaultFileBrowser,
17
+ requires: [IFileBrowserFactory],
18
+ optional: [IRouter, JupyterFrontEnd.ITreeResolver, ILabShell],
19
+ activate: async (app, fileBrowserFactory, router, tree, labShell) => {
20
+ console.debug('@jupyter/collaboration-extension:defaultFileBrowser: activated');
21
+ const { commands } = app;
22
+ const drive = new YDrive(app.serviceManager.user);
23
+ app.serviceManager.contents.addDrive(drive);
24
+ // Manually restore and load the default file browser.
25
+ const defaultBrowser = fileBrowserFactory.createFileBrowser('filebrowser', {
26
+ auto: false,
27
+ restore: false,
28
+ driveName: 'YDrive'
29
+ });
30
+ void Private.restoreBrowser(defaultBrowser, commands, router, tree, labShell);
31
+ return defaultBrowser;
32
+ }
33
+ };
34
+ var Private;
35
+ (function (Private) {
36
+ /**
37
+ * Restores file browser state and overrides state if tree resolver resolves.
38
+ */
39
+ async function restoreBrowser(browser, commands, router, tree, labShell) {
40
+ const restoring = 'jp-mod-restoring';
41
+ browser.addClass(restoring);
42
+ if (!router) {
43
+ await browser.model.restore(browser.id);
44
+ await browser.model.refresh();
45
+ browser.removeClass(restoring);
46
+ return;
47
+ }
48
+ const listener = async () => {
49
+ router.routed.disconnect(listener);
50
+ const paths = await (tree === null || tree === void 0 ? void 0 : tree.paths);
51
+ if ((paths === null || paths === void 0 ? void 0 : paths.file) || (paths === null || paths === void 0 ? void 0 : paths.browser)) {
52
+ // Restore the model without populating it.
53
+ await browser.model.restore(browser.id, false);
54
+ if (paths.file) {
55
+ await commands.execute(CommandIDs.openPath, {
56
+ path: paths.file,
57
+ dontShowBrowser: true
58
+ });
59
+ }
60
+ if (paths.browser) {
61
+ await commands.execute(CommandIDs.openPath, {
62
+ path: paths.browser,
63
+ dontShowBrowser: true
64
+ });
65
+ }
66
+ }
67
+ else {
68
+ await browser.model.restore(browser.id);
69
+ await browser.model.refresh();
70
+ }
71
+ browser.removeClass(restoring);
72
+ if (labShell === null || labShell === void 0 ? void 0 : labShell.isEmpty('main')) {
73
+ void commands.execute('launcher:create');
74
+ }
75
+ };
76
+ router.routed.connect(listener);
77
+ }
78
+ Private.restoreBrowser = restoreBrowser;
79
+ })(Private || (Private = {}));
package/lib/index.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * @module collaboration-extension
4
+ */
5
+ import { JupyterFrontEndPlugin } from '@jupyterlab/application';
6
+ /**
7
+ * Export the plugins as default.
8
+ */
9
+ declare const plugins: JupyterFrontEndPlugin<any>[];
10
+ export default plugins;
package/lib/index.js ADDED
@@ -0,0 +1,19 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+ /**
4
+ * @packageDocumentation
5
+ * @module collaboration-extension
6
+ */
7
+ import { defaultFileBrowser } from './filebrowser';
8
+ import { userMenuPlugin, menuBarPlugin, rtcGlobalAwarenessPlugin, rtcPanelPlugin } from './collaboration';
9
+ /**
10
+ * Export the plugins as default.
11
+ */
12
+ const plugins = [
13
+ defaultFileBrowser,
14
+ userMenuPlugin,
15
+ menuBarPlugin,
16
+ rtcGlobalAwarenessPlugin,
17
+ rtcPanelPlugin
18
+ ];
19
+ export default plugins;
package/package.json ADDED
@@ -0,0 +1,105 @@
1
+ {
2
+ "name": "@jupyter/collaboration-extension",
3
+ "version": "1.0.0-alpha.0",
4
+ "description": "JupyterLab - Real-Time Collaboration Extension",
5
+ "keywords": [
6
+ "jupyter",
7
+ "jupyterlab",
8
+ "jupyterlab-extension"
9
+ ],
10
+ "homepage": "https://github.com/jupyterlab/jupyter_collaboration",
11
+ "bugs": {
12
+ "url": "https://github.com/jupyterlab/jupyter_collaboration/issues"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/jupyterlab/jupyter_collaboration.git"
17
+ },
18
+ "license": "BSD-3-Clause",
19
+ "author": "Project Jupyter",
20
+ "sideEffects": [
21
+ "style/*.css",
22
+ "style/index.js"
23
+ ],
24
+ "main": "lib/index.js",
25
+ "types": "lib/index.d.ts",
26
+ "style": "style/index.css",
27
+ "styleModule": "style/index.js",
28
+ "directories": {
29
+ "lib": "lib/"
30
+ },
31
+ "files": [
32
+ "lib/*.d.ts",
33
+ "lib/*.js.map",
34
+ "lib/*.js",
35
+ "schema/*.json",
36
+ "style/*.css",
37
+ "style/index.js"
38
+ ],
39
+ "scripts": {
40
+ "build": "jlpm run build:lib && jlpm run build:labextension:dev",
41
+ "build:lib": "tsc",
42
+ "build:prod": "jlpm run clean && jlpm run build:lib && jlpm run build:labextension",
43
+ "build:labextension": "jupyter labextension build .",
44
+ "build:labextension:dev": "jupyter labextension build --development True .",
45
+ "clean": "jlpm run clean:lib",
46
+ "clean:lib": "rimraf lib tsconfig.tsbuildinfo node_modules",
47
+ "clean:labextension": "rimraf ../../jupyter_collaboration/labextension",
48
+ "clean:all": "jlpm run clean:lib && jlpm run clean:labextension",
49
+ "install:extension": "jlpm run build",
50
+ "watch": "run-p watch:src watch:labextension",
51
+ "watch:src": "tsc -w",
52
+ "watch:labextension": "jupyter labextension watch ."
53
+ },
54
+ "dependencies": {
55
+ "@jupyter/collaboration": "^1.0.0-alpha.0",
56
+ "@jupyter/docprovider": "^1.0.0-alpha.0",
57
+ "@jupyterlab/application": "^4.0.0-alpha.18",
58
+ "@jupyterlab/apputils": "^4.0.0-alpha.18",
59
+ "@jupyterlab/coreutils": "^6.0.0-alpha.18",
60
+ "@jupyterlab/filebrowser": "^4.0.0-alpha.18",
61
+ "@jupyterlab/services": "^7.0.0-alpha.18",
62
+ "@jupyterlab/statedb": "^4.0.0-alpha.18",
63
+ "@jupyterlab/translation": "^4.0.0-alpha.18",
64
+ "@jupyterlab/ui-components": "^4.0.0-alpha.33",
65
+ "@lumino/commands": "^2.0.0-alpha.6",
66
+ "@lumino/widgets": "^2.0.0-alpha.6",
67
+ "y-protocols": "^1.0.5",
68
+ "y-websocket": "^1.3.15",
69
+ "yjs": "^13.5.40"
70
+ },
71
+ "devDependencies": {
72
+ "@jupyterlab/builder": "^4.0.0-alpha.18",
73
+ "@types/react": "^18.0.27",
74
+ "npm-run-all": "^4.1.5",
75
+ "rimraf": "~3.0.0",
76
+ "typescript": "~4.7.3"
77
+ },
78
+ "publishConfig": {
79
+ "access": "public"
80
+ },
81
+ "typedoc": {
82
+ "entryPoint": "./src/index.ts",
83
+ "readmeFile": "./README.md",
84
+ "displayName": "@jupyter/collaboration-extension",
85
+ "tsconfig": "./tsconfig.json"
86
+ },
87
+ "jupyterlab": {
88
+ "extension": true,
89
+ "schemaDir": "./schema",
90
+ "outputDir": "../../jupyter_collaboration/labextension",
91
+ "disabledExtensions": [
92
+ "@jupyterlab/filebrowser-extension:defaultFileBrowser"
93
+ ],
94
+ "sharedPackages": {
95
+ "@jupyter/collaboration": {
96
+ "bundled": true,
97
+ "singleton": true
98
+ },
99
+ "@jupyter/docprovider": {
100
+ "bundled": true,
101
+ "singleton": true
102
+ }
103
+ }
104
+ }
105
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "title": "User Menu Bar",
3
+ "description": "User Menu Bar settings.",
4
+ "jupyter.lab.toolbars": {
5
+ "TopBar": [
6
+ {
7
+ "name": "user-menu",
8
+ "rank": 100
9
+ }
10
+ ]
11
+ },
12
+ "properties": {},
13
+ "additionalProperties": false,
14
+ "type": "object"
15
+ }
package/style/base.css ADDED
@@ -0,0 +1,4 @@
1
+ /* -----------------------------------------------------------------------------
2
+ | Copyright (c) Jupyter Development Team.
3
+ | Distributed under the terms of the Modified BSD License.
4
+ |---------------------------------------------------------------------------- */
@@ -0,0 +1,6 @@
1
+ /* -----------------------------------------------------------------------------
2
+ | Copyright (c) Jupyter Development Team.
3
+ | Distributed under the terms of the Modified BSD License.
4
+ |---------------------------------------------------------------------------- */
5
+
6
+ @import url('./base.css');
package/style/index.js ADDED
@@ -0,0 +1,6 @@
1
+ /*-----------------------------------------------------------------------------
2
+ | Copyright (c) Jupyter Development Team.
3
+ | Distributed under the terms of the Modified BSD License.
4
+ |----------------------------------------------------------------------------*/
5
+
6
+ import './base.css';