Skip to content

Commit

Permalink
add commands to switch to another drive and create a new drive
Browse files Browse the repository at this point in the history
  • Loading branch information
DenisaCG committed Mar 13, 2024
1 parent 9dc6950 commit d74276c
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 33 deletions.
13 changes: 8 additions & 5 deletions schema/file-browser-toolbar.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
"jupyter.lab.toolbars": {
"DriveBrowser": [
{
"name": "new-directory",
"command": "filebrowser:create-new-directory",
"rank": 10
"name": "drive",
"command": "drives:open-change-drive-dialog",
"rank": 35
},
{ "name": "uploader", "rank": 20 },
{ "name": "refresh", "command": "filebrowser:refresh", "rank": 30 }
{
"name": "new-drive",
"command": "drives:open-new-drive-dialog",
"rank": 40
}
]
},
"title": "jupyter-drives-browser:file-browser-toolbar",
Expand Down
247 changes: 222 additions & 25 deletions src/filebrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,63 @@ import {
IRouter,
JupyterFrontEnd
} from '@jupyterlab/application';
import { showDialog, Dialog } from '@jupyterlab/apputils';
import {
IDefaultFileBrowser,
IFileBrowserFactory,
FileBrowser
FileBrowser,
Uploader
} from '@jupyterlab/filebrowser';

import {
// createToolbarFactory,
IToolbarWidgetRegistry
// setToolbar
createToolbarFactory,
IToolbarWidgetRegistry,
setToolbar
} from '@jupyterlab/apputils';
import { ISettingRegistry } from '@jupyterlab/settingregistry';
import { ITranslator } from '@jupyterlab/translation';

import { CommandRegistry } from '@lumino/commands';

import { Widget } from '@lumino/widgets';
import { Drive } from './s3contents';

import driveSvg from '../style/driveIconFileBrowser.svg';
import { folderIcon } from '@jupyterlab/ui-components';
// import driveSvg from '../style/driveIconFileBrowser.svg';
import { DriveIcon, NewDriveIcon } from './icons';
import {
// folderIcon,
FilenameSearcher,
IScore
} from '@jupyterlab/ui-components';

/**
* The command IDs used to the filebrowser plugin.
*/
namespace CommandIDs {
export const openPath = 'filebrowser:open-path';
export const openChangeDrive = 'drives:open-change-drive-dialog';
export const newDrive = 'drives:open-new-drive-dialog';
}

// const FILE_BROWSER_FACTORY = 'DriveBrowser';
// const FILE_BROWSER_PLUGIN_ID = 'jupyter-drives-browser:file-browser-toolbar';
const FILE_BROWSER_FACTORY = 'DriveBrowser';
const FILE_BROWSER_PLUGIN_ID = 'jupyter-drives-browser:file-browser-toolbar';

/**
* The class name added to the drive filebrowser filterbox node.
*/
const FILTERBOX_CLASS = 'jp-DriveBrowser-filterBox';

/**
* The class name added to file dialogs.
*/
const FILE_DIALOG_CLASS = 'jp-FileDialog';

/**
* The class name added for the new drive label in the switch drive dialog.
*/
const SWITCH_DRIVE_TITLE_CLASS = 'jp-new-drive-title';

