From ba8671ac0372c50e46d548fc4dd5e8a84e133044 Mon Sep 17 00:00:00 2001 From: YuviPanda Date: Wed, 9 Jun 2021 02:18:24 +0530 Subject: [PATCH] Add an 'interface switcher' to the toolbar Fixes https://github.com/jupyterlab/retrolab/issues/157 --- packages/notebook-extension/src/index.ts | 5 +- packages/notebook-extension/src/toolbar.tsx | 144 ++++++++++++++++++++ 2 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 packages/notebook-extension/src/toolbar.tsx diff --git a/packages/notebook-extension/src/index.ts b/packages/notebook-extension/src/index.ts index 17913804..25861244 100644 --- a/packages/notebook-extension/src/index.ts +++ b/packages/notebook-extension/src/index.ts @@ -20,6 +20,8 @@ import { Poll } from '@lumino/polling'; import { Widget } from '@lumino/widgets'; +import { addNotebookToolbarItems } from './toolbar'; + /** * The class for kernel status errors. */ @@ -241,7 +243,8 @@ const shell: JupyterFrontEndPlugin = { const plugins: JupyterFrontEndPlugin[] = [ checkpoints, kernelLogo, - kernelStatus + kernelStatus, + addNotebookToolbarItems ]; export default plugins; diff --git a/packages/notebook-extension/src/toolbar.tsx b/packages/notebook-extension/src/toolbar.tsx new file mode 100644 index 00000000..96ac8434 --- /dev/null +++ b/packages/notebook-extension/src/toolbar.tsx @@ -0,0 +1,144 @@ +import { + JupyterFrontEnd, + JupyterFrontEndPlugin +} from '@jupyterlab/application'; +import { ICommandPalette, ReactWidget } from '@jupyterlab/apputils'; +import { PageConfig } from '@jupyterlab/coreutils'; +import { DocumentRegistry } from '@jupyterlab/docregistry'; +import { IMainMenu } from '@jupyterlab/mainmenu'; +import { + INotebookModel, + INotebookTracker, + NotebookPanel +} from '@jupyterlab/notebook'; +import { HTMLSelect } from '@jupyterlab/ui-components'; +import { CommandRegistry } from '@lumino/commands'; +import { IDisposable } from '@lumino/disposable'; +import * as React from 'react'; + +/** + * Command IDs used by notebook toolbar items + */ +namespace CommandIDs { + /** + * Open current notebook in classic notebook + */ + export const openClassic = 'retro:open-classic'; + /** + * Open current notebook in JupyterLab + */ + export const openLab = 'retro:open-lab'; +} + +class InterfaceSwitcher extends ReactWidget { + constructor(private commands: CommandRegistry) { + super(); + this.addClass('jp-Notebook-toolbarCellType'); + } + + onChange = (event: React.ChangeEvent) => { + const target = event.target.value; + if (target === '-') { + return; + } + this.commands.execute(target); + }; + + render = () => { + return ( + + + + + + ); + }; +} + +/** + * A notebook widget extension that adds a open in classic notebook button to the toolbar. + */ +class InterfaceSwitcherButton + implements DocumentRegistry.IWidgetExtension { + constructor(commands: CommandRegistry) { + this._commands = commands; + } + + createNew(panel: NotebookPanel): IDisposable { + const switcher = new InterfaceSwitcher(this._commands); + panel.toolbar.insertBefore('kernelName', 'switch-interface', switcher); + return switcher; + } + + private _commands: CommandRegistry; +} + +/** + * A plugin to add custom toolbar items to the notebook page + */ +const notebookToolbarItems: JupyterFrontEndPlugin = { + id: '@retrolab/notebook-extension:open-classic', + autoStart: true, + optional: [INotebookTracker, ICommandPalette, IMainMenu], + activate: ( + app: JupyterFrontEnd, + notebookTracker: INotebookTracker | null, + palette: ICommandPalette | null, + menu: IMainMenu | null + ) => { + if (!notebookTracker) { + // to prevent showing the toolbar button in RetroLab + return; + } + + const { commands, docRegistry, shell } = app; + const baseUrl = PageConfig.getBaseUrl(); + + const isEnabled = () => { + return ( + notebookTracker.currentWidget !== null && + notebookTracker.currentWidget === shell.currentWidget + ); + }; + + commands.addCommand(CommandIDs.openClassic, { + label: 'Open in Classic Notebook', + execute: () => { + const current = notebookTracker.currentWidget; + if (!current) { + return; + } + window.open(`${baseUrl}tree/${current.context.path}`); + }, + isEnabled + }); + + commands.addCommand(CommandIDs.openLab, { + label: 'Open in JupyterLab', + execute: () => { + const current = notebookTracker.currentWidget; + if (!current) { + return; + } + window.open(`${baseUrl}lab/tree/${current.context.path}`); + }, + isEnabled + }); + + if (palette) { + palette.addItem({ command: CommandIDs.openClassic, category: 'Other' }); + } + + if (menu) { + menu.viewMenu.addGroup([{ command: CommandIDs.openClassic }], 1); + } + + const interfaceSwitcher = new InterfaceSwitcherButton(commands); + docRegistry.addWidgetExtension('Notebook', interfaceSwitcher); + } +}; + +export { notebookToolbarItems as addNotebookToolbarItems };