From 3f49eea5519282f289df00b590a6514b56bd6ff0 Mon Sep 17 00:00:00 2001 From: Jeremy Tuloup Date: Fri, 3 Sep 2021 12:14:42 +0200 Subject: [PATCH] Add buttons to switch to classic lab and retro --- packages/lab-extension/package.json | 3 + packages/lab-extension/src/index.ts | 160 +++++++++++++++- .../lab-extension/src/interfaceswitcher.tsx | 171 ------------------ packages/lab-extension/tsconfig.json | 3 + 4 files changed, 158 insertions(+), 179 deletions(-) delete mode 100644 packages/lab-extension/src/interfaceswitcher.tsx diff --git a/packages/lab-extension/package.json b/packages/lab-extension/package.json index b2d0043c..21b79387 100644 --- a/packages/lab-extension/package.json +++ b/packages/lab-extension/package.json @@ -50,8 +50,11 @@ "@jupyterlab/docregistry": "^3.1.8", "@jupyterlab/mainmenu": "^3.1.8", "@jupyterlab/notebook": "^3.1.8", + "@jupyterlab/translation": "^3.1.8", + "@jupyterlab/ui-components": "^3.1.8", "@lumino/commands": "^1.15.0", "@lumino/disposable": "^1.7.0", + "@retrolab/application": "^0.3.3", "@retrolab/ui-components": "^0.3.3" }, "devDependencies": { diff --git a/packages/lab-extension/src/index.ts b/packages/lab-extension/src/index.ts index a70108cb..189f6f40 100644 --- a/packages/lab-extension/src/index.ts +++ b/packages/lab-extension/src/index.ts @@ -2,25 +2,172 @@ // Distributed under the terms of the Modified BSD License. import { + ILabShell, JupyterFrontEnd, JupyterFrontEndPlugin } from '@jupyterlab/application'; -import { ICommandPalette } from '@jupyterlab/apputils'; + +import { CommandToolbarButton, ICommandPalette } from '@jupyterlab/apputils'; + import { PageConfig } from '@jupyterlab/coreutils'; + import { IMainMenu } from '@jupyterlab/mainmenu'; + +import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook'; + import { ITranslator } from '@jupyterlab/translation'; -import { interfaceSwitcher } from './interfaceswitcher'; + +import { + jupyterIcon, + jupyterFaviconIcon, + LabIcon +} from '@jupyterlab/ui-components'; + +import { IRetroShell } from '@retrolab/application'; + +import { retroSunIcon } from '@retrolab/ui-components'; /** * The command IDs used by the application plugin. */ namespace CommandIDs { /** - * Toggle Top Bar visibility + * Launch RetroLab Tree + */ + export const launchRetroTree = 'retrolab:launch-tree'; + + /** + * Open RetroLab + */ + export const openRetro = 'retrolab:open-retro'; + + /** + * Open in Classic Notebook */ - export const launchRetroTree = 'retrolab:launchtree'; + export const openClassic = 'retrolab:open-classic'; + + /** + * Open in JupyterLab + */ + export const openLab = 'retrolab:open-lab'; +} + +interface ISwitcherChoice { + command: string; + commandLabel: string; + buttonLabel: string; + icon: LabIcon; + urlPrefix: string; } +/** + * A plugin to add custom toolbar items to the notebook page + */ +const launchButtons: JupyterFrontEndPlugin = { + id: '@retrolab/lab-extension:interface-switcher', + autoStart: true, + optional: [ + INotebookTracker, + ICommandPalette, + IMainMenu, + IRetroShell, + ILabShell + ], + activate: ( + app: JupyterFrontEnd, + notebookTracker: INotebookTracker | null, + palette: ICommandPalette | null, + menu: IMainMenu | null, + retroShell: IRetroShell | null, + labShell: ILabShell | null + ) => { + if (!notebookTracker) { + // to prevent showing the toolbar button in RetroLab + return; + } + + const { commands, shell } = app; + const baseUrl = PageConfig.getBaseUrl(); + + const isEnabled = () => { + return ( + notebookTracker.currentWidget !== null && + notebookTracker.currentWidget === shell.currentWidget + ); + }; + + const addInterface = (option: ISwitcherChoice) => { + const { command, icon, buttonLabel, commandLabel, urlPrefix } = option; + commands.addCommand(command, { + label: args => (args.noLabel ? '' : commandLabel), + caption: commandLabel, + icon, + execute: () => { + const current = notebookTracker.currentWidget; + if (!current) { + return; + } + window.open(`${urlPrefix}${current.context.path}`); + }, + isEnabled + }); + + if (palette) { + palette.addItem({ command, category: 'Other' }); + } + + if (menu) { + menu.viewMenu.addGroup([{ command }], 1); + } + + notebookTracker.widgetAdded.connect( + async (sender: INotebookTracker, panel: NotebookPanel) => { + panel.toolbar.insertBefore( + 'kernelName', + buttonLabel, + new CommandToolbarButton({ + commands, + id: command, + args: { noLabel: 1 } + }) + ); + await panel.context.ready; + commands.notifyCommandChanged(); + } + ); + }; + + // always add Classic + addInterface({ + command: 'retrolab:open-classic', + commandLabel: 'Open in Classic Notebook', + buttonLabel: 'openClassic', + icon: jupyterIcon, + urlPrefix: `${baseUrl}tree/` + }); + + if (!retroShell) { + addInterface({ + command: 'retrolab:open-retro', + commandLabel: 'Open in RetroLab', + buttonLabel: 'openRetro', + icon: retroSunIcon, + urlPrefix: `${baseUrl}retro/tree/` + }); + } + + if (!labShell) { + addInterface({ + command: 'retrolab:open-lab', + commandLabel: 'Open in JupyterLab', + buttonLabel: 'openLab', + icon: jupyterFaviconIcon, + urlPrefix: `${baseUrl}doc/tree/` + }); + } + } +}; + /** * A plugin to add a command to open the RetroLab Tree. */ @@ -60,9 +207,6 @@ const launchRetroTree: JupyterFrontEndPlugin = { /** * Export the plugins as default. */ -const plugins: JupyterFrontEndPlugin[] = [ - launchRetroTree, - interfaceSwitcher -]; +const plugins: JupyterFrontEndPlugin[] = [launchRetroTree, launchButtons]; export default plugins; diff --git a/packages/lab-extension/src/interfaceswitcher.tsx b/packages/lab-extension/src/interfaceswitcher.tsx deleted file mode 100644 index 4fb1b0bf..00000000 --- a/packages/lab-extension/src/interfaceswitcher.tsx +++ /dev/null @@ -1,171 +0,0 @@ -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 { IRetroShell } from '@retrolab/application'; -import * as React from 'react'; - -interface ISwitcherChoice { - command: string; - dropdownLabel: string; - commandLabel: string; - urlPrefix: string; - current: boolean; -} - -class InterfaceSwitcher extends ReactWidget { - private switcherChoices: ISwitcherChoice[]; - constructor( - private commands: CommandRegistry, - switcherChoices: ISwitcherChoice[] - ) { - super(); - this.addClass('jp-Notebook-toolbarCellType'); - this.switcherChoices = switcherChoices; - } - - render = () => { - return ( - sc.current)?.command} - > - {this.switcherChoices.map(sc => { - return ( - - ); - })} - - ); - }; -} - -/** - * A notebook widget extension that adds a open in classic notebook button to the toolbar. - */ -class InterfaceSwitcherButton - implements DocumentRegistry.IWidgetExtension { - private switcherChoices: ISwitcherChoice[]; - - constructor(commands: CommandRegistry, switcherChoices: ISwitcherChoice[]) { - this._commands = commands; - this.switcherChoices = switcherChoices; - } - - createNew(panel: NotebookPanel): IDisposable { - const switcher = new InterfaceSwitcher( - this._commands, - this.switcherChoices - ); - panel.toolbar.insertBefore('kernelName', 'switch-interface', switcher); - return switcher; - } - - private _commands: CommandRegistry; -} - -/** - * A plugin to add custom toolbar items to the notebook page - */ -const interfaceSwitcher: JupyterFrontEndPlugin = { - id: '@retrolab/lab-extension:interface-switcher', - autoStart: true, - optional: [INotebookTracker, ICommandPalette, IMainMenu, IRetroShell], - activate: ( - app: JupyterFrontEnd, - notebookTracker: INotebookTracker | null, - palette: ICommandPalette | null, - menu: IMainMenu | null, - retroShell: IRetroShell | null - ) => { - if (!notebookTracker) { - // to prevent showing the toolbar button in RetroLab - return; - } - - const { commands, docRegistry, shell } = app; - const baseUrl = PageConfig.getBaseUrl(); - - const switcherChoices: ISwitcherChoice[] = [ - { - command: 'retrolab:open-classic', - commandLabel: 'Open in Classic Notebook', - dropdownLabel: 'Classic', - urlPrefix: `${baseUrl}tree/`, - current: false - }, - { - command: 'retrolab:open-retro', - commandLabel: 'Open in RetroLab', - dropdownLabel: 'RetroLab', - urlPrefix: `${baseUrl}retro/tree/`, - current: retroShell !== null - }, - { - command: 'retrolab:open-lab', - commandLabel: 'Open in JupyterLab', - dropdownLabel: 'JupyterLab', - urlPrefix: `${baseUrl}lab/tree/`, - // If we aren't in retroShell, assume we're in JupyterLab - // So any new Lab based UIs will fallback to behaving like JupyterLab - current: retroShell === null - } - ]; - - const addInterface = (option: ISwitcherChoice) => { - commands.addCommand(option.command, { - label: option.commandLabel, - execute: () => { - const current = notebookTracker.currentWidget; - if (!current) { - return; - } - window.location.href = `${option.urlPrefix}${current.context.path}`; - }, - isEnabled: () => { - return ( - notebookTracker.currentWidget !== null && - notebookTracker.currentWidget === shell.currentWidget && - !option.current - ); - } - }); - - if (palette) { - palette.addItem({ command: option.command, category: 'Other' }); - } - - if (menu) { - menu.viewMenu.addGroup([{ command: option.command }], 1); - } - }; - - switcherChoices.map(iface => addInterface(iface)); - - const interfaceSwitcher = new InterfaceSwitcherButton( - commands, - switcherChoices - ); - docRegistry.addWidgetExtension('Notebook', interfaceSwitcher); - } -}; - -export { interfaceSwitcher }; diff --git a/packages/lab-extension/tsconfig.json b/packages/lab-extension/tsconfig.json index 1b9e4bfd..34d11b40 100644 --- a/packages/lab-extension/tsconfig.json +++ b/packages/lab-extension/tsconfig.json @@ -6,6 +6,9 @@ }, "include": ["src/**/*"], "references": [ + { + "path": "../application" + }, { "path": "../ui-components" }