// create S3 drive for test purposes
const test_drive = new Drive({
// create S3 drive
const S3Drive = new Drive({
name: 'jupyter-drives-test-bucket-1'
});

Expand All @@ -59,15 +83,15 @@ export const defaultFileBrowser: JupyterFrontEndPlugin<IDefaultFileBrowser> = {
const { commands } = app;

// manager.services.contents.addDrive(test_drive);
app.serviceManager.contents.addDrive(test_drive);
app.serviceManager.contents.addDrive(S3Drive);

// Manually restore and load the default file browser.
const defaultBrowser = fileBrowserFactory.createFileBrowser(
'drivebrowser',
{
auto: false,
restore: false,
driveName: test_drive.name
driveName: S3Drive.name
}
);

Expand All @@ -80,7 +104,7 @@ export const defaultFileBrowser: JupyterFrontEndPlugin<IDefaultFileBrowser> = {
);

// Override folder icon with the drive one - temporary
folderIcon.svgstr = driveSvg;
// folderIcon.svgstr = driveSvg;

// add lines from browser widget plugin to define attributes

Expand Down Expand Up @@ -109,20 +133,155 @@ export const toolbarFileBrowser: JupyterFrontEndPlugin<void> = {
'jupyter-drives-browser:file-browser-toolbar pluging activated!'
);

// // connect the filebrowser toolbar to the settings registry for the plugin
// setToolbar(
// fileBrowser,
// createToolbarFactory(
// toolbarRegistry,
// settingsRegistry,
// FILE_BROWSER_FACTORY,
// FILE_BROWSER_PLUGIN_ID,
// translator
// )
// );
app.commands.addCommand(CommandIDs.openChangeDrive, {
execute: () => {
return showDialog({
body: new SwitchDriveHandler(S3Drive.name),
focusNodeSelector: 'input',
buttons: [
Dialog.okButton({
label: 'Switch Drive',
ariaLabel: 'Switch to another Drive'
})
]
}).then(result => {
if (result.value) {
S3Drive.name = result.value;
app.serviceManager.contents.addDrive(S3Drive);
}
});
},
icon: DriveIcon.bindprops({ stylesheet: 'menuItem' })
});

app.commands.addCommand(CommandIDs.newDrive, {
execute: () => {
return showDialog({
body: new NewDriveHandler(),
focusNodeSelector: 'input',
buttons: [
Dialog.okButton({
label: 'Create',
ariaLabel: 'Create New Drive'
})
]
}).then(result => {
if (result.value) {
// test_drive.name = result.value!;
// app.serviceManager.contents.addDrive(newDrive);
}
});
},
icon: NewDriveIcon.bindprops({ stylesheet: 'menuItem' })
});

toolbarRegistry.addFactory(
FILE_BROWSER_FACTORY,
'uploaderTest',
(fileBrowser: FileBrowser) =>
new Uploader({ model: fileBrowser.model, translator })
);

toolbarRegistry.addFactory(
FILE_BROWSER_FACTORY,
'fileNameSearcherTest',
(fileBrowser: FileBrowser) => {
const searcher = FilenameSearcher({
updateFilter: (
filterFn: (item: string) => Partial<IScore> | null,
query?: string
) => {
fileBrowser.model.setFilter(value => {
return filterFn(value.name.toLowerCase());
});
},
useFuzzyFilter: true,
placeholder: 'Filter files by namesss',
forceRefresh: true
});
searcher.addClass(FILTERBOX_CLASS);
return searcher;
}
);

// connect the filebrowser toolbar to the settings registry for the plugin
setToolbar(
fileBrowser,
createToolbarFactory(
toolbarRegistry,
settingsRegistry,
FILE_BROWSER_FACTORY,
FILE_BROWSER_PLUGIN_ID,
translator
)
);
}
};

/**
* A widget used to switch to another drive.
*/
class SwitchDriveHandler extends Widget {
/**
* Construct a new "switch-drive" dialog.
*/
constructor(oldDriveName: string) {
super({ node: Private.createSwitchDriveNode(oldDriveName) });
this.addClass(FILE_DIALOG_CLASS);
// const ext = PathExt.extname(oldPath);
// const value = (this.inputNode.value = PathExt.basename(oldPath));
const value = this.inputNode.value;
console.log(value);
this.inputNode.setSelectionRange(0, value.length);
}

/**
* Get the input text node.
*/
get inputNode(): HTMLInputElement {
return this.node.getElementsByTagName('input')[0] as HTMLInputElement;
}

/**
* Get the value of the widget.
*/
getValue(): string {
return this.inputNode.value;
}
}

/**
* A widget used to switch to create a new drive.
*/
class NewDriveHandler extends Widget {
/**
* Construct a new "new-drive" dialog.
*/
constructor() {
super({ node: Private.createNewDriveNode() });
this.addClass(FILE_DIALOG_CLASS);
// const ext = PathExt.extname(oldPath);
// const value = (this.inputNode.value = PathExt.basename(oldPath));
const value = this.inputNode.value;
console.log(value);
this.inputNode.setSelectionRange(0, value.length);
}

/**
* Get the input text node.
*/
get inputNode(): HTMLInputElement {
return this.node.getElementsByTagName('input')[0] as HTMLInputElement;
}

/**
* Get the value of the widget.
*/
getValue(): string {
return this.inputNode.value;
}
}

namespace Private {
/**
* Restores file browser state and overrides state if tree resolver resolves.
Expand Down Expand Up @@ -176,4 +335,42 @@ namespace Private {
};
router.routed.connect(listener);
}

/**
* Create the node for a switch drive handler.
*/
export function createSwitchDriveNode(oldDriveName: string): HTMLElement {
const body = document.createElement('div');
const existingLabel = document.createElement('label');
existingLabel.textContent = 'Current Drive';
const existingName = document.createElement('span');
existingName.textContent = oldDriveName;

const nameTitle = document.createElement('label');
nameTitle.textContent = 'Switch to another Drive';
nameTitle.className = SWITCH_DRIVE_TITLE_CLASS;
const name = document.createElement('input');

body.appendChild(existingLabel);
body.appendChild(existingName);
body.appendChild(nameTitle);
body.appendChild(name);
return body;
}

/**
* Create the node for a new drive handler.
*/
export function createNewDriveNode(): HTMLElement {
const body = document.createElement('div');

const nameTitle = document.createElement('label');
nameTitle.textContent = 'Create a New Drive';
nameTitle.className = SWITCH_DRIVE_TITLE_CLASS;
const name = document.createElement('input');

body.appendChild(nameTitle);
body.appendChild(name);
return body;
}
}
6 changes: 6 additions & 0 deletions src/icons.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { LabIcon } from '@jupyterlab/ui-components';
import driveSvg from '../style/driveIconFileBrowser.svg';
import newDriveSvg from '../style/newDriveIcon.svg';

export const DriveIcon = new LabIcon({
name: '@jupyter/jupyter-drives-browser:drive',
svgstr: driveSvg
});

export const NewDriveIcon = new LabIcon({
name: '@jupyter/jupyter-drives-browser:new-drive',
svgstr: newDriveSvg
});
3 changes: 2 additions & 1 deletion src/s3contents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ export class Drive implements Contents.IDrive {
console.log('path: ', path);

// check if we are getting the list of files from the drive
if (!path) {
if (!path || path === this._name) {
path = '';
const content: Contents.IModel[] = [];

const command = new ListObjectsV2Command({
Expand Down
4 changes: 2 additions & 2 deletions style/driveIconFileBrowser.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions style/newDriveIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit d74276c

Please sign in to comment.