Skip to content

Commit

Permalink
add create new drive command
Browse files Browse the repository at this point in the history
  • Loading branch information
DenisaCG committed Jan 9, 2025
1 parent 106b0a8 commit 34be2a4
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 3 deletions.
2 changes: 1 addition & 1 deletion jupyter_drives/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ async def get(self, drive: str = "", path: str = ""):
async def post(self, drive: str = "", path: str = ""):
body = self.get_json_body()
if 'location' in body:
result = await self._manager.new_drive(**body)
result = await self._manager.new_drive(drive, **body)
else:
result = await self._manager.new_file(drive, path, **body)
self.finish(result)
Expand Down
28 changes: 27 additions & 1 deletion src/contents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
countObjectNameAppearances,
renameObjects,
copyObjects,
presignedLink
presignedLink,
createDrive
} from './requests';

let data: Contents.IModel = {
Expand Down Expand Up @@ -625,6 +626,31 @@ export class Drive implements Contents.IDrive {
return data;
}

/**
* Create a new drive.
*
* @param options: The options used to create the drive.
*
* @returns A promise which resolves with the contents model.
*/
async newDrive(
newDriveName: string,
region: string
): Promise<Contents.IModel> {
data = await createDrive(newDriveName, {
location: region
});

Contents.validateContentsModel(data);
this._fileChanged.emit({
type: 'new',
oldValue: null,
newValue: data
});

return data;
}

/**
* Create a checkpoint for a file.
*
Expand Down
115 changes: 114 additions & 1 deletion src/plugins/driveBrowserPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ import { ITranslator } from '@jupyterlab/translation';
import {
createToolbarFactory,
IToolbarWidgetRegistry,
setToolbar
setToolbar,
showDialog,
Dialog
} from '@jupyterlab/apputils';
import { ISettingRegistry } from '@jupyterlab/settingregistry';
import { FilenameSearcher, IScore } from '@jupyterlab/ui-components';
import { CommandRegistry } from '@lumino/commands';
import { Widget } from '@lumino/widgets';

import { driveBrowserIcon } from '../icons';
import { Drive } from '../contents';
Expand All @@ -35,6 +38,16 @@ const FILE_BROWSER_FACTORY = 'DriveBrowser';
*/
const FILTERBOX_CLASS = 'jp-drive-browser-search-box';

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

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

/**
* The drives list provider.
*/
Expand Down Expand Up @@ -184,6 +197,9 @@ export const driveFileBrowser: JupyterFrontEndPlugin<void> = {

// Listen for your plugin setting changes using Signal
setting.changed.connect(loadSetting);

// Add commands
Private.addCommands(app, drive);
})
.catch(reason => {
console.error(
Expand Down Expand Up @@ -246,4 +262,101 @@ namespace Private {
};
router.routed.connect(listener);
}

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

const drive = document.createElement('label');
drive.textContent = 'Name';
drive.className = CREATE_DRIVE_TITLE_CLASS;
const driveName = document.createElement('input');

const region = document.createElement('label');
region.textContent = 'Region';
region.className = CREATE_DRIVE_TITLE_CLASS;
const regionName = document.createElement('input');
regionName.placeholder = 'us-east-1';

body.appendChild(drive);
body.appendChild(driveName);
body.appendChild(region);
body.appendChild(regionName);
return body;
};

/**
* A widget used to create a new drive.
*/
export class CreateDriveHandler extends Widget {
/**
* Construct a new "create-drive" dialog.
*/
constructor(newDriveName: string) {
super({ node: createNewDriveNode(newDriveName) });
this.onAfterAttach();
}

protected onAfterAttach(): void {
this.addClass(FILE_DIALOG_CLASS);
const drive = this.driveInput.value;
this.driveInput.setSelectionRange(0, drive.length);
const region = this.regionInput.value;
this.regionInput.setSelectionRange(0, region.length);
}

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

/**
* Get the input text node for region.
*/
get regionInput(): HTMLInputElement {
return this.node.getElementsByTagName('input')[1] as HTMLInputElement;
}

/**
* Get the value of the widget.
*/
getValue(): string[] {
return [this.driveInput.value, this.regionInput.value];
}
}

export function addCommands(app: JupyterFrontEnd, drive: Drive): void {
app.commands.addCommand(CommandIDs.createNewDrive, {
execute: async () => {
return showDialog({
title: 'Create New Drive',
body: new Private.CreateDriveHandler(drive.name),
focusNodeSelector: 'input',
buttons: [
Dialog.cancelButton(),
Dialog.okButton({
label: 'Create',
ariaLabel: 'Create New Drive'
})
]
}).then(result => {
if (result.value) {
drive.newDrive(result.value[0], result.value[1]);
}
});
},
label: 'Create New Drive',
icon: driveBrowserIcon.bindprops({ stylesheet: 'menuItem' })
});

app.contextMenu.addItem({
command: CommandIDs.createNewDrive,
selector: '#drive-file-browser.jp-SidePanel .jp-DirListing-content',
rank: 10
});
}
}
1 change: 1 addition & 0 deletions src/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export namespace CommandIDs {
export const openDrivesDialog = 'drives:open-drives-dialog';
export const openPath = 'drives:open-path';
export const toggleBrowser = 'drives:toggle-main';
export const createNewDrive = 'drives:create-new-drive';
export const launcher = 'launcher:create';
}

Expand Down

0 comments on commit 34be2a4

Please sign in to comment.