-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Draft implementation of custom kernel dialog
- Loading branch information
1 parent
09b6f3d
commit b1c739b
Showing
10 changed files
with
655 additions
and
308 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
import { | ||
JupyterFrontEnd, | ||
JupyterFrontEndPlugin | ||
} from '@jupyterlab/application'; | ||
import type { CommandRegistry } from '@lumino/commands'; | ||
import { | ||
SessionContextDialogs, | ||
ISessionContextDialogs, | ||
ISessionContext, | ||
SessionContext, | ||
Dialog, | ||
ReactWidget | ||
} from '@jupyterlab/apputils'; | ||
import { ISettingRegistry } from '@jupyterlab/settingregistry'; | ||
import { | ||
ITranslator, | ||
nullTranslator, | ||
TranslationBundle | ||
} from '@jupyterlab/translation'; | ||
|
||
import { KernelTable } from './launcher'; | ||
import { | ||
IItem, | ||
ILastUsedDatabase, | ||
IFavoritesDatabase, | ||
ILauncherDatabase, | ||
MAIN_PLUGIN_ID | ||
} from './types'; | ||
import { Item } from './item'; | ||
import type { ILauncher } from '@jupyterlab/launcher'; | ||
import { JSONExt, ReadonlyJSONValue } from '@lumino/coreutils'; | ||
import * as React from 'react'; | ||
|
||
class CustomSessionContextDialogs extends SessionContextDialogs { | ||
constructor(protected options: CustomSessionContextDialogs.IOptions) { | ||
super(options); | ||
const translator = options.translator ?? nullTranslator; | ||
this.trans = translator.load('jupyterlab'); | ||
} | ||
/** | ||
* Select a kernel for the session. | ||
*/ | ||
async selectKernel(sessionContext: ISessionContext): Promise<void> { | ||
const trans = this.trans; | ||
if (sessionContext.isDisposed) { | ||
return Promise.resolve(); | ||
} | ||
|
||
// If there is no existing kernel, offer the option | ||
// to keep no kernel. | ||
let label = trans.__('Cancel'); | ||
if (sessionContext.hasNoKernel) { | ||
label = sessionContext.kernelDisplayName; | ||
} | ||
const buttons = [ | ||
Dialog.cancelButton({ | ||
label | ||
}), | ||
Dialog.okButton({ | ||
label: trans.__('Select'), | ||
ariaLabel: trans.__('Select Kernel') | ||
}) | ||
]; | ||
|
||
const autoStartDefault = sessionContext.kernelPreference.autoStartDefault; | ||
const hasCheckbox = typeof autoStartDefault === 'boolean'; | ||
const settings = await this.options.settingRegistry.load(MAIN_PLUGIN_ID); | ||
|
||
const dialog = new Dialog({ | ||
title: trans.__('Select Kernel'), | ||
body: new KernelSelector({ | ||
data: { | ||
specs: sessionContext.specsManager.specs, | ||
sessions: sessionContext.sessionManager.running(), | ||
preference: sessionContext.kernelPreference | ||
}, | ||
commands: this.options.commands, | ||
favoritesDatabase: this.options.database.favorites, | ||
lastUsedDatabase: this.options.database.lastUsed, | ||
settings, | ||
trans | ||
}), | ||
buttons, | ||
checkbox: hasCheckbox | ||
? { | ||
label: trans.__('Always start the preferred kernel'), | ||
caption: trans.__( | ||
'Remember my choice and always start the preferred kernel' | ||
), | ||
checked: autoStartDefault | ||
} | ||
: null | ||
}); | ||
|
||
const result = await dialog.launch(); | ||
|
||
if (sessionContext.isDisposed || !result.button.accept) { | ||
return; | ||
} | ||
|
||
if (hasCheckbox && result.isChecked !== null) { | ||
sessionContext.kernelPreference = { | ||
...sessionContext.kernelPreference, | ||
autoStartDefault: result.isChecked | ||
}; | ||
} | ||
|
||
const model = result.value; | ||
if (model === null && !sessionContext.hasNoKernel) { | ||
return sessionContext.shutdown(); | ||
} | ||
if (model) { | ||
await sessionContext.changeKernel(model); | ||
} | ||
} | ||
private trans: TranslationBundle; | ||
} | ||
|
||
export namespace CustomSessionContextDialogs { | ||
export interface IOptions extends ISessionContext.IDialogsOptions { | ||
database: ILauncherDatabase; | ||
commands: CommandRegistry; | ||
settingRegistry: ISettingRegistry; | ||
} | ||
} | ||
|
||
/** | ||
* Initialization data for the jupyterlab-new-launcher session dialogs. | ||
*/ | ||
export const sessionDialogsPlugin: JupyterFrontEndPlugin<ISessionContextDialogs> = | ||
{ | ||
id: 'jupyterlab-new-launcher:dialogs', | ||
description: 'Session dialogs for redesigned JupyterLab launcher', | ||
provides: ISessionContextDialogs, | ||
autoStart: true, | ||
requires: [ITranslator, ILauncherDatabase, ISettingRegistry], | ||
activate: ( | ||
app: JupyterFrontEnd, | ||
translator: ITranslator, | ||
database: ILauncherDatabase, | ||
settingRegistry: ISettingRegistry | ||
) => { | ||
return new CustomSessionContextDialogs({ | ||
translator: translator, | ||
database: database, | ||
commands: app.commands, | ||
settingRegistry: settingRegistry | ||
}); | ||
} | ||
}; | ||
|
||
export class KernelSelector extends ReactWidget { | ||
constructor(protected options: KernelSelector.IOptions) { | ||
super(); | ||
this.commands = options.commands; | ||
this._lastUsedDatabase = options.lastUsedDatabase; | ||
this._favoritesDatabase = options.favoritesDatabase; | ||
this._settings = options.settings; | ||
this.trans = options.trans; | ||
} | ||
private _lastUsedDatabase: ILastUsedDatabase; | ||
private _favoritesDatabase: IFavoritesDatabase; | ||
trans: TranslationBundle; | ||
|
||
renderKernelCommand = (item: ILauncher.IItemOptions): IItem => { | ||
return new Item({ | ||
item, | ||
cwd: '', | ||
commands: this.commands, | ||
lastUsedDatabase: this._lastUsedDatabase, | ||
favoritesDatabase: this._favoritesDatabase | ||
}); | ||
}; | ||
|
||
/** | ||
* Render the launcher to virtual DOM nodes. | ||
*/ | ||
protected render(): React.ReactElement<any> | null { | ||
const items: ILauncher.IItemOptions[] = []; | ||
|
||
for (const [_, spec] of Object.entries( | ||
this.options.data.specs!.kernelspecs! | ||
)) { | ||
if (!spec) { | ||
continue; | ||
} | ||
const kernelIconUrl = | ||
spec.resources['logo-svg'] || spec.resources['logo-64x64']; | ||
items.push({ | ||
command: 'notebook:create-new', | ||
args: { | ||
isLauncher: true, | ||
kernelName: spec.name | ||
}, | ||
kernelIconUrl, | ||
metadata: { | ||
kernel: JSONExt.deepCopy(spec.metadata || {}) as ReadonlyJSONValue | ||
}, | ||
category: this.trans.__('Notebook') | ||
}); | ||
} | ||
const notebookItems = items.map(this.renderKernelCommand); | ||
|
||
return ( | ||
<KernelTable | ||
trans={this.trans} | ||
commands={this.commands} | ||
items={notebookItems} | ||
settings={this._settings} | ||
query={''} | ||
showSearchBox={true} | ||
/> | ||
); | ||
} | ||
protected commands: CommandRegistry; | ||
private _settings: ISettingRegistry.ISettings; | ||
} | ||
|
||
export namespace KernelSelector { | ||
export interface IOptions { | ||
lastUsedDatabase: ILastUsedDatabase; | ||
favoritesDatabase: IFavoritesDatabase; | ||
settings: ISettingRegistry.ISettings; | ||
commands: CommandRegistry; | ||
trans: TranslationBundle; | ||
data: SessionContext.IKernelSearch; | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.