@@ -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 drive file browser factory provider.
4053 */
@@ -163,6 +176,9 @@ export const driveFileBrowser: JupyterFrontEndPlugin<void> = {
163176
164177 // Listen for your plugin setting changes using Signal
165178 setting . changed . connect ( loadSetting ) ;
179+
180+ // Add commands
181+ Private . addCommands ( app , drive ) ;
166182 } )
167183 . catch ( reason => {
168184 console . error (
@@ -225,4 +241,101 @@ namespace Private {
225241 } ;
226242 router . routed . connect ( listener ) ;
227243 }
244+
245+ /**
246+ * Create the node for a creating a new drive handler.
247+ */
248+ const createNewDriveNode = ( newDriveName : string ) : HTMLElement => {
249+ const body = document . createElement ( 'div' ) ;
250+
251+ const drive = document . createElement ( 'label' ) ;
252+ drive . textContent = 'Name' ;
253+ drive . className = CREATE_DRIVE_TITLE_CLASS ;
254+ const driveName = document . createElement ( 'input' ) ;
255+
256+ const region = document . createElement ( 'label' ) ;
257+ region . textContent = 'Region' ;
258+ region . className = CREATE_DRIVE_TITLE_CLASS ;
259+ const regionName = document . createElement ( 'input' ) ;
260+ regionName . placeholder = 'us-east-1' ;
261+
262+ body . appendChild ( drive ) ;
263+ body . appendChild ( driveName ) ;
264+ body . appendChild ( region ) ;
265+ body . appendChild ( regionName ) ;
266+ return body ;
267+ } ;
268+
269+ /**
270+ * A widget used to create a new drive.
271+ */
272+ export class CreateDriveHandler extends Widget {
273+ /**
274+ * Construct a new "create-drive" dialog.
275+ */
276+ constructor ( newDriveName : string ) {
277+ super ( { node : createNewDriveNode ( newDriveName ) } ) ;
278+ this . onAfterAttach ( ) ;
279+ }
280+
281+ protected onAfterAttach ( ) : void {
282+ this . addClass ( FILE_DIALOG_CLASS ) ;
283+ const drive = this . driveInput . value ;
284+ this . driveInput . setSelectionRange ( 0 , drive . length ) ;
285+ const region = this . regionInput . value ;
286+ this . regionInput . setSelectionRange ( 0 , region . length ) ;
287+ }
288+
289+ /**
290+ * Get the input text node for drive name.
291+ */
292+ get driveInput ( ) : HTMLInputElement {
293+ return this . node . getElementsByTagName ( 'input' ) [ 0 ] as HTMLInputElement ;
294+ }
295+
296+ /**
297+ * Get the input text node for region.
298+ */
299+ get regionInput ( ) : HTMLInputElement {
300+ return this . node . getElementsByTagName ( 'input' ) [ 1 ] as HTMLInputElement ;
301+ }
302+
303+ /**
304+ * Get the value of the widget.
305+ */
306+ getValue ( ) : string [ ] {
307+ return [ this . driveInput . value , this . regionInput . value ] ;
308+ }
309+ }
310+
311+ export function addCommands ( app : JupyterFrontEnd , drive : Drive ) : void {
312+ app . commands . addCommand ( CommandIDs . createNewDrive , {
313+ execute : async ( ) => {
314+ return showDialog ( {
315+ title : 'New Drive' ,
316+ body : new Private . CreateDriveHandler ( drive . name ) ,
317+ focusNodeSelector : 'input' ,
318+ buttons : [
319+ Dialog . cancelButton ( ) ,
320+ Dialog . okButton ( {
321+ label : 'Create' ,
322+ ariaLabel : 'Create New Drive'
323+ } )
324+ ]
325+ } ) . then ( result => {
326+ if ( result . value ) {
327+ drive . newDrive ( result . value [ 0 ] , result . value [ 1 ] ) ;
328+ }
329+ } ) ;
330+ } ,
331+ label : 'New Drive' ,
332+ icon : driveBrowserIcon . bindprops ( { stylesheet : 'menuItem' } )
333+ } ) ;
334+
335+ app . contextMenu . addItem ( {
336+ command : CommandIDs . createNewDrive ,
337+ selector : '#drive-file-browser.jp-SidePanel .jp-DirListing-content' ,
338+ rank : 100
339+ } ) ;
340+ }
228341}
0 commit comments