Skip to content

Commit 3e335b4

Browse files
Create a newDrive class and a DriveFileBrowser widget.
1 parent 45dc4af commit 3e335b4

File tree

3 files changed

+345
-1
lines changed

3 files changed

+345
-1
lines changed

src/browser.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) Jupyter Development Team.
2+
// Distributed under the terms of the Modified BSD License.
3+
4+
/*import { ToolbarButton } from '@jupyterlab/apputils';
5+
6+
import { URLExt } from '@jupyterlab/coreutils';*/
7+
8+
import { FileBrowser } from '@jupyterlab/filebrowser';
9+
10+
/*import { refreshIcon } from '@jupyterlab/ui-components';
11+
12+
import { find } from '@lumino/algorithm';
13+
14+
import { Message } from '@lumino/messaging';
15+
16+
import { ISignal, Signal } from '@lumino/signaling';*/
17+
18+
import { PanelLayout, Widget } from '@lumino/widgets';
19+
import { Drive } from './contents';
20+
21+
export class DriveFileBrowser extends Widget {
22+
constructor(browser: FileBrowser, drive: Drive) {
23+
super();
24+
this.addClass('jp-DrivebBrowser');
25+
this.layout = new PanelLayout();
26+
(this.layout as PanelLayout).addWidget(browser);
27+
}
28+
}

