Skip to content

Commit

Permalink
refactor into mutiple plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
bollwyvl committed May 7, 2021
1 parent f336b09 commit de174c8
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 46 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ next opened, those overrides will become the defaults, and your tour will be ava
An example `overrides.json` might look like:
```json5
{
"jupyterlab-tour:tours": {
"jupyterlab-tour:user-tours": {
"tours": [
// that tour up there!
]
Expand Down
2 changes: 1 addition & 1 deletion schema/tours.json → schema/user-tours.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"description": "Configuration for user tours. This schema is generated from https://github.com/gilbarbara/react-joyride/blob/master/types/index.d.ts",
"description": "Configuration for user-defined tours. This schema is generated from https://github.com/gilbarbara/react-joyride/blob/master/types/index.d.ts",
"jupyter.lab.setting-icon-label": "Tours",
"title": "Tours",
"type": "object",
Expand Down
9 changes: 4 additions & 5 deletions src/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { UseSignal } from '@jupyterlab/apputils';
import { ISignal } from '@lumino/signaling';
import React from 'react';
import ReactJoyride, { CallBackProps, STATUS } from 'react-joyride';
import { ITourManager } from './tokens';
import { TourHandler } from './tour';
import { ITourHandler, ITourManager } from './tokens';

/**
* Tour component properties
Expand All @@ -12,7 +11,7 @@ interface ITourProps {
/**
* List of tours to play
*/
tours: TourHandler[];
tours: ITourHandler[];
}

/**
Expand Down Expand Up @@ -88,7 +87,7 @@ interface ITourLauncherProps {
/**
* Tours to be run
*/
tours: TourHandler[];
tours: ITourHandler[];
}

/**
Expand All @@ -111,7 +110,7 @@ export interface ITourContainerProps {
/**
* Signal emitting when a tour should be launched
*/
tourLaunched: ISignal<ITourManager, TourHandler[]>;
tourLaunched: ISignal<ITourManager, ITourHandler[]>;
}

/**
Expand Down
77 changes: 54 additions & 23 deletions src/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import { TourContainer } from './components';
import { CommandIDs, NOTEBOOK_ID, WELCOME_ID } from './constants';
import { addTours } from './defaults';
import {
DEFAULTS_PLUGIN_ID,
ITourHandler,
ITourManager,
PLUGIN_ID,
USER_TOURS_SETTINGS
USER_PLUGIN_ID
} from './tokens';
import { TourHandler } from './tour';
import { TourManager } from './tourManager';
Expand All @@ -26,22 +27,20 @@ import { addJSONTour } from './utils';
/**
* Initialization data for the jupyterlab-tour extension.
*/
const extension: JupyterFrontEndPlugin<ITourManager> = {
id: `${PLUGIN_ID}:plugin`,
const plugin: JupyterFrontEndPlugin<ITourManager> = {
id: PLUGIN_ID,
autoStart: true,
activate,
requires: [IStateDB],
optional: [ICommandPalette, IMainMenu, INotebookTracker, ISettingRegistry],
optional: [ICommandPalette, IMainMenu],
provides: ITourManager
};

function activate(
app: JupyterFrontEnd,
stateDB: IStateDB,
palette?: ICommandPalette,
menu?: MainMenu,
nbTracker?: INotebookTracker,
settings?: ISettingRegistry
menu?: MainMenu
): ITourManager {
const { commands } = app;

Expand Down Expand Up @@ -98,35 +97,67 @@ function activate(
});
}

addTours(manager, app, nbTracker);

const node = document.createElement('div');

document.body.appendChild(node);
ReactDOM.render(<TourContainer tourLaunched={manager.tourLaunched} />, node);

return manager;
}

/**
* Optional plugin for user-defined tours stored in the settings registry
*/
const userPlugin: JupyterFrontEndPlugin<void> = {
id: USER_PLUGIN_ID,
autoStart: true,
activate: activateUser,
requires: [ISettingRegistry, ITourManager]
};

function activateUser(
app: JupyterFrontEnd,
settings: ISettingRegistry,
tours: ITourManager
): void {
settings
.load(USER_PLUGIN_ID)
.then(settings => (tours.userTours = settings))
.catch(err => console.error(err));
}

/**
* Optional plugin for the curated default tours and default toast behavior
*/
const defaultPlugin: JupyterFrontEndPlugin<void> = {
id: DEFAULTS_PLUGIN_ID,
autoStart: true,
activate: activateDefaults,
requires: [ITourManager],
optional: [INotebookTracker]
};

function activateDefaults(
app: JupyterFrontEnd,
tourManager: ITourManager,
nbTracker?: INotebookTracker
): void {
addTours(tourManager, app, nbTracker);

if (nbTracker) {
nbTracker.widgetAdded.connect(() => {
if (manager.tours.has(NOTEBOOK_ID)) {
manager.launch([NOTEBOOK_ID], false);
if (tourManager.tours.has(NOTEBOOK_ID)) {
tourManager.launch([NOTEBOOK_ID], false);
}
});
}

app.restored.then(() => {
if (manager.tours.has(WELCOME_ID)) {
if (tourManager.tours.has(WELCOME_ID)) {
// Wait 3s before launching the first tour - to be sure element are loaded
setTimeout(() => manager.launch([WELCOME_ID], false), 3000);
setTimeout(() => tourManager.launch([WELCOME_ID], false), 3000);
}
});

if (settings) {
settings
.load(USER_TOURS_SETTINGS)
.then(settings => (manager.userTours = settings))
.catch(err => console.error(err));
}

return manager;
}

export default extension;
export default [plugin, userPlugin, defaultPlugin];
35 changes: 24 additions & 11 deletions src/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,29 @@ import {
} from 'react-joyride';

/**
* Extension ID
* Namespace for everything
*/
export const PLUGIN_ID = 'jupyterlab-tour';
export const NS = 'jupyterlab-tour';

/**
* Settings key for user-defined tours
*
* @see ../schema/tours.json
* Core Extension ID
*/
export const USER_TOURS_SETTINGS = `${PLUGIN_ID}:tours`;
export const PLUGIN_ID = `${NS}:plugin`;

/**
* A prefix appended to all user tour ids.
* User-defined tours extension ID
*/
export const USER_TOUR_ID_PREFIX = `${PLUGIN_ID}:user-tour`;
export const USER_PLUGIN_ID = `${NS}:user-tours`;

/**
* First-party curated tours, like Notebook and Welcomes
*/
export const DEFAULTS_PLUGIN_ID = `${NS}:default-tours`;

/**
* Token to get a reference to the tours manager
*/
export const ITourManager = new Token<ITourManager>(
`${PLUGIN_ID}:ITourManager`
);
export const ITourManager = new Token<ITourManager>(`${NS}:ITourManager`);

/**
* Serialized step interface
Expand Down Expand Up @@ -110,6 +111,13 @@ export interface ITourHandler extends IDisposable {
title?: string
): Step;

/**
* Handle react-joyride callbacks
*
* @param data Callback data
*/
handleTourEvent(data: CallBackProps): void;

/**
* The index of the current step of the tour. Returns -1 if tour isn't active.
*/
Expand Down Expand Up @@ -190,6 +198,11 @@ export interface ITourManager extends IDisposable {
*/
readonly activeTour: ITourHandler | undefined;

/**
* Signal emmitted with the set of tours to show to the user
*/
readonly tourLaunched: ISignal<ITourManager, ITourHandler[]>;

/**
* Creates an interactive TourHandler object that can be customized and run by the TourManager.
* @param id The id used to track the tour.
Expand Down
10 changes: 5 additions & 5 deletions src/tourManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import {
ITour,
ITourHandler,
ITourManager,
PLUGIN_ID,
USER_TOUR_ID_PREFIX
NS,
USER_PLUGIN_ID
} from './tokens';
import { TourHandler } from './tour';
import { version } from './version';
import { Menu } from '@lumino/widgets';

const STATE_ID = `${PLUGIN_ID}:state`;
const STATE_ID = `${NS}:state`;

/**
* Manager state saved in the state database
Expand Down Expand Up @@ -292,7 +292,7 @@ export class TourManager implements ITourManager {
}

for (const id of this._tours.keys()) {
if (id.startsWith(USER_TOUR_ID_PREFIX)) {
if (id.startsWith(USER_PLUGIN_ID)) {
this.removeTour(id);
}
}
Expand Down Expand Up @@ -320,7 +320,7 @@ export class TourManager implements ITourManager {
*/
private _addUserTour(tour: ITour): void {
const handler = this.createTour(
`${USER_TOUR_ID_PREFIX}:${tour.id}`,
`${USER_PLUGIN_ID}:${tour.id}`,
tour.label,
tour.hasHelpEntry === false ? false : true,
tour.options
Expand Down

0 comments on commit de174c8

Please sign in to comment.