Skip to content

Commit

Permalink
Add factory token
Browse files Browse the repository at this point in the history
  • Loading branch information
fcollonval committed Sep 6, 2023
1 parent 01bd241 commit 4a0deb7
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 31 deletions.
7 changes: 6 additions & 1 deletion packages/application/src/plugins/rise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ export const plugin: JupyterFrontEndPlugin<void> = {
app.restored
]).then(async ([settings]) => {
const notebookPath = PageConfig.getOption('notebookPath');
const notebookPanel = documentManager.open(notebookPath) as NotebookPanel;
const notebookPanel = (documentManager.open(notebookPath, 'Notebook') ??
// If the file cannot be opened with the Notebook factory, try jupytext
documentManager.open(
notebookPath,
'Jupytext Notebook'
)) as NotebookPanel;
// With the new windowing, some cells are not visible and we need
// to deactivate the windowing and wait for each cell to be ready.
notebookPanel.content.notebookConfig = {
Expand Down
1 change: 1 addition & 0 deletions packages/lab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"@lumino/coreutils": "^2.0.0",
"@lumino/disposable": "^2.0.0",
"@lumino/messaging": "^2.0.0",
"@lumino/signaling": "^2.0.0",
"@lumino/widgets": "^2.0.1"
},
"devDependencies": {
Expand Down
51 changes: 23 additions & 28 deletions packages/lab/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import {
WidgetTracker
} from '@jupyterlab/apputils';

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

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

import {
Expand All @@ -32,10 +30,11 @@ import { ReadonlyPartialJSONObject } from '@lumino/coreutils';

import { fullScreenIcon, RISEIcon } from './icons';

import { RisePreview, RisePreviewFactory } from './preview';
import { IRisePreviewTracker } from './tokens';
import { RisePreview } from './preview';

import { IRisePreviewFactory, IRisePreviewTracker } from './tokens';

export { IRisePreviewTracker } from './tokens';
export { IRisePreviewFactory, IRisePreviewTracker } from './tokens';

/**
* Command IDs namespace for JupyterLab RISE extension
Expand All @@ -56,13 +55,22 @@ namespace CommandIDs {
export const riseSetSlideType = 'RISE:set-slide-type';
}

const factory: JupyterFrontEndPlugin<IRisePreviewFactory> = {
id: 'jupyterlab-rise:factory',
provides: IRisePreviewFactory,
activate: (app: JupyterFrontEnd): IRisePreviewFactory => {
const { commands, docRegistry } = app;
return new RisePreview.FactoryToken({ commands, docRegistry });
}
};

/**
* Open the notebook with RISE.
*/
const plugin: JupyterFrontEndPlugin<IRisePreviewTracker> = {
id: 'jupyterlab-rise:plugin',
autoStart: true,
requires: [ITranslator],
requires: [IRisePreviewFactory, ITranslator],
optional: [
INotebookTracker,
ICommandPalette,
Expand All @@ -72,6 +80,7 @@ const plugin: JupyterFrontEndPlugin<IRisePreviewTracker> = {
provides: IRisePreviewTracker,
activate: (
app: JupyterFrontEnd,
factory: IRisePreviewFactory,
translator: ITranslator,
notebookTracker: INotebookTracker | null,
palette: ICommandPalette | null,
Expand All @@ -89,7 +98,7 @@ const plugin: JupyterFrontEndPlugin<IRisePreviewTracker> = {
return tracker;
}

const { commands, docRegistry, shell } = app;
const { commands, shell } = app;
const trans = translator.load('rise');

let settings: ISettingRegistry.ISettings | null = null;
Expand All @@ -99,27 +108,19 @@ const plugin: JupyterFrontEndPlugin<IRisePreviewTracker> = {
});
}

const factory = new RisePreviewFactory(getRiseUrl, commands, {
name: 'rise',
fileTypes: ['notebook'],
modelName: 'notebook'
});

if (restorer) {
restorer.restore(tracker, {
// Need to modify to handle auto full screen
command: 'docmanager:open',
args: panel => ({
path: panel.context.path,
factory: factory.name
factory: RisePreview.FACTORY_NAME
}),
name: panel => panel.context.path,
when: app.serviceManager.ready
});
}

docRegistry.addWidgetFactory(factory);

function getCurrent(args: ReadonlyPartialJSONObject): NotebookPanel | null {
const widget = notebookTracker?.currentWidget ?? null;
const activate = args['activate'] !== false;
Expand All @@ -138,15 +139,6 @@ const plugin: JupyterFrontEndPlugin<IRisePreviewTracker> = {
);
}

function getRiseUrl(path: string, activeCellIndex?: number): string {
const baseUrl = PageConfig.getBaseUrl();
let url = `${baseUrl}rise/${path}`;
if (typeof activeCellIndex === 'number') {
url += URLExt.objectToQueryString({ activeCellIndex });
}
return url;
}

factory.widgetCreated.connect((sender, widget) => {
// Notify the widget tracker if restore data needs to update.
widget.context.pathChanged.connect(() => {
Expand All @@ -172,7 +164,10 @@ const plugin: JupyterFrontEndPlugin<IRisePreviewTracker> = {
}
await current.context.save();
window.open(
getRiseUrl(current.context.path, current.content.activeCellIndex)
RisePreview.getRiseUrl(
current.context.path,
current.content.activeCellIndex
)
);
},
isEnabled
Expand All @@ -194,7 +189,7 @@ const plugin: JupyterFrontEndPlugin<IRisePreviewTracker> = {
'docmanager:open',
{
path: context.path,
factory: 'rise',
factory: RisePreview.FACTORY_NAME,
options: {
mode: 'split-right'
}
Expand Down Expand Up @@ -374,4 +369,4 @@ const plugin: JupyterFrontEndPlugin<IRisePreviewTracker> = {
}
};

export default plugin;
export default [factory, plugin];
72 changes: 71 additions & 1 deletion packages/lab/src/preview.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { IFrame, ToolbarButton, Toolbar } from '@jupyterlab/apputils';

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

import {
ABCWidgetFactory,
DocumentRegistry,
Expand All @@ -16,13 +18,16 @@ import { CommandRegistry } from '@lumino/commands';

import { PromiseDelegate } from '@lumino/coreutils';

import { DisposableSet, IDisposable } from '@lumino/disposable';

import { Message } from '@lumino/messaging';

import { Signal } from '@lumino/signaling';
import { ISignal, Signal } from '@lumino/signaling';

import { Widget } from '@lumino/widgets';

import { fullScreenIcon, RISEIcon } from './icons';
import { IRisePreviewFactory } from './tokens';

/**
* A DocumentWidget that shows a Rise preview in an IFrame.
Expand Down Expand Up @@ -212,6 +217,8 @@ export class RisePreview extends DocumentWidget<IFrame, INotebookModel> {
* A namespace for RisePreview statics.
*/
export namespace RisePreview {
export const FACTORY_NAME = 'rise';

/**
* Instantiation options for `RisePreview`.
*/
Expand All @@ -231,6 +238,69 @@ export namespace RisePreview {
*/
renderOnSave?: boolean;
}

export function getRiseUrl(path: string, activeCellIndex?: number): string {
const baseUrl = PageConfig.getBaseUrl();
let url = `${baseUrl}rise/${path}`;
if (typeof activeCellIndex === 'number') {
url += URLExt.objectToQueryString({ activeCellIndex });
}
return url;
}

export class FactoryToken implements IRisePreviewFactory {
constructor(options: {
commands: CommandRegistry;
docRegistry: DocumentRegistry;
fileTypes?: string[];
}) {
const { commands, docRegistry, fileTypes } = options;
this._commands = commands;
this._docRegistry = docRegistry;
this._fileTypes = fileTypes ?? ['notebook'];

this._updateFactory();
}

addFileType(ft: string): void {
if (!this._fileTypes.includes(ft)) {
this._fileTypes.push(ft);
this._updateFactory();
}
}

get widgetCreated(): ISignal<IRisePreviewFactory, RisePreview> {
return this._widgetCreated;
}

private _updateFactory(): void {
if (this._disposeFactory) {
this._disposeFactory.dispose();
this._disposeFactory = null;
}

const factory = new RisePreviewFactory(getRiseUrl, this._commands, {
name: FACTORY_NAME,
fileTypes: this._fileTypes,
modelName: 'notebook'
});

factory.widgetCreated.connect((_, args) => {
this._widgetCreated.emit(args);
}, this);

this._disposeFactory = DisposableSet.from([
this._docRegistry.addWidgetFactory(factory),
factory
]);
}

private _commands: CommandRegistry;
private _disposeFactory: IDisposable | null = null;
private _docRegistry: DocumentRegistry;
private _fileTypes: string[];
private _widgetCreated = new Signal<FactoryToken, RisePreview>(this);
}
}

export class RisePreviewFactory extends ABCWidgetFactory<
Expand Down
20 changes: 19 additions & 1 deletion packages/lab/src/tokens.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IWidgetTracker } from '@jupyterlab/apputils';
import { Token } from '@lumino/coreutils';
import { ISignal } from '@lumino/signaling';
import type { RisePreview } from './preview';

/**
Expand All @@ -12,5 +13,22 @@ export interface IRisePreviewTracker extends IWidgetTracker<RisePreview> {}
* The Rise Preview tracker token.
*/
export const IRisePreviewTracker = new Token<IRisePreviewTracker>(
'jupyterlab-rise:IRisePreviewTracker'
'jupyterlab-rise:IRisePreviewTracker',
'Adds a tracker for RISE slides preview widgets.'
);

/**
*
*/
export interface IRisePreviewFactory {
readonly widgetCreated: ISignal<IRisePreviewFactory, RisePreview>;
addFileType(ft: string): void;
}

/**
*
*/
export const IRisePreviewFactory = new Token<IRisePreviewFactory>(
'jupyterlab-rise:IRisePreviewFactory',
'Customize the RISE slides preview factory.'
);
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9555,6 +9555,7 @@ __metadata:
"@lumino/coreutils": ^2.0.0
"@lumino/disposable": ^2.0.0
"@lumino/messaging": ^2.0.0
"@lumino/signaling": ^2.0.0
"@lumino/widgets": ^2.0.1
rimraf: ~5.0.0
typescript: ~5.0.4
Expand Down

0 comments on commit 4a0deb7

Please sign in to comment.