src/contents.ts

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
// Copyright (c) Jupyter Development Team.
2+
// Distributed under the terms of the Modified BSD License.
3+
4+
import { Signal, ISignal } from '@lumino/signaling';
5+
6+
import { DocumentRegistry } from '@jupyterlab/docregistry';
7+
8+
import { Contents, ServerConnection } from '@jupyterlab/services';
9+
10+
/**
11+
* A Contents.IDrive implementation that serves as a read-only
12+
* view onto the drive repositories.
13+
*/
14+
export class Drive implements Contents.IDrive {
15+
/**
16+
* Construct a new drive object.
17+
*
18+
* @param options - The options used to initialize the object.
19+
*/
20+
constructor(registry: DocumentRegistry) {
21+
this._serverSettings = ServerConnection.makeSettings();
22+
}
23+
/**
24+
* The Drive base URL
25+
*/
26+
get baseUrl(): string {
27+
return this._baseUrl;
28+
}
29+
30+
/**
31+
* The Drive base URL is set by the settingsRegistry change hook
32+
*/
33+
set baseUrl(url: string) {
34+
this._baseUrl = url;
35+
}
36+
/**
37+
* The Drive name getter
38+
*/
39+
get name(): string {
40+
return this._name;
41+
}
42+
43+
/**
44+
* The Drive name setter */
45+
set name(name: string) {
46+
this._name = name;
47+
}
48+
49+
/**
50+
* The Drive provider getter
51+
*/
52+
get provider(): string {
53+
return this._provider;
54+
}
55+
56+
/**
57+
* The Drive provider setter */
58+
set provider(name: string) {
59+
this._provider = name;
60+
}
61+
62+
/**
63+
* The Drive is Active getter
64+
*/
65+
get isActive(): boolean {
66+
return this._isActive;
67+
}
68+
69+
/**
70+
* The Drive isActive provider setter */
71+
set isActive(isActive: boolean) {
72+
this._isActive = isActive;
73+
}
74+
75+
/**
76+
* Settings for the notebook server.
77+
*/
78+
get serverSettings(): ServerConnection.ISettings {
79+
return this._serverSettings;
80+
}
81+
82+
/**
83+
* A signal emitted when a file operation takes place.
84+
*/
85+
get fileChanged(): ISignal<this, Contents.IChangedArgs> {
86+
return this._fileChanged;
87+
}
88+
89+
/**
90+
* Test whether the manager has been disposed.
91+
*/
92+
get isDisposed(): boolean {
93+
return this._isDisposed;
94+
}
95+
96+
/**
97+
* Dispose of the resources held by the manager.
98+
*/
99+
dispose(): void {
100+
if (this.isDisposed) {
101+
return;
102+
}
103+
this._isDisposed = true;
104+
Signal.clearData(this);
105+
}
106+
107+
/**
108+
* Get an encoded download url given a file path.
109+
*
110+
* @param path - An absolute POSIX file path on the server.
111+
*
112+
* #### Notes
113+
* It is expected that the path contains no relative paths,
114+
* use [[ContentsManager.getAbsolutePath]] to get an absolute
115+
* path if necessary.
116+
*/
117+
getDownloadUrl(path: string): Promise<string> {
118+
// Parse the path into user/repo/path
119+
console.log('Path is:', path);
120+
return Promise.reject('Empty getDownloadUrl method');
121+
}
122+
123+
get(
124+
path: string,
125+
options?: Contents.IFetchOptions
126+
): Promise<Contents.IModel> {
127+
return Promise.reject('Empty get method');
128+
}
129+
130+
/**
131+
* Create a new untitled file or directory in the specified directory path.
132+
*
133+
* @param options: The options used to create the file.
134+
*
135+
* @returns A promise which resolves with the created file content when the
136+
* file is created.
137+
*/
138+
newUntitled(options: Contents.ICreateOptions = {}): Promise<Contents.IModel> {
139+
return Promise.reject('Repository is read only');
140+
}
141+
142+
/**
143+
* Delete a file.
144+
*
145+
* @param path - The path to the file.
146+
*
147+
* @returns A promise which resolves when the file is deleted.
148+
*/
149+
delete(path: string): Promise<void> {
150+
return Promise.reject('Repository is read only');
151+
}
152+
153+
/**
154+
* Rename a file or directory.
155+
*
156+
* @param path - The original file path.
157+
*
158+
* @param newPath - The new file path.
159+
*
160+
* @returns A promise which resolves with the new file contents model when
161+
* the file is renamed.
162+
*/
163+
rename(path: string, newPath: string): Promise<Contents.IModel> {
164+
return Promise.reject('Repository is read only');
165+
}
166+
167+
/**
168+
* Save a file.
169+
*
170+
* @param path - The desired file path.
171+
*
172+
* @param options - Optional overrides to the model.
173+
*
174+
* @returns A promise which resolves with the file content model when the
175+
* file is saved.
176+
*/
177+
save(
178+
path: string,
179+
options: Partial<Contents.IModel>
180+
): Promise<Contents.IModel> {
181+
return Promise.reject('Repository is read only');
182+
}
183+
184+
/**
185+
* Copy a file into a given directory.
186+
*
187+
* @param path - The original file path.
188+
*
189+
* @param toDir - The destination directory path.
190+
*
191+
* @returns A promise which resolves with the new contents model when the
192+
* file is copied.
193+
*/
194+
copy(fromFile: string, toDir: string): Promise<Contents.IModel> {
195+
return Promise.reject('Repository is read only');
196+
}
197+
198+
/**
199+
* Create a checkpoint for a file.
200+
*
201+
* @param path - The path of the file.
202+
*
203+
* @returns A promise which resolves with the new checkpoint model when the
204+
* checkpoint is created.
205+
*/
206+
createCheckpoint(path: string): Promise<Contents.ICheckpointModel> {
207+
return Promise.reject('Repository is read only');
208+
}
209+
210+
/**
211+
* List available checkpoints for a file.
212+
*
213+
* @param path - The path of the file.
214+
*
215+
* @returns A promise which resolves with a list of checkpoint models for
216+
* the file.
217+
*/
218+
listCheckpoints(path: string): Promise<Contents.ICheckpointModel[]> {
219+
return Promise.resolve([]);
220+
}
221+
222+
/**
223+
* Restore a file to a known checkpoint state.
224+
*
225+
* @param path - The path of the file.
226+
*
227+
* @param checkpointID - The id of the checkpoint to restore.
228+
*
229+
* @returns A promise which resolves when the checkpoint is restored.
230+
*/
231+
restoreCheckpoint(path: string, checkpointID: string): Promise<void> {
232+
return Promise.reject('Repository is read only');
233+
}
234+
235+
/**
236+
* Delete a checkpoint for a file.
237+
*
238+
* @param path - The path of the file.
239+
*
240+
* @param checkpointID - The id of the checkpoint to delete.
241+
*
242+
* @returns A promise which resolves when the checkpoint is deleted.
243+
*/
244+
deleteCheckpoint(path: string, checkpointID: string): Promise<void> {
245+
return Promise.reject('Read only');
246+
}
247+
248+
private _serverSettings: ServerConnection.ISettings;
249+
private _name: string = '';
250+
private _provider: string = '';
251+
private _baseUrl: string = '';
252+
private _isActive: boolean = false;
253+
private _fileChanged = new Signal<this, Contents.IChangedArgs>(this);
254+
private _isDisposed: boolean = false;
255+
}

src/index.ts

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
ILayoutRestorer,
23
JupyterFrontEnd,
34
JupyterFrontEndPlugin
45
} from '@jupyterlab/application';
@@ -10,6 +11,16 @@ import { addJupyterLabThemeChangeListener } from '@jupyter/web-components';
1011
import { Dialog, showDialog } from '@jupyterlab/apputils';
1112
import { DriveListModel, DriveListView, IDrive } from './drivelistmanager';
1213
import { DriveIcon } from './icons';
14+
import { IDocumentManager } from '@jupyterlab/docmanager';
15+
import { ISettingRegistry } from '@jupyterlab/settingregistry';
16+
import { DriveFileBrowser } from './browser';
17+
import { Drive } from './contents';
18+
19+
/**
20+
* The ID for the plugin.
21+
*/
22+
const PLUGIN_ID = '@jupyterlab/jupyter:drives';
23+
const NAMESPACE = 'drive-filebrowser';
1324

1425
namespace CommandIDs {
1526
export const openDrivesDialog = 'drives:open-drives-dialog';
@@ -37,6 +48,52 @@ const plugin: JupyterFrontEndPlugin<void> = {
3748
}
3849
};
3950

51+
/**
52+
* The JupyterLab plugin for the Drives Filebrowser.
53+
*/
54+
const fileBrowserPlugin: JupyterFrontEndPlugin<void> = {
55+
id: PLUGIN_ID,
56+
requires: [IDocumentManager, IFileBrowserFactory, ISettingRegistry],
57+
optional: [ILayoutRestorer],
58+
activate: activateFileBrowser,
59+
autoStart: true
60+
};
61+
62+
/**
63+
* Activate the file browser.
64+
*/
65+
function activateFileBrowser(
66+
app: JupyterFrontEnd,
67+
manager: IDocumentManager,
68+
factory: IFileBrowserFactory,
69+
settingRegistry: ISettingRegistry,
70+
restorer: ILayoutRestorer | null
71+
): void {
72+
// Add the drive backend to the contents manager.
73+
const drive = new Drive(app.docRegistry);
74+
manager.services.contents.addDrive(drive);
75+
76+
// Create the embedded filebrowser.
77+
const browser = factory.createFileBrowser(NAMESPACE, {
78+
driveName: drive.name,
79+
refreshInterval: 300000
80+
});
81+
82+
const driveBrowser = new DriveFileBrowser(browser, drive);
83+
84+
driveBrowser.title.icon = DriveIcon;
85+
driveBrowser.title.iconClass = 'jp-SideBar-tabIcon';
86+
driveBrowser.title.caption = 'Browse Drives';
87+
88+
driveBrowser.id = 'drive-file-browser';
89+
90+
// Add the file browser widget to the application restorer.
91+
if (restorer) {
92+
restorer.add(driveBrowser, NAMESPACE);
93+
}
94+
app.shell.add(driveBrowser, 'left', { rank: 102 });
95+
}
96+
4097
const openDriveDialogPlugin: JupyterFrontEndPlugin<void> = {
4198
id: '@jupyter/drives:widget',
4299
description: 'Open a dialog to select drives to be added in the filebrowser.',
@@ -140,5 +197,9 @@ const openDriveDialogPlugin: JupyterFrontEndPlugin<void> = {
140197
});
141198
}
142199
};
143-
const plugins: JupyterFrontEndPlugin<any>[] = [plugin, openDriveDialogPlugin];
200+
const plugins: JupyterFrontEndPlugin<any>[] = [
201+
plugin,
202+
openDriveDialogPlugin,
203+
fileBrowserPlugin
204+
];
144205
export default plugins;

0 commit comments

Comments
 (0)