@jupyter/collaboration-extension 1.0.0-alpha.7 → 1.0.0-alpha.9

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.
@@ -4,7 +4,7 @@
4
4
  * @packageDocumentation
5
5
  * @module collaboration-extension
6
6
  */
7
- import { DOMUtils } from '@jupyterlab/apputils';
7
+ import { DOMUtils, IToolbarWidgetRegistry } from '@jupyterlab/apputils';
8
8
  import { EditorExtensionRegistry, IEditorExtensionRegistry } from '@jupyterlab/codemirror';
9
9
  import { CollaboratorsPanel, IGlobalAwareness, IUserMenu, remoteUserCursors, RendererUserMenu, UserInfoPanel, UserMenu } from '@jupyter/collaboration';
10
10
  import { SidePanel, usersIcon } from '@jupyterlab/ui-components';
@@ -34,12 +34,11 @@ export const userMenuPlugin = {
34
34
  * Jupyter plugin adding the IUserMenu to the menu bar if collaborative flag enabled.
35
35
  */
36
36
  export const menuBarPlugin = {
37
- id: '@jupyter/collaboration-extension:userMenuBar',
37
+ id: '@jupyter/collaboration-extension:user-menu-bar',
38
38
  description: 'Add user menu to the interface.',
39
39
  autoStart: true,
40
- requires: [IUserMenu],
41
- activate: async (app, menu) => {
42
- const { shell } = app;
40
+ requires: [IUserMenu, IToolbarWidgetRegistry],
41
+ activate: async (app, menu, toolbarRegistry) => {
43
42
  const { user } = app.serviceManager;
44
43
  const menuBar = new MenuBar({
45
44
  forceItemsPosition: {
@@ -51,7 +50,7 @@ export const menuBarPlugin = {
51
50
  menuBar.id = 'jp-UserMenu';
52
51
  user.userChanged.connect(() => menuBar.update());
53
52
  menuBar.addMenu(menu);
54
- shell.add(menuBar, 'top', { rank: 1000 });
53
+ toolbarRegistry.addFactory('TopBar', 'user-menu', () => menuBar);
55
54
  }
56
55
  };
57
56
  /**
@@ -2,18 +2,22 @@ import { JupyterFrontEndPlugin } from '@jupyterlab/application';
2
2
  import { IDefaultFileBrowser } from '@jupyterlab/filebrowser';
3
3
  import { ICollaborativeDrive } from '@jupyter/docprovider';
4
4
  /**
5
- * The default file browser factory provider.
5
+ * The default collaborative drive provider.
6
6
  */
7
7
  export declare const drive: JupyterFrontEndPlugin<ICollaborativeDrive>;
8
8
  /**
9
- * The default file browser factory provider.
9
+ * Plugin to register the shared model factory for the content type 'file'.
10
10
  */
11
11
  export declare const yfile: JupyterFrontEndPlugin<void>;
12
12
  /**
13
- * The default file browser factory provider.
13
+ * Plugin to register the shared model factory for the content type 'notebook'.
14
14
  */
15
15
  export declare const ynotebook: JupyterFrontEndPlugin<void>;
16
16
  /**
17
17
  * The default file browser factory provider.
18
18
  */
19
19
  export declare const defaultFileBrowser: JupyterFrontEndPlugin<IDefaultFileBrowser>;
20
+ /**
21
+ * The default collaborative drive provider.
22
+ */
23
+ export declare const logger: JupyterFrontEndPlugin<void>;
@@ -1,7 +1,15 @@
1
+ /*
2
+ * Copyright (c) Jupyter Development Team.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
1
5
  import { ILabShell, IRouter, JupyterFrontEnd } from '@jupyterlab/application';
6
+ import { Dialog, showDialog } from '@jupyterlab/apputils';
2
7
  import { IDefaultFileBrowser, IFileBrowserFactory } from '@jupyterlab/filebrowser';
3
- import { ITranslator } from '@jupyterlab/translation';
8
+ import { IEditorTracker } from '@jupyterlab/fileeditor';
9
+ import { ILoggerRegistry } from '@jupyterlab/logconsole';
10
+ import { INotebookTracker } from '@jupyterlab/notebook';
4
11
  import { ISettingRegistry } from '@jupyterlab/settingregistry';
12
+ import { ITranslator, nullTranslator } from '@jupyterlab/translation';
5
13
  import { YFile, YNotebook } from '@jupyter/ydoc';
6
14
  import { ICollaborativeDrive, YDrive } from '@jupyter/docprovider';
7
15
  /**
@@ -12,10 +20,11 @@ var CommandIDs;
12
20
  CommandIDs.openPath = 'filebrowser:open-path';
13
21
  })(CommandIDs || (CommandIDs = {}));
14
22
  /**
15
- * The default file browser factory provider.
23
+ * The default collaborative drive provider.
16
24
  */
17
25
  export const drive = {
18
26
  id: '@jupyter/collaboration-extension:drive',
27
+ description: 'The default collaborative drive provider',
19
28
  provides: ICollaborativeDrive,
20
29
  requires: [ITranslator],
21
30
  optional: [],
@@ -27,10 +36,11 @@ export const drive = {
27
36
  }
28
37
  };
29
38
  /**
30
- * The default file browser factory provider.
39
+ * Plugin to register the shared model factory for the content type 'file'.
31
40
  */
32
41
  export const yfile = {
33
42
  id: '@jupyter/collaboration-extension:yfile',
43
+ description: "Plugin to register the shared model factory for the content type 'file'",
34
44
  autoStart: true,
35
45
  requires: [ICollaborativeDrive],
36
46
  optional: [],
@@ -42,10 +52,11 @@ export const yfile = {
42
52
  }
43
53
  };
44
54
  /**
45
- * The default file browser factory provider.
55
+ * Plugin to register the shared model factory for the content type 'notebook'.
46
56
  */
47
57
  export const ynotebook = {
48
58
  id: '@jupyter/collaboration-extension:ynotebook',
59
+ description: "Plugin to register the shared model factory for the content type 'notebook'",
49
60
  autoStart: true,
50
61
  requires: [ICollaborativeDrive],
51
62
  optional: [ISettingRegistry],
@@ -78,6 +89,7 @@ export const ynotebook = {
78
89
  */
79
90
  export const defaultFileBrowser = {
80
91
  id: '@jupyter/collaboration-extension:defaultFileBrowser',
92
+ description: 'The default file browser factory provider',
81
93
  provides: IDefaultFileBrowser,
82
94
  requires: [ICollaborativeDrive, IFileBrowserFactory],
83
95
  optional: [
@@ -99,6 +111,72 @@ export const defaultFileBrowser = {
99
111
  return defaultBrowser;
100
112
  }
101
113
  };
114
+ /**
115
+ * The default collaborative drive provider.
116
+ */
117
+ export const logger = {
118
+ id: '@jupyter/collaboration-extension:logger',
119
+ description: 'A logging plugin for debugging purposes.',
120
+ autoStart: true,
121
+ optional: [ILoggerRegistry, IEditorTracker, INotebookTracker, ITranslator],
122
+ activate: (app, loggerRegistry, fileTracker, nbTracker, translator) => {
123
+ const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('jupyter_collaboration');
124
+ const schemaID = 'https://schema.jupyter.org/jupyter_collaboration/session/v1';
125
+ if (!loggerRegistry) {
126
+ app.serviceManager.events.stream.connect((_, emission) => {
127
+ var _a, _b;
128
+ if (emission.schema_id === schemaID) {
129
+ console.debug(`[${emission.room}(${emission.path})] ${(_a = emission.action) !== null && _a !== void 0 ? _a : ''}: ${(_b = emission.msg) !== null && _b !== void 0 ? _b : ''}`);
130
+ if (emission.level === 'WARNING') {
131
+ showDialog({
132
+ title: trans.__('Warning'),
133
+ body: trans.__(`Two collaborative sessions are accessing the file ${emission.path} simultaneously.
134
+ \nOpening the same file using different views simultaneously is not supported. Please, close one view; otherwise, you might lose some of your progress.`),
135
+ buttons: [Dialog.okButton()]
136
+ });
137
+ }
138
+ }
139
+ });
140
+ return;
141
+ }
142
+ const loggers = new Map();
143
+ const addLogger = (sender, document) => {
144
+ const logger = loggerRegistry.getLogger(document.context.path);
145
+ loggers.set(document.context.localPath, logger);
146
+ document.disposed.connect(document => {
147
+ loggers.delete(document.context.localPath);
148
+ });
149
+ };
150
+ if (fileTracker) {
151
+ fileTracker.widgetAdded.connect(addLogger);
152
+ }
153
+ if (nbTracker) {
154
+ nbTracker.widgetAdded.connect(addLogger);
155
+ }
156
+ void (async () => {
157
+ var _a, _b;
158
+ const { events } = app.serviceManager;
159
+ for await (const emission of events.stream) {
160
+ if (emission.schema_id === schemaID) {
161
+ const logger = loggers.get(emission.path);
162
+ logger === null || logger === void 0 ? void 0 : logger.log({
163
+ type: 'text',
164
+ level: emission.level.toLowerCase(),
165
+ data: `[${emission.room}] ${(_a = emission.action) !== null && _a !== void 0 ? _a : ''}: ${(_b = emission.msg) !== null && _b !== void 0 ? _b : ''}`
166
+ });
167
+ if (emission.level === 'WARNING') {
168
+ showDialog({
169
+ title: trans.__('Warning'),
170
+ body: trans.__(`Two collaborative sessions are accessing the file %1 simultaneously.
171
+ \n'Opening a document with multiple views simultaneously is not supported. Please close one view; otherwise, you might lose some of your progress.`, emission.path),
172
+ buttons: [Dialog.warnButton({ label: trans.__('Ok') })]
173
+ });
174
+ }
175
+ }
176
+ }
177
+ })();
178
+ }
179
+ };
102
180
  var Private;
103
181
  (function (Private) {
104
182
  /**
package/lib/index.js CHANGED
@@ -4,8 +4,9 @@
4
4
  * @packageDocumentation
5
5
  * @module collaboration-extension
6
6
  */
7
- import { drive, yfile, ynotebook, defaultFileBrowser } from './filebrowser';
7
+ import { drive, yfile, ynotebook, defaultFileBrowser, logger } from './filebrowser';
8
8
  import { userMenuPlugin, menuBarPlugin, rtcGlobalAwarenessPlugin, rtcPanelPlugin, userEditorCursors } from './collaboration';
9
+ import { sharedLink } from './sharedlink';
9
10
  /**
10
11
  * Export the plugins as default.
11
12
  */
@@ -14,10 +15,12 @@ const plugins = [
14
15
  yfile,
15
16
  ynotebook,
16
17
  defaultFileBrowser,
18
+ logger,
17
19
  userMenuPlugin,
18
20
  menuBarPlugin,
19
21
  rtcGlobalAwarenessPlugin,
20
22
  rtcPanelPlugin,
23
+ sharedLink,
21
24
  userEditorCursors
22
25
  ];
23
26
  export default plugins;
@@ -0,0 +1,5 @@
1
+ import { JupyterFrontEndPlugin } from '@jupyterlab/application';
2
+ /**
3
+ * Plugin to share the URL of the running Jupyter Server
4
+ */
5
+ export declare const sharedLink: JupyterFrontEndPlugin<void>;
@@ -0,0 +1,43 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+ import { Clipboard, ICommandPalette } from '@jupyterlab/apputils';
4
+ import { ITranslator, nullTranslator } from '@jupyterlab/translation';
5
+ import { shareIcon } from '@jupyterlab/ui-components';
6
+ import { showSharedLinkDialog } from '@jupyter/collaboration';
7
+ /**
8
+ * The command IDs used by the plugin.
9
+ */
10
+ var CommandIDs;
11
+ (function (CommandIDs) {
12
+ CommandIDs.share = 'collaboration:shared-link';
13
+ })(CommandIDs || (CommandIDs = {}));
14
+ /**
15
+ * Plugin to share the URL of the running Jupyter Server
16
+ */
17
+ export const sharedLink = {
18
+ id: '@jupyter/collaboration-extension:shared-link',
19
+ autoStart: true,
20
+ optional: [ICommandPalette, ITranslator],
21
+ activate: async (app, palette, translator) => {
22
+ const { commands } = app;
23
+ const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('collaboration');
24
+ commands.addCommand(CommandIDs.share, {
25
+ label: trans.__('Generate a Shared Link'),
26
+ icon: shareIcon,
27
+ execute: async () => {
28
+ const result = await showSharedLinkDialog({
29
+ translator
30
+ });
31
+ if (result.button.accept && result.value) {
32
+ Clipboard.copyToSystem(result.value);
33
+ }
34
+ }
35
+ });
36
+ if (palette) {
37
+ palette.addItem({
38
+ command: CommandIDs.share,
39
+ category: trans.__('Server')
40
+ });
41
+ }
42
+ }
43
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jupyter/collaboration-extension",
3
- "version": "1.0.0-alpha.7",
3
+ "version": "1.0.0-alpha.9",
4
4
  "description": "JupyterLab - Real-Time Collaboration Extension",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -53,30 +53,34 @@
53
53
  "watch:labextension": "jupyter labextension watch ."
54
54
  },
55
55
  "dependencies": {
56
- "@jupyter/collaboration": "^1.0.0-alpha.7",
57
- "@jupyter/docprovider": "^1.0.0-alpha.7",
58
- "@jupyterlab/application": "^4.0.0-beta.0",
59
- "@jupyterlab/apputils": "^4.0.0-beta.0",
60
- "@jupyterlab/codemirror": "^4.0.0-beta.0",
61
- "@jupyterlab/coreutils": "^6.0.0-beta.0",
62
- "@jupyterlab/filebrowser": "^4.0.0-beta.0",
63
- "@jupyterlab/services": "^7.0.0-beta.0",
64
- "@jupyterlab/settingregistry": "^4.0.0-beta.0",
65
- "@jupyterlab/statedb": "^4.0.0-beta.0",
66
- "@jupyterlab/translation": "^4.0.0-beta.0",
67
- "@jupyterlab/ui-components": "^4.0.0-beta.0",
68
- "@lumino/commands": "^2.0.0",
69
- "@lumino/widgets": "^2.0.0",
56
+ "@jupyter/collaboration": "^1.0.0-alpha.9",
57
+ "@jupyter/docprovider": "^1.0.0-alpha.9",
58
+ "@jupyterlab/application": "^4.0.0",
59
+ "@jupyterlab/apputils": "^4.0.0",
60
+ "@jupyterlab/codemirror": "^4.0.0",
61
+ "@jupyterlab/coreutils": "^6.0.0",
62
+ "@jupyterlab/docregistry": "^4.0.0",
63
+ "@jupyterlab/filebrowser": "^4.0.0",
64
+ "@jupyterlab/fileeditor": "^4.0.0",
65
+ "@jupyterlab/logconsole": "^4.0.0",
66
+ "@jupyterlab/notebook": "^4.0.0",
67
+ "@jupyterlab/services": "^7.0.0",
68
+ "@jupyterlab/settingregistry": "^4.0.0",
69
+ "@jupyterlab/statedb": "^4.0.0",
70
+ "@jupyterlab/translation": "^4.0.0",
71
+ "@jupyterlab/ui-components": "^4.0.0",
72
+ "@lumino/commands": "^2.1.0",
73
+ "@lumino/widgets": "^2.1.0",
70
74
  "y-protocols": "^1.0.5",
71
75
  "y-websocket": "^1.3.15",
72
76
  "yjs": "^13.5.40"
73
77
  },
74
78
  "devDependencies": {
75
- "@jupyterlab/builder": "^4.0.0-beta.0",
76
- "@types/react": "^18.0.27",
79
+ "@jupyterlab/builder": "^4.0.0",
80
+ "@types/react": "~18.0.26",
77
81
  "npm-run-all": "^4.1.5",
78
82
  "rimraf": "^4.1.2",
79
- "typescript": "~5.0.2"
83
+ "typescript": "~5.0.4"
80
84
  },
81
85
  "publishConfig": {
82
86
  "access": "public"
@@ -0,0 +1,16 @@
1
+ {
2
+ "title": "Shared link",
3
+ "description": "Shared link settings",
4
+ "jupyter.lab.toolbars": {
5
+ "TopBar": [
6
+ {
7
+ "name": "@jupyter/collaboration:shared-link",
8
+ "command": "collaboration:shared-link",
9
+ "rank": 99
10
+ }
11
+ ]
12
+ },
13
+ "properties": {},
14
+ "additionalProperties": false,
15
+ "type": "object"
16
+ }