Add buttons to switch to classic lab and retro

Jeremy Tuloup 5 years ago
parent a396892eb8
commit 3f49eea551

@ -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": {

@ -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<void> = {
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<void> = {
/**
* Export the plugins as default.
*/
const plugins: JupyterFrontEndPlugin<any>[] = [
launchRetroTree,
interfaceSwitcher
];
const plugins: JupyterFrontEndPlugin<any>[] = [launchRetroTree, launchButtons];
export default plugins;

@ -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 (
<HTMLSelect
className="jp-Notebook-toolbarCellTypeDropdown"
value={this.switcherChoices.find(sc => sc.current)?.command}
>
{this.switcherChoices.map(sc => {
return (
<option
key={sc.command}
value={sc.command}
onClick={() => !sc.current && this.commands.execute(sc.command)}
>
{sc.dropdownLabel}
</option>
);
})}
</HTMLSelect>
);
};
}
/**
* A notebook widget extension that adds a open in classic notebook button to the toolbar.
*/
class InterfaceSwitcherButton
implements DocumentRegistry.IWidgetExtension<NotebookPanel, INotebookModel> {
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<void> = {
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 };

@ -6,6 +6,9 @@
},
"include": ["src/**/*"],
"references": [
{
"path": "../application"
},
{
"path": "../ui-components"
}

Loading…
Cancel
Save