jupyterlab-tour 3.1.3 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -75
- package/lib/__tests__/plugin.spec.d.ts +1 -0
- package/lib/__tests__/plugin.spec.js +151 -0
- package/lib/components.js +1 -1
- package/lib/defaults.js +480 -282
- package/lib/icons.d.ts +8 -0
- package/lib/icons.js +37 -0
- package/lib/notebookButton.d.ts +21 -0
- package/lib/notebookButton.js +69 -0
- package/lib/notebookTourManager.d.ts +43 -0
- package/lib/notebookTourManager.js +124 -0
- package/lib/package.json +215 -0
- package/lib/plugin.d.ts +3 -3
- package/lib/plugin.js +79 -24
- package/lib/schema/user-tours.json +862 -0
- package/lib/tokens.d.ts +142 -7
- package/lib/tokens.js +10 -1
- package/lib/tour.d.ts +17 -1
- package/lib/tour.js +27 -15
- package/lib/tourManager.d.ts +21 -8
- package/lib/tourManager.js +111 -49
- package/lib/userTourManager.d.ts +0 -5
- package/lib/userTourManager.js +9 -27
- package/package.json +212 -100
- package/schema/user-tours.json +18 -10
- package/style/base.css +5 -1
- package/style/img/bad-pin.svg +5 -0
- package/style/img/notebook-pin.svg +5 -0
- package/style/img/person-pin.svg +5 -0
- package/style/img/pin.svg +5 -0
- package/lib/version.d.ts +0 -1
- package/lib/version.js +0 -2
package/README.md
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
# jupyterlab-tour
|
|
2
2
|
|
|
3
|
+
[](https://jupyterlab-contrib.github.io/)
|
|
3
4
|
[](https://github.com/jupyterlab-contrib/jupyterlab-tour/actions?query=workflow%3ABuild)
|
|
4
|
-
[](https://mybinder.org/v2/gh/jupyterlab-contrib/jupyterlab-tour
|
|
5
|
+
[](https://mybinder.org/v2/gh/jupyterlab-contrib/jupyterlab-tour/main?urlpath=lab)
|
|
5
6
|
[](https://www.npmjs.com/package/jupyterlab-tour)
|
|
6
7
|
[](https://pypi.org/project/jupyterlab-tour)
|
|
7
8
|
[](https://anaconda.org/conda-forge/jupyterlab-tour)
|
|
8
9
|
|
|
9
10
|
A JupyterLab UI Tour based on [react-joyride](https://docs.react-joyride.com).
|
|
10
11
|
|
|
11
|
-

|
|
12
13
|
|
|
13
14
|
## Install
|
|
14
15
|
|
|
16
|
+
To install the extension, execute:
|
|
17
|
+
|
|
15
18
|
```bash
|
|
16
19
|
pip install jupyterlab-tour
|
|
17
20
|
```
|
|
@@ -30,31 +33,38 @@ This extension has the following features:
|
|
|
30
33
|
- Welcome tour
|
|
31
34
|
- Notebook tour
|
|
32
35
|
- User-defined features in Settings
|
|
33
|
-
- Toast proposing to start a
|
|
34
|
-
- If a
|
|
36
|
+
- Toast proposing to start a Tour
|
|
37
|
+
- If a Tour has already be seen by the user, this is saved in the state database. So you
|
|
38
|
+
can start Tour on event only if the user have not seen it; e.g. the _Welcome Tour_ is
|
|
39
|
+
launched at JupyterLab start except if the user have seen it.
|
|
35
40
|
|
|
36
41
|
> The state is cleaned if this extension is updated
|
|
37
42
|
|
|
38
43
|
- Tooltip are styled using JupyterLab theming system
|
|
39
44
|
- Commands to _add_ and _launch_ tours
|
|
40
|
-
- Through the
|
|
41
|
-
|
|
42
|
-
-
|
|
45
|
+
- Through the _Tour Manager_ (`ITourManager` extension token), add, modify or delete a
|
|
46
|
+
Tour
|
|
47
|
+
- Connect to Tour events through signals
|
|
48
|
+
- Override the default style (and options) for the Tour separately
|
|
43
49
|
|
|
44
|
-
This extension is inspired by
|
|
50
|
+
This extension is inspired by
|
|
51
|
+
[@cdat/jupyterlab-tutorial](https://github.com/CDAT/jupyterlab-tutorial) licensed under
|
|
52
|
+
BSD 3-Clause License with Copyright (c) 2020, Lawrence Livermore National Security, LLC.
|
|
45
53
|
|
|
46
54
|
## Requirements
|
|
47
55
|
|
|
48
|
-
- JupyterLab >= 3.
|
|
56
|
+
- JupyterLab >= 3.6
|
|
49
57
|
|
|
50
|
-
For JupyterLab 2.x, have look
|
|
58
|
+
For JupyterLab 2.x, have look
|
|
59
|
+
[there](https://github.com/jupyterlab-contrib/jupyterlab-tour/tree/2.x).
|
|
51
60
|
|
|
52
|
-
> For developers, the API has changed between v3 (for JupyterLab 3) and v2 (for
|
|
61
|
+
> For developers, the API has changed between v3 (for JupyterLab 3) and v2 (for
|
|
62
|
+
> JupyterLab 2).
|
|
53
63
|
|
|
54
|
-
## How to add a
|
|
64
|
+
## How to add a Tour with Advanced Settings
|
|
55
65
|
|
|
56
|
-
As a user of JupyterLab, after you've installed `jupyterlab-tour`, you can create
|
|
57
|
-
|
|
66
|
+
As a user of JupyterLab, after you've installed `jupyterlab-tour`, you can create your
|
|
67
|
+
own _Tours_ as data.
|
|
58
68
|
|
|
59
69
|
- Open the JupyterLab _Advanced Settings_ panel <kbd>Ctrl+,</kbd>
|
|
60
70
|
- Select _Tours_ from list of settings groups
|
|
@@ -70,20 +80,18 @@ overlay when pressed:
|
|
|
70
80
|
```json5
|
|
71
81
|
// json5 can have comments
|
|
72
82
|
{
|
|
73
|
-
|
|
83
|
+
tours: [
|
|
74
84
|
{
|
|
75
|
-
|
|
76
|
-
|
|
85
|
+
id: 'my-tour',
|
|
86
|
+
label: 'My First Tour',
|
|
77
87
|
// steps are required, and have many, many options
|
|
78
|
-
|
|
79
|
-
{"target": "#jp-MainLogo", "content": "Look at this!"}
|
|
80
|
-
],
|
|
88
|
+
steps: [{ target: '#jp-MainLogo', content: 'Look at this!' }],
|
|
81
89
|
// below here not required!
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
90
|
+
options: {
|
|
91
|
+
styles: {
|
|
92
|
+
options: {
|
|
85
93
|
// you can use jupyterlab theme variables
|
|
86
|
-
|
|
94
|
+
backgroundColor: 'var(--jp-warn-color0)'
|
|
87
95
|
}
|
|
88
96
|
}
|
|
89
97
|
}
|
|
@@ -92,42 +100,65 @@ overlay when pressed:
|
|
|
92
100
|
}
|
|
93
101
|
```
|
|
94
102
|
|
|
103
|
+
## How to add a Tour to a Notebook
|
|
104
|
+
|
|
105
|
+
The same JSON used to create a Tour in _Advanced Settings_ can be added to a Notebook.
|
|
106
|
+
|
|
107
|
+
- Open the Notebook
|
|
108
|
+
- Open the _Property Inspector_ sidebar (the "gears" icon)
|
|
109
|
+
- Open _Advanced Tools_
|
|
110
|
+
- Create a key in _Notebook Metadata_ like:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"jupyterlab-tour": {
|
|
115
|
+
"tours": []
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Now, when the notebook is opened, a "pin" icon will be visible in the _Notebook Toolbar_
|
|
121
|
+
which will allow lauching one (or all) of the tours saved in the Notebook.
|
|
122
|
+
|
|
95
123
|
### Shipping a Tour to Binder
|
|
96
124
|
|
|
97
|
-
On Binder, and elsewhere, you can store the above (_without_ comments) in
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
125
|
+
On Binder, and elsewhere, you can store the above (_without_ comments) in an
|
|
126
|
+
[overrides.json] file and put it in the _right place_, e.g.
|
|
127
|
+
`{sys.prefix}/share/jupyter/lab/settings/overrides.json`. When JupyterLab is next
|
|
128
|
+
opened, those overrides will become the defaults, and your Tour will be available.
|
|
101
129
|
|
|
102
130
|
An example `overrides.json` might look like:
|
|
103
|
-
|
|
131
|
+
|
|
132
|
+
```json
|
|
104
133
|
{
|
|
105
134
|
"jupyterlab-tour:user-tours": {
|
|
106
|
-
"tours": [
|
|
107
|
-
// that tour up there!
|
|
108
|
-
]
|
|
135
|
+
"tours": []
|
|
109
136
|
}
|
|
110
137
|
}
|
|
111
138
|
```
|
|
112
139
|
|
|
113
|
-
[overrides.json]:
|
|
140
|
+
[overrides.json]:
|
|
141
|
+
https://jupyterlab.readthedocs.io/en/stable/user/directories.html#overrides-json
|
|
114
142
|
|
|
115
|
-
## How to add
|
|
143
|
+
## How to add Tour for my JupyterLab extension
|
|
116
144
|
|
|
117
|
-
As an extension developer, there are two methods to add a tour: the easiest is to use
|
|
118
|
-
extension token
|
|
145
|
+
As an extension developer, there are two methods to add a tour: the easiest is to use
|
|
146
|
+
JupyterLab commands and the advanced version is to request this extension token
|
|
147
|
+
`ITourManager`.
|
|
119
148
|
|
|
120
|
-
### Add
|
|
149
|
+
### Add a Tour with TypeScript
|
|
121
150
|
|
|
122
151
|
```ts
|
|
123
152
|
const { commands } = app;
|
|
124
|
-
// Add a
|
|
153
|
+
// Add a Tour - returns the Tour or null if something went wrong
|
|
125
154
|
const tour = (await app.commands.execute('jupyterlab-tour:add', {
|
|
126
|
-
tour: {
|
|
155
|
+
tour: {
|
|
156
|
+
// Tour must be of type ITour - see src/tokens.ts
|
|
127
157
|
id: 'test-jupyterlab-tour:welcome',
|
|
128
158
|
label: 'Welcome Tour',
|
|
129
159
|
hasHelpEntry: true,
|
|
130
|
-
steps: [
|
|
160
|
+
steps: [
|
|
161
|
+
// Step must be of type IStep - see src/tokens.ts
|
|
131
162
|
{
|
|
132
163
|
content:
|
|
133
164
|
'The following tutorial will point out some of the main UI components within JupyterLab.',
|
|
@@ -142,46 +173,48 @@ const tour = (await app.commands.execute('jupyterlab-tour:add', {
|
|
|
142
173
|
target: '#jp-main-dock-panel',
|
|
143
174
|
title: 'Main Content'
|
|
144
175
|
}
|
|
145
|
-
]
|
|
176
|
+
]
|
|
146
177
|
// can also define `options`
|
|
147
178
|
}
|
|
148
179
|
})) as ITourHandler;
|
|
149
|
-
if (
|
|
180
|
+
if (tour) {
|
|
150
181
|
app.commands.execute('jupyterlab-tour:launch', {
|
|
151
182
|
id: 'test-jupyterlab-tour:welcome',
|
|
152
|
-
force: false
|
|
153
|
-
})
|
|
183
|
+
force: false // Optional, if false the Tour will start only if the user have not seen or skipped it
|
|
184
|
+
});
|
|
154
185
|
}
|
|
155
186
|
```
|
|
156
187
|
|
|
157
|
-
> One example is available on
|
|
188
|
+
> One example is available on
|
|
189
|
+
> [Mamba navigator](https://github.com/mamba-org/gator/blob/master/packages/labextension/src/index.ts#L76).
|
|
158
190
|
> Test it on [binder](https://mybinder.org/v2/gh/mamba-org/gator/master?urlpath=lab).
|
|
159
191
|
|
|
160
|
-
If you want to react to step changes to trigger elements of the UI (like opening
|
|
161
|
-
to the `stepChanged` signal. Building from the previous
|
|
162
|
-
after the first step.
|
|
192
|
+
If you want to react to step changes to trigger elements of the UI (like opening
|
|
193
|
+
sidebar), you can connect to the `stepChanged` signal. Building from the previous
|
|
194
|
+
example, this snippet will open the filebrowser after the first step.
|
|
163
195
|
|
|
164
196
|
```ts
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
197
|
+
tour.stepChanged.connect((_, data) => {
|
|
198
|
+
switch (data.type) {
|
|
199
|
+
case 'step:after':
|
|
200
|
+
if (data.step.target === '#jp-main-dock-panel') {
|
|
201
|
+
commands.execute('filebrowser:activate');
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
174
206
|
```
|
|
175
207
|
|
|
176
|
-
> `data` is an object of type
|
|
208
|
+
> `data` is an object of type
|
|
209
|
+
> [`CallbackProps`](https://docs.react-joyride.com/callback).
|
|
177
210
|
|
|
178
|
-
## Disabling the User and Default Tours
|
|
211
|
+
## Disabling the User, Notebook, and Default Tours
|
|
179
212
|
|
|
180
|
-
If you _only_ wish to see the default _Welcome_ and _Notebook_ tours, or ones
|
|
181
|
-
|
|
213
|
+
If you _only_ wish to see the default _Welcome_ and _Notebook_ tours, or ones defined by
|
|
214
|
+
users, they can be disabled via the command line or a well-known file.
|
|
182
215
|
|
|
183
|
-
The examples below disable all tours not provided by third-party extensions.
|
|
184
|
-
|
|
216
|
+
The examples below disable all tours not provided by third-party extensions. Adding
|
|
217
|
+
`jupyterlab-tour:plugin` to either of these will disable tours altogether!
|
|
185
218
|
|
|
186
219
|
### Disabling Tours from the Command Line
|
|
187
220
|
|
|
@@ -189,6 +222,7 @@ From the command line, run:
|
|
|
189
222
|
|
|
190
223
|
```bash
|
|
191
224
|
jupyter labextension disable "jupyterlab-tour:user-tours"
|
|
225
|
+
jupyter labextension disable "jupyterlab-tour:notebook-tours"
|
|
192
226
|
jupyter labextension disable "jupyterlab-tour:default-tours"
|
|
193
227
|
```
|
|
194
228
|
|
|
@@ -202,16 +236,19 @@ Create a [pageConfig.json] and put it in _the right place_, e.g.
|
|
|
202
236
|
{
|
|
203
237
|
"disabledExtensions": {
|
|
204
238
|
"jupyterlab-tour:user-tours": true,
|
|
205
|
-
"jupyterlab-tour:
|
|
239
|
+
"jupyterlab-tour:notebook-tours": true,
|
|
240
|
+
"jupyterlab-tour:default-tours": true
|
|
206
241
|
}
|
|
207
242
|
}
|
|
208
243
|
```
|
|
209
244
|
|
|
210
|
-
[pageConfig.json]:
|
|
211
|
-
|
|
245
|
+
[pageConfig.json]:
|
|
246
|
+
https://jupyterlab.readthedocs.io/en/stable/user/directories.html#labconfig-directories
|
|
212
247
|
|
|
213
248
|
## Uninstall
|
|
214
249
|
|
|
250
|
+
To remove the extension, execute:
|
|
251
|
+
|
|
215
252
|
```bash
|
|
216
253
|
pip uninstall jupyterlab-tour
|
|
217
254
|
```
|
|
@@ -228,34 +265,76 @@ conda remove -c conda-forge jupyterlab-tour
|
|
|
228
265
|
|
|
229
266
|
Note: You will need NodeJS to build the extension package.
|
|
230
267
|
|
|
231
|
-
The `jlpm` command is JupyterLab's pinned version of
|
|
232
|
-
|
|
233
|
-
`yarn` or `npm` in lieu of `jlpm` below.
|
|
268
|
+
The `jlpm` command is JupyterLab's pinned version of [yarn](https://yarnpkg.com/) that
|
|
269
|
+
is installed with JupyterLab. You may use `yarn` or `npm` in lieu of `jlpm` below.
|
|
234
270
|
|
|
235
271
|
```bash
|
|
236
272
|
# Clone the repo to your local environment
|
|
237
273
|
# Change directory to the jupyterlab-tour directory
|
|
238
274
|
# Install package in development mode
|
|
239
|
-
pip install -e .
|
|
275
|
+
pip install -e "."
|
|
240
276
|
# Link your development version of the extension with JupyterLab
|
|
241
277
|
jupyter labextension develop . --overwrite
|
|
242
278
|
# Rebuild extension Typescript source after making changes
|
|
243
|
-
jlpm
|
|
279
|
+
jlpm build
|
|
244
280
|
```
|
|
245
281
|
|
|
246
|
-
You can watch the source directory and run JupyterLab at the same time in different
|
|
282
|
+
You can watch the source directory and run JupyterLab at the same time in different
|
|
283
|
+
terminals to watch for changes in the extension's source and automatically rebuild the
|
|
284
|
+
extension.
|
|
247
285
|
|
|
248
286
|
```bash
|
|
249
287
|
# Watch the source directory in one terminal, automatically rebuilding when needed
|
|
250
|
-
jlpm
|
|
288
|
+
jlpm watch
|
|
251
289
|
# Run JupyterLab in another terminal
|
|
252
290
|
jupyter lab
|
|
253
291
|
```
|
|
254
292
|
|
|
255
|
-
With the watch command running, every saved change will immediately be built locally and
|
|
293
|
+
With the watch command running, every saved change will immediately be built locally and
|
|
294
|
+
available in your running JupyterLab. Refresh JupyterLab to load the change in your
|
|
295
|
+
browser (you may need to wait several seconds for the extension to be rebuilt).
|
|
256
296
|
|
|
257
|
-
By default, the `jlpm
|
|
297
|
+
By default, the `jlpm build` command generates the source maps for this extension to
|
|
298
|
+
make it easier to debug using the browser dev tools. To also generate source maps for
|
|
299
|
+
the JupyterLab core extensions, you can run the following command:
|
|
258
300
|
|
|
259
301
|
```bash
|
|
260
302
|
jupyter lab build --minimize=False
|
|
261
303
|
```
|
|
304
|
+
|
|
305
|
+
### Development uninstall
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
pip uninstall jupyterlab-tour
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
In development mode, you will also need to remove the symlink created by
|
|
312
|
+
`jupyter labextension develop` command. To find its location, you can run
|
|
313
|
+
`jupyter labextension list` to figure out where the `labextensions` folder is located.
|
|
314
|
+
Then you can remove the symlink named `jupyterlab-tour` within that folder.
|
|
315
|
+
|
|
316
|
+
### Testing the extension
|
|
317
|
+
|
|
318
|
+
#### Frontend tests
|
|
319
|
+
|
|
320
|
+
This extension is using [Jest](https://jestjs.io/) for JavaScript code testing.
|
|
321
|
+
|
|
322
|
+
To execute them, execute:
|
|
323
|
+
|
|
324
|
+
```sh
|
|
325
|
+
jlpm
|
|
326
|
+
jlpm test
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
#### Integration tests
|
|
330
|
+
|
|
331
|
+
This extension uses [Playwright](https://playwright.dev/docs/intro) for the integration
|
|
332
|
+
tests (aka user level tests). More precisely, the JupyterLab helper
|
|
333
|
+
[Galata](https://github.com/jupyterlab/jupyterlab/tree/master/galata) is used to handle
|
|
334
|
+
testing the extension in JupyterLab.
|
|
335
|
+
|
|
336
|
+
More information are provided within the [ui-tests](./ui-tests/README.md) README.
|
|
337
|
+
|
|
338
|
+
### Packaging the extension
|
|
339
|
+
|
|
340
|
+
See [RELEASE](RELEASE.md)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'jest';
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Notebook, NotebookModel, NotebookPanel } from '@jupyterlab/notebook';
|
|
2
|
+
import { CommandRegistry } from '@lumino/commands';
|
|
3
|
+
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
|
4
|
+
import { CodeMirrorEditorFactory, CodeMirrorMimeTypeService, EditorLanguageRegistry } from '@jupyterlab/codemirror';
|
|
5
|
+
import { Signal } from '@lumino/signaling';
|
|
6
|
+
import 'jest';
|
|
7
|
+
import { CommandIDs } from '../constants';
|
|
8
|
+
import plugin from '../index';
|
|
9
|
+
import { NS } from '../tokens';
|
|
10
|
+
const DEFAULT_TOURS_SIZE = 2;
|
|
11
|
+
const [corePlugin, userPlugin, notebookPlugin, defaultsPlugin] = plugin;
|
|
12
|
+
function mockApp() {
|
|
13
|
+
return {
|
|
14
|
+
commands: new CommandRegistry(),
|
|
15
|
+
restored: Promise.resolve(),
|
|
16
|
+
docRegistry: new DocumentRegistry()
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function aTour() {
|
|
20
|
+
return {
|
|
21
|
+
id: 'test-jupyterlab-tour:welcome',
|
|
22
|
+
label: 'Welcome Tour',
|
|
23
|
+
hasHelpEntry: true,
|
|
24
|
+
steps: [
|
|
25
|
+
{
|
|
26
|
+
content: 'Tours of Jupyter',
|
|
27
|
+
placement: 'auto',
|
|
28
|
+
target: '#jp-MainLogo',
|
|
29
|
+
title: 'Jupyter'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
content: 'The following tour will point out some of the main UI components within JupyterLab.',
|
|
33
|
+
placement: 'right',
|
|
34
|
+
target: '#jp-main-dock-panel',
|
|
35
|
+
title: 'Welcome to Jupyter Lab!'
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
content: 'This is the main content area where notebooks and other content can be viewed and edited.',
|
|
39
|
+
placement: 'center',
|
|
40
|
+
target: '#jp-main-dock-panel',
|
|
41
|
+
title: 'Main Content'
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function mockSettingRegistry() {
|
|
47
|
+
const settings = {
|
|
48
|
+
composite: { tours: [aTour()] }
|
|
49
|
+
};
|
|
50
|
+
settings['changed'] = new Signal(settings);
|
|
51
|
+
return {
|
|
52
|
+
load: async () => settings
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function mockNbTracker() {
|
|
56
|
+
const nbTracker = {};
|
|
57
|
+
nbTracker.widgetAdded = new Signal(nbTracker);
|
|
58
|
+
return nbTracker;
|
|
59
|
+
}
|
|
60
|
+
describe(corePlugin.id, () => {
|
|
61
|
+
describe('activation', () => {
|
|
62
|
+
it('should create add-tour command', () => {
|
|
63
|
+
var _a;
|
|
64
|
+
const app = mockApp();
|
|
65
|
+
corePlugin.activate(app);
|
|
66
|
+
expect((_a = app.commands) === null || _a === void 0 ? void 0 : _a.hasCommand(CommandIDs.addTour)).toEqual(true);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('commands', () => {
|
|
70
|
+
describe(`${CommandIDs.addTour}`, () => {
|
|
71
|
+
it('should add a tour command', async () => {
|
|
72
|
+
var _a;
|
|
73
|
+
const app = mockApp();
|
|
74
|
+
const manager = corePlugin.activate(app);
|
|
75
|
+
expect(manager.tours.size).toEqual(0);
|
|
76
|
+
const tour = await ((_a = app.commands) === null || _a === void 0 ? void 0 : _a.execute(CommandIDs.addTour, {
|
|
77
|
+
tour: aTour()
|
|
78
|
+
}));
|
|
79
|
+
expect(manager.tours.size).toEqual(1);
|
|
80
|
+
expect(tour).toBeTruthy();
|
|
81
|
+
expect(manager.tours.get(tour.id)).toBeTruthy();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe(userPlugin.id, () => {
|
|
87
|
+
describe('activation', () => {
|
|
88
|
+
it('should have userTours', async () => {
|
|
89
|
+
const app = mockApp();
|
|
90
|
+
const manager = corePlugin.activate(app);
|
|
91
|
+
const settings = mockSettingRegistry();
|
|
92
|
+
const userManager = userPlugin.activate(app, settings, manager);
|
|
93
|
+
await userManager.ready;
|
|
94
|
+
expect(userManager.tourManager.tours.size).toBe(1);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe('settings', () => {
|
|
98
|
+
it('should react to settings', async () => {
|
|
99
|
+
const app = mockApp();
|
|
100
|
+
const manager = corePlugin.activate(app);
|
|
101
|
+
const settingsRegistry = mockSettingRegistry();
|
|
102
|
+
const userManager = userPlugin.activate(app, settingsRegistry, manager);
|
|
103
|
+
await userManager.ready;
|
|
104
|
+
const settings = await settingsRegistry.load('whatever');
|
|
105
|
+
settings.composite = { tours: [] };
|
|
106
|
+
settings.changed.emit(void 0);
|
|
107
|
+
expect(userManager.tourManager.tours.size).toBe(0);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
describe(notebookPlugin.id, () => {
|
|
112
|
+
describe('activation', () => {
|
|
113
|
+
it('should activate', async () => {
|
|
114
|
+
const app = mockApp();
|
|
115
|
+
const manager = corePlugin.activate(app);
|
|
116
|
+
const nbTracker = mockNbTracker();
|
|
117
|
+
const notebookTourManager = notebookPlugin.activate(app, nbTracker, manager);
|
|
118
|
+
const languages = new EditorLanguageRegistry();
|
|
119
|
+
const factoryService = new CodeMirrorEditorFactory({
|
|
120
|
+
languages
|
|
121
|
+
});
|
|
122
|
+
const mimeTypeService = new CodeMirrorMimeTypeService(languages);
|
|
123
|
+
const editorFactory = factoryService.newInlineEditor;
|
|
124
|
+
const notebook = new Notebook({
|
|
125
|
+
rendermime: null,
|
|
126
|
+
mimeTypeService,
|
|
127
|
+
contentFactory: new NotebookPanel.ContentFactory({ editorFactory })
|
|
128
|
+
});
|
|
129
|
+
const model = new NotebookModel();
|
|
130
|
+
notebook.model = model;
|
|
131
|
+
notebookTourManager.addNotebook(notebook);
|
|
132
|
+
expect(notebookTourManager.tourManager.tours.size).toBe(0);
|
|
133
|
+
model.setMetadata(NS, {
|
|
134
|
+
tours: [aTour()]
|
|
135
|
+
});
|
|
136
|
+
expect(notebookTourManager.tourManager.tours.size).toBe(1);
|
|
137
|
+
model.deleteMetadata(NS);
|
|
138
|
+
expect(notebookTourManager.tourManager.tours.size).toBe(0);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe(defaultsPlugin.id, () => {
|
|
143
|
+
describe('activation', () => {
|
|
144
|
+
it('should activate', () => {
|
|
145
|
+
const app = mockApp();
|
|
146
|
+
const manager = corePlugin.activate(app);
|
|
147
|
+
defaultsPlugin.activate(app, manager);
|
|
148
|
+
expect(manager.tours.size).toEqual(DEFAULT_TOURS_SIZE);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
package/lib/components.js
CHANGED
|
@@ -37,7 +37,7 @@ class Tour extends React.Component {
|
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
render() {
|
|
40
|
-
return this.props.tours && this.props.tours[this.state.index] ? (React.createElement(ReactJoyride,
|
|
40
|
+
return this.props.tours && this.props.tours[this.state.index] ? (React.createElement(ReactJoyride, { key: this.props.tours[this.state.index].id, ...this.props.tours[this.state.index].options, callback: this._handleJoyrideCallback, run: this.state.run, steps: this.props.tours[this.state.index].steps })) : null;
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
/**
|