@@ -14,11 +14,14 @@ import { ITranslator } from '@jupyterlab/translation';
1414import {
1515 createToolbarFactory ,
1616 IToolbarWidgetRegistry ,
17- setToolbar
17+ setToolbar ,
18+ showDialog ,
19+ Dialog
1820} from '@jupyterlab/apputils' ;
1921import { ISettingRegistry } from '@jupyterlab/settingregistry' ;
2022import { FilenameSearcher , IScore } from '@jupyterlab/ui-components' ;
2123import { CommandRegistry } from '@lumino/commands' ;
24+ import { Widget } from '@lumino/widgets' ;
2225
2326import { driveBrowserIcon } from '../icons' ;
2427import { Drive } from '../contents' ;
@@ -35,6 +38,16 @@ const FILE_BROWSER_FACTORY = 'DriveBrowser';
3538 */
3639const FILTERBOX_CLASS = 'jp-drive-browser-search-box' ;
3740
41+ /**
42+ * The class name added to dialogs.
43+ */
44+ const FILE_DIALOG_CLASS = 'jp-FileDialog' ;
45+
46+ /**
47+ * The class name added for the new drive label in the creating new drive dialog.
48+ */
49+ const CREATE_DRIVE_TITLE_CLASS = 'jp-new-drive-title' ;
50+
3851/**
3952 * The drives list provider.
4053 */
@@ -184,6 +197,9 @@ export const driveFileBrowser: JupyterFrontEndPlugin<void> = {
184197
185198 // Listen for your plugin setting changes using Signal
186199 setting . changed . connect ( loadSetting ) ;
200+
201+ // Add commands
202+ Private . addCommands ( app , drive ) ;
187203 } )
188204 . catch ( reason => {
189205 console . error (
@@ -246,4 +262,101 @@ namespace Private {
246262 } ;
247263 router . routed . connect ( listener ) ;
248264 }
265+
266+ /**
267+ * Create the node for a creating a new drive handler.
268+ */
269+ const createNewDriveNode = ( newDriveName : string ) : HTMLElement => {
270+ const body = document . createElement ( 'div' ) ;
271+
272+ const drive = document . createElement ( 'label' ) ;
273+ drive . textContent = 'Name' ;
274+ drive . className = CREATE_DRIVE_TITLE_CLASS ;
275+ const driveName = document . createElement ( 'input' ) ;
276+
277+ const region = document . createElement ( 'label' ) ;
278+ region . textContent = 'Region' ;
279+ region . className = CREATE_DRIVE_TITLE_CLASS ;
280+ const regionName = document . createElement ( 'input' ) ;
281+ regionName . placeholder = 'us-east-1' ;
282+
283+ body . appendChild ( drive ) ;
284+ body . appendChild ( driveName ) ;
285+ body . appendChild ( region ) ;
286+ body . appendChild ( regionName ) ;
287+ return body ;
288+ } ;
289+
290+ /**
291+ * A widget used to create a new drive.
292+ */
293+ export class CreateDriveHandler extends Widget {
294+ /**
295+ * Construct a new "create-drive" dialog.
296+ */
297+ constructor ( newDriveName : string ) {
298+ super ( { node : createNewDriveNode ( newDriveName ) } ) ;
299+ this . onAfterAttach ( ) ;
300+ }
301+
302+ protected onAfterAttach ( ) : void {
303+ this . addClass ( FILE_DIALOG_CLASS ) ;
304+ const drive = this . driveInput . value ;
305+ this . driveInput . setSelectionRange ( 0 , drive . length ) ;
306+ const region = this . regionInput . value ;
307+ this . regionInput . setSelectionRange ( 0 , region . length ) ;
308+ }
309+
310+ /**
311+ * Get the input text node for drive name.
312+ */
313+ get driveInput ( ) : HTMLInputElement {
314+ return this . node . getElementsByTagName ( 'input' ) [ 0 ] as HTMLInputElement ;
315+ }
316+
317+ /**
318+ * Get the input text node for region.
319+ */
320+ get regionInput ( ) : HTMLInputElement {
321+ return this . node . getElementsByTagName ( 'input' ) [ 1 ] as HTMLInputElement ;
322+ }
323+
324+ /**
325+ * Get the value of the widget.
326+ */
327+ getValue ( ) : string [ ] {
328+ return [ this . driveInput . value , this . regionInput . value ] ;
329+ }
330+ }
331+
332+ export function addCommands ( app : JupyterFrontEnd , drive : Drive ) : void {
333+ app . commands . addCommand ( CommandIDs . createNewDrive , {
334+ execute : async ( ) => {
335+ return showDialog ( {
336+ title : 'New Drive' ,
337+ body : new Private . CreateDriveHandler ( drive . name ) ,
338+ focusNodeSelector : 'input' ,
339+ buttons : [
340+ Dialog . cancelButton ( ) ,
341+ Dialog . okButton ( {
342+ label : 'Create' ,
343+ ariaLabel : 'Create New Drive'
344+ } )
345+ ]
346+ } ) . then ( result => {
347+ if ( result . value ) {
348+ drive . newDrive ( result . value [ 0 ] , result . value [ 1 ] ) ;
349+ }
350+ } ) ;
351+ } ,
352+ label : 'New Drive' ,
353+ icon : driveBrowserIcon . bindprops ( { stylesheet : 'menuItem' } )
354+ } ) ;
355+
356+ app . contextMenu . addItem ( {
357+ command : CommandIDs . createNewDrive ,
358+ selector : '#drive-file-browser.jp-SidePanel .jp-DirListing-content' ,
359+ rank : 100
360+ } ) ;
361+ }
249362}
0 commit comments