Skip to content
This repository has been archived by the owner on Feb 16, 2023. It is now read-only.

Add an 'interface switcher' to the toolbar #158

Merged
merged 6 commits into from
Sep 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/lab-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
167 changes: 104 additions & 63 deletions packages/lab-extension/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,91 +7,86 @@ import {
JupyterFrontEndPlugin
} from '@jupyterlab/application';

import { ICommandPalette, ToolbarButton } from '@jupyterlab/apputils';
import { CommandToolbarButton, ICommandPalette } from '@jupyterlab/apputils';

import { PageConfig } from '@jupyterlab/coreutils';

import { DocumentRegistry } from '@jupyterlab/docregistry';

import { IMainMenu } from '@jupyterlab/mainmenu';

import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook';

import { ITranslator } from '@jupyterlab/translation';

import {
INotebookModel,
INotebookTracker,
NotebookPanel
} from '@jupyterlab/notebook';

import { retroSunIcon } from '@retrolab/ui-components';
jupyterIcon,
jupyterFaviconIcon,
LabIcon
} from '@jupyterlab/ui-components';

import { CommandRegistry } from '@lumino/commands';
import { IRetroShell } from '@retrolab/application';

import { IDisposable } from '@lumino/disposable';
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 openRetro = 'retrolab:open';
export const launchRetroTree = 'retrolab:launchtree';
}
export const launchRetroTree = 'retrolab:launch-tree';

/**
* A notebook widget extension that adds a retrolab button to the toolbar.
*/
class RetroButton
implements DocumentRegistry.IWidgetExtension<NotebookPanel, INotebookModel> {
/**
* Instantiate a new RetroButton.
* @param commands The command registry.
* Open RetroLab
*/
constructor(commands: CommandRegistry) {
this._commands = commands;
}
export const openRetro = 'retrolab:open-retro';

/**
* Create a new extension object.
* Open in Classic Notebook
*/
createNew(panel: NotebookPanel): IDisposable {
const button = new ToolbarButton({
tooltip: 'Open with RetroLab',
icon: retroSunIcon,
onClick: () => {
this._commands.execute(CommandIDs.openRetro);
}
});
panel.toolbar.insertAfter('cellType', 'retro', button);
return button;
}
export const openClassic = 'retrolab:open-classic';

private _commands: CommandRegistry;
/**
* Open in JupyterLab
*/
export const openLab = 'retrolab:open-lab';
}

interface ISwitcherChoice {
command: string;
commandLabel: string;
buttonLabel: string;
icon: LabIcon;
urlPrefix: string;
}

/**
* A plugin for the checkpoint indicator
* A plugin to add custom toolbar items to the notebook page
*/
const openRetro: JupyterFrontEndPlugin<void> = {
id: '@retrolab/lab-extension:open-retro',
const launchButtons: JupyterFrontEndPlugin<void> = {
id: '@retrolab/lab-extension:interface-switcher',
autoStart: true,
optional: [INotebookTracker, ICommandPalette, IMainMenu, ILabShell],
optional: [
INotebookTracker,
ICommandPalette,
IMainMenu,
IRetroShell,
ILabShell
],
activate: (
app: JupyterFrontEnd,
notebookTracker: INotebookTracker | null,
palette: ICommandPalette | null,
menu: IMainMenu | null,
retroShell: IRetroShell | null,
labShell: ILabShell | null
) => {
// TODO: do not activate if already in a IRetroShell?
if (!notebookTracker || !labShell) {
if (!notebookTracker) {
// to prevent showing the toolbar button in RetroLab
return;
}

const { commands, docRegistry, shell } = app;
const { commands, shell } = app;
const baseUrl = PageConfig.getBaseUrl();

const isEnabled = () => {
Expand All @@ -101,29 +96,75 @@ const openRetro: JupyterFrontEndPlugin<void> = {
);
};

commands.addCommand(CommandIDs.openRetro, {
label: 'Open in RetroLab',
execute: () => {
const current = notebookTracker.currentWidget;
if (!current) {
return;
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();
}
const { context } = current;
window.open(`${baseUrl}retro/notebooks/${context.path}`);
},
isEnabled
);
};

// always add Classic
addInterface({
command: 'retrolab:open-classic',
commandLabel: 'Open in Classic Notebook',
buttonLabel: 'openClassic',
icon: jupyterIcon,
urlPrefix: `${baseUrl}tree/`
});

if (palette) {
palette.addItem({ command: CommandIDs.openRetro, category: 'Other' });
if (!retroShell) {
addInterface({
command: 'retrolab:open-retro',
commandLabel: 'Open in RetroLab',
buttonLabel: 'openRetro',
icon: retroSunIcon,
urlPrefix: `${baseUrl}retro/tree/`
});
}

if (menu) {
menu.viewMenu.addGroup([{ command: CommandIDs.openRetro }], 1);
if (!labShell) {
addInterface({
command: 'retrolab:open-lab',
commandLabel: 'Open in JupyterLab',
buttonLabel: 'openLab',
icon: jupyterFaviconIcon,
urlPrefix: `${baseUrl}doc/tree/`
});
}

const retroButton = new RetroButton(commands);
docRegistry.addWidgetExtension('Notebook', retroButton);
}
};

Expand Down Expand Up @@ -166,6 +207,6 @@ const launchRetroTree: JupyterFrontEndPlugin<void> = {
/**
* Export the plugins as default.
*/
const plugins: JupyterFrontEndPlugin<any>[] = [launchRetroTree, openRetro];
const plugins: JupyterFrontEndPlugin<any>[] = [launchRetroTree, launchButtons];

export default plugins;
3 changes: 3 additions & 0 deletions packages/lab-extension/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
},
"include": ["src/**/*"],
"references": [
{
"path": "../application"
},
{
"path": "../ui-components"
}
Expand Down