From ef5f9bc17fd63d0a26ba15f1eeb588b47a8990eb Mon Sep 17 00:00:00 2001 From: krassowski <5832902+krassowski@users.noreply.github.com> Date: Thu, 25 Apr 2024 17:37:11 +0100 Subject: [PATCH] Implement connecting to running kernel --- src/dialogs.tsx | 83 ++++++++++++++++++++++++++++++++++++++++-------- src/launcher.tsx | 10 +++++- style/base.css | 13 ++++++++ 3 files changed, 91 insertions(+), 15 deletions(-) diff --git a/src/dialogs.tsx b/src/dialogs.tsx index 157c0c4..3c8f38a 100644 --- a/src/dialogs.tsx +++ b/src/dialogs.tsx @@ -184,8 +184,9 @@ export class KernelSelector extends ReactWidget { */ protected render(): React.ReactElement | null { const items: ILauncher.IItemOptions[] = []; + const specs = this.options.data.specs!.kernelspecs!; - for (const spec of Object.values(this.options.data.specs!.kernelspecs!)) { + for (const spec of Object.values(specs)) { if (!spec) { continue; } @@ -200,25 +201,76 @@ export class KernelSelector extends ReactWidget { kernelIconUrl, metadata: { kernel: JSONExt.deepCopy(spec.metadata || {}) as ReadonlyJSONValue + } + }); + } + const runningItems: ILauncher.IItemOptions[] = []; + for (const model of this.options.data.sessions!) { + const kernel = model.kernel; + if (!kernel) { + continue; + } + const spec = specs[kernel.name]!; + const kernelIconUrl = + spec.resources['logo-svg'] || spec.resources['logo-64x64']; + runningItems.push({ + command: 'notebook:create-new', + args: { + isLauncher: true, + kernelName: spec.name }, - category: this.trans.__('Notebook') + kernelIconUrl, + metadata: { + kernel: { + ...JSONExt.deepCopy(spec.metadata || {}), + state: kernel.execution_state ?? 'running', + 'used by': model.name + } as ReadonlyJSONValue, + model: kernel as unknown as ReadonlyJSONValue + } }); } const notebookItems = items.map(this.renderKernelCommand); + const runningKernelsItems = runningItems.map(this.renderKernelCommand); return ( - { - this._selection = item; - this.options.acceptDialog(); - }} - /> + <> +

+ {this.trans.__('Start a new kernel')} +

+ { + this._selection = item; + this.options.acceptDialog(); + }} + /> + {runningKernelsItems.length > 0 ? ( + <> +

+ {this.trans.__('Connect to a running kernel')} +

+ { + this._selection = item; + this.options.acceptDialog(); + }} + hideColumns={['last-used', 'star']} + /> + + ) : null} + ); } @@ -226,6 +278,9 @@ export class KernelSelector extends ReactWidget { if (!this._selection) { return null; } + if (this._selection.metadata?.model) { + return this._selection.metadata.model as unknown as Kernel.IModel; + } return { name: this._selection.args!.kernelName as string }; } diff --git a/src/launcher.tsx b/src/launcher.tsx index 2ffbf80..edd6d03 100644 --- a/src/launcher.tsx +++ b/src/launcher.tsx @@ -227,6 +227,7 @@ export function KernelTable(props: { showSearchBox: boolean; query: string; onClick: (item: IKernelItem) => void; + hideColumns?: string[]; }) { const { trans } = props; let query: string; @@ -266,6 +267,9 @@ export function KernelTable(props: { return '-'; } const value = kernelMeta[metadataKey]; + if (typeof value === 'string') { + return value; + } return JSON.stringify(value); }, sort: (a: IKernelItem, b: IKernelItem) => { @@ -295,7 +299,7 @@ export function KernelTable(props: { } ); - const columns: Table.IColumn[] = [ + const availableColumns: Table.IColumn[] = [ { id: 'icon', label: trans.__('Icon'), @@ -405,6 +409,10 @@ export function KernelTable(props: { Number(a.starred) - Number(b.starred) } ]; + const forceHiddenColumns = props.hideColumns ?? []; + const columns = availableColumns.filter( + column => !forceHiddenColumns.includes(column.id) + ); const [hiddenColumns, setHiddenColumns] = React.useState< ISettingsLayout['hiddenColumns'] diff --git a/style/base.css b/style/base.css index e3c48d2..3e94db1 100644 --- a/style/base.css +++ b/style/base.css @@ -182,10 +182,23 @@ max-width: unset; } +.jp-KernelSelector-Dialog > .jp-Dialog-content > .jp-Dialog-header { + display: none; +} + .jp-KernelSelector-SelectButton { display: none; } +.jp-KernelSelector-Dialog .jp-NewLauncher-table { + margin-bottom: 8px; +} + +.jp-KernelSelector-Section { + margin: 0; + margin-bottom: 4px; +} + /* Styles for scenario where full row is clickable */ .jp-NewLauncher-table tr {