@jupyter/collaboration 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.
- package/lib/index.d.ts +2 -1
- package/lib/index.js +2 -1
- package/lib/sharedlink.d.ts +18 -0
- package/lib/sharedlink.js +122 -0
- package/package.json +8 -8
- package/style/base.css +4 -0
- package/lib/utils.d.ts +0 -8
- package/lib/utils.js +0 -35
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Dialog } from '@jupyterlab/apputils';
|
|
2
|
+
import { ITranslator } from '@jupyterlab/translation';
|
|
3
|
+
/**
|
|
4
|
+
* Shared link dialog options
|
|
5
|
+
*/
|
|
6
|
+
export interface ISharedLinkDialogOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Translation object.
|
|
9
|
+
*/
|
|
10
|
+
translator?: ITranslator | null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Show the shared link dialog
|
|
14
|
+
*
|
|
15
|
+
* @param options Shared link dialog options
|
|
16
|
+
* @returns Dialog result
|
|
17
|
+
*/
|
|
18
|
+
export declare function showSharedLinkDialog({ translator }: ISharedLinkDialogOptions): Promise<Dialog.IResult<string>>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
import { Dialog, showDialog } from '@jupyterlab/apputils';
|
|
4
|
+
import { PageConfig, URLExt } from '@jupyterlab/coreutils';
|
|
5
|
+
import { nullTranslator } from '@jupyterlab/translation';
|
|
6
|
+
import { Widget } from '@lumino/widgets';
|
|
7
|
+
/**
|
|
8
|
+
* Show the shared link dialog
|
|
9
|
+
*
|
|
10
|
+
* @param options Shared link dialog options
|
|
11
|
+
* @returns Dialog result
|
|
12
|
+
*/
|
|
13
|
+
export async function showSharedLinkDialog({ translator }) {
|
|
14
|
+
const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('collaboration');
|
|
15
|
+
const token = PageConfig.getToken();
|
|
16
|
+
const url = new URL(URLExt.normalize(PageConfig.getUrl({
|
|
17
|
+
workspace: PageConfig.defaultWorkspace
|
|
18
|
+
})));
|
|
19
|
+
return showDialog({
|
|
20
|
+
title: trans.__('Share Jupyter Server Link'),
|
|
21
|
+
body: new SharedLinkBody(url.toString(), token, PageConfig.getOption('hubUser') !== '', trans),
|
|
22
|
+
buttons: [
|
|
23
|
+
Dialog.cancelButton(),
|
|
24
|
+
Dialog.okButton({
|
|
25
|
+
label: trans.__('Copy Link'),
|
|
26
|
+
caption: trans.__('Copy the link to the Jupyter Server')
|
|
27
|
+
})
|
|
28
|
+
]
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
class SharedLinkBody extends Widget {
|
|
32
|
+
constructor(_url, _token, _behindHub, _trans) {
|
|
33
|
+
super();
|
|
34
|
+
this._url = _url;
|
|
35
|
+
this._token = _token;
|
|
36
|
+
this._behindHub = _behindHub;
|
|
37
|
+
this._trans = _trans;
|
|
38
|
+
this._tokenCheckbox = null;
|
|
39
|
+
this.onTokenChange = (e) => {
|
|
40
|
+
const target = e.target;
|
|
41
|
+
this.updateContent(target === null || target === void 0 ? void 0 : target.checked);
|
|
42
|
+
};
|
|
43
|
+
this._warning = document.createElement('div');
|
|
44
|
+
this.populateBody(this.node);
|
|
45
|
+
this.addClass('jp-shared-link-body');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Returns the input value.
|
|
49
|
+
*/
|
|
50
|
+
getValue() {
|
|
51
|
+
var _a;
|
|
52
|
+
const withToken = ((_a = this._tokenCheckbox) === null || _a === void 0 ? void 0 : _a.checked) === true;
|
|
53
|
+
if (withToken) {
|
|
54
|
+
const url_ = new URL(this._url);
|
|
55
|
+
url_.searchParams.set('token', this._token);
|
|
56
|
+
return url_.toString();
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return this._url;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
onAfterAttach(msg) {
|
|
63
|
+
var _a;
|
|
64
|
+
super.onAfterAttach(msg);
|
|
65
|
+
(_a = this._tokenCheckbox) === null || _a === void 0 ? void 0 : _a.addEventListener('change', this.onTokenChange);
|
|
66
|
+
}
|
|
67
|
+
onBeforeDetach(msg) {
|
|
68
|
+
var _a;
|
|
69
|
+
(_a = this._tokenCheckbox) === null || _a === void 0 ? void 0 : _a.removeEventListener('change', this.onTokenChange);
|
|
70
|
+
super.onBeforeDetach(msg);
|
|
71
|
+
}
|
|
72
|
+
updateContent(withToken) {
|
|
73
|
+
this._warning.innerHTML = '';
|
|
74
|
+
const urlInput = this.node.querySelector('input[readonly]');
|
|
75
|
+
if (withToken) {
|
|
76
|
+
if (urlInput) {
|
|
77
|
+
const url_ = new URL(this._url);
|
|
78
|
+
url_.searchParams.set('token', this._token.slice(0, 5));
|
|
79
|
+
urlInput.value = url_.toString() + '…';
|
|
80
|
+
}
|
|
81
|
+
this._warning.appendChild(document.createElement('h3')).textContent =
|
|
82
|
+
this._trans.__('Security warning!');
|
|
83
|
+
this._warning.insertAdjacentText('beforeend', this._trans.__('Anyone with this link has full access to your notebook server, including all your files!'));
|
|
84
|
+
this._warning.insertAdjacentHTML('beforeend', '<br>');
|
|
85
|
+
this._warning.insertAdjacentText('beforeend', this._trans.__('Please be careful who you share it with.'));
|
|
86
|
+
this._warning.insertAdjacentHTML('beforeend', '<br>');
|
|
87
|
+
if (this._behindHub) {
|
|
88
|
+
this._warning.insertAdjacentText('beforeend', // You can restart the server to revoke the token in a JupyterHub
|
|
89
|
+
this._trans.__('They will be able to access this server AS YOU.'));
|
|
90
|
+
this._warning.insertAdjacentHTML('beforeend', '<br>');
|
|
91
|
+
this._warning.insertAdjacentText('beforeend', this._trans.__('To revoke access, go to File -> Hub Control Panel, and restart your server.'));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
this._warning.insertAdjacentText('beforeend',
|
|
95
|
+
// Elsewhere, you *must* shut down your server - no way to revoke it
|
|
96
|
+
this._trans.__('Currently, there is no way to revoke access other than shutting down your server.'));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
if (urlInput) {
|
|
101
|
+
urlInput.value = this._url;
|
|
102
|
+
}
|
|
103
|
+
if (this._behindHub) {
|
|
104
|
+
this._warning.insertAdjacentText('beforeend', this._trans.__('Only users with `access:servers` permissions for this server will be able to use this link.'));
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
this._warning.insertAdjacentText('beforeend', this._trans.__('Only authenticated users will be able to use this link.'));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
populateBody(dialogBody) {
|
|
112
|
+
dialogBody.insertAdjacentHTML('afterbegin', `<input readonly value="${this._url}">`);
|
|
113
|
+
if (this._token) {
|
|
114
|
+
const label = dialogBody.appendChild(document.createElement('label'));
|
|
115
|
+
label.insertAdjacentHTML('beforeend', '<input type="checkbox">');
|
|
116
|
+
this._tokenCheckbox = label.firstChild;
|
|
117
|
+
label.insertAdjacentText('beforeend', this._trans.__('Include token in URL'));
|
|
118
|
+
dialogBody.insertAdjacentElement('beforeend', this._warning);
|
|
119
|
+
this.updateContent(false);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyter/collaboration",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.9",
|
|
4
4
|
"description": "JupyterLab - Real-Time Collaboration Widgets",
|
|
5
5
|
"homepage": "https://github.com/jupyterlab/jupyter_collaboration",
|
|
6
6
|
"bugs": {
|
|
@@ -41,13 +41,13 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@codemirror/state": "^6.2.0",
|
|
43
43
|
"@codemirror/view": "^6.7.0",
|
|
44
|
-
"@jupyterlab/apputils": "^4.0.0
|
|
45
|
-
"@jupyterlab/coreutils": "^6.0.0
|
|
46
|
-
"@jupyterlab/services": "^7.0.0
|
|
47
|
-
"@jupyterlab/ui-components": "^4.0.0
|
|
48
|
-
"@lumino/coreutils": "^2.
|
|
44
|
+
"@jupyterlab/apputils": "^4.0.0",
|
|
45
|
+
"@jupyterlab/coreutils": "^6.0.0",
|
|
46
|
+
"@jupyterlab/services": "^7.0.0",
|
|
47
|
+
"@jupyterlab/ui-components": "^4.0.0",
|
|
48
|
+
"@lumino/coreutils": "^2.1.0",
|
|
49
49
|
"@lumino/virtualdom": "^2.0.0",
|
|
50
|
-
"@lumino/widgets": "^2.
|
|
50
|
+
"@lumino/widgets": "^2.1.0",
|
|
51
51
|
"react": "^18.2.0",
|
|
52
52
|
"y-protocols": "^1.0.5",
|
|
53
53
|
"yjs": "^13.5.40"
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/react": "^18.0.27",
|
|
57
57
|
"rimraf": "^4.1.2",
|
|
58
|
-
"typescript": "~5.0.
|
|
58
|
+
"typescript": "~5.0.4"
|
|
59
59
|
},
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public"
|
package/style/base.css
CHANGED
package/lib/utils.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Call the API extension
|
|
3
|
-
*
|
|
4
|
-
* @param endPoint API REST end point for the extension
|
|
5
|
-
* @param init Initial values for the request
|
|
6
|
-
* @returns The response body interpreted as JSON
|
|
7
|
-
*/
|
|
8
|
-
export declare function requestAPI<T>(endPoint?: string, init?: RequestInit): Promise<T>;
|
package/lib/utils.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Jupyter Development Team.
|
|
2
|
-
// Distributed under the terms of the Modified BSD License.
|
|
3
|
-
import { URLExt } from '@jupyterlab/coreutils';
|
|
4
|
-
import { ServerConnection } from '@jupyterlab/services';
|
|
5
|
-
/**
|
|
6
|
-
* Call the API extension
|
|
7
|
-
*
|
|
8
|
-
* @param endPoint API REST end point for the extension
|
|
9
|
-
* @param init Initial values for the request
|
|
10
|
-
* @returns The response body interpreted as JSON
|
|
11
|
-
*/
|
|
12
|
-
export async function requestAPI(endPoint = '', init = {}) {
|
|
13
|
-
const settings = ServerConnection.makeSettings();
|
|
14
|
-
const requestUrl = URLExt.join(settings.baseUrl, endPoint);
|
|
15
|
-
let response;
|
|
16
|
-
try {
|
|
17
|
-
response = await ServerConnection.makeRequest(requestUrl, init, settings);
|
|
18
|
-
}
|
|
19
|
-
catch (error) {
|
|
20
|
-
throw new ServerConnection.NetworkError(error);
|
|
21
|
-
}
|
|
22
|
-
let data = await response.text();
|
|
23
|
-
if (data.length > 0) {
|
|
24
|
-
try {
|
|
25
|
-
data = JSON.parse(data);
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
console.log('Not a JSON response body.', response);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
if (!response.ok) {
|
|
32
|
-
throw new ServerConnection.ResponseError(response, data.message || data);
|
|
33
|
-
}
|
|
34
|
-
return data;
|
|
35
|
-
}
|