Skip to content

Commit 6f7b031

Browse files
Added clap-button-message widget example. (#244)
* Initial clap-button-message example. * Removed notebooks. * Added README. * Removed unneeded RELEASE file. * Updated README and id's. * Updated README. * Updated README. * Updated root/proj README. * Updated title. * Updated root project metadata files. * Updated comments to highlight lab/nb7 plugins. * Formatting. * Fixed hello world config file diff in CI. * Improve example * Skip browser_check for clap-button example --------- Co-authored-by: Frédéric Collonval <[email protected]> Co-authored-by: Frédéric Collonval <[email protected]>
1 parent f3b2b0b commit 6f7b031

29 files changed

+950
-23
lines changed

.github/workflows/main.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
fail-fast: false
1515
matrix:
1616
example:
17+
- clap-button-message
1718
- codemirror-extension
1819
- command-palette
1920
- commands
@@ -102,7 +103,7 @@ jobs:
102103
python -m pip install --upgrade pip "jupyterlab>=4.0.0"
103104
# This is challenging to test in collaboration;
104105
# got trouble with the file ID service and the uncontrolled auto-save
105-
# - if: steps.filter.outputs.extension == 'true' && matrix.example == 'documents'
106+
# - if: steps.filter.outputs.extension == 'true' && matrix.example == 'clap-button-message'
106107
# run: |
107108
# python -m pip install jupyter-collaboration
108109
- name: Build the extension
@@ -121,6 +122,11 @@ jobs:
121122
run: |
122123
jupyter labextension list 2>&1 | tee labextension.list
123124
cat labextension.list | grep -ie "@jupyterlab-examples/*.*OK"
125+
# clap-button-message example will have one plugin failing as it is requiring a
126+
# Jupyter Notebook specific token. This is expected. Hence we need to skip this
127+
# test for that example
128+
- if: steps.filter.outputs.extension == 'true' && matrix.example != 'clap-button-message'
129+
run: |
124130
python -m jupyterlab.browser_check
125131
126132
- name: Install galata

README.md

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
1. [Context Menu](#context-menu)
1414
1. [Custom Log Console](#custom-log-console)
1515
1. [Datagrid](#datagrid)
16-
1. [Dual Compatibility Shout Button](#dual-compatibility-shout-button)
16+
1. [Dual Compatibility](#dual-compatibility)
17+
1. [Top Area Text Widget](#top-area-text-widget)
18+
1. [Shout Button](#shout-button)
19+
1. [Clap Button](#clap-button-message)
1720
1. [Collaborative Document](#collaborative-document)
1821
1. _[Hello World](#hello-world)_
1922
1. [Kernel Messaging](#kernel-messaging)
@@ -30,7 +33,6 @@
3033
1. [Signals](#signals)
3134
1. [State](#state)
3235
1. [Toolbar Item](#toolbar-item)
33-
1. [Top Area Text Widget](#top-area-text-widget)
3436
1. [Widgets](#widgets)
3537
1. [Prerequisites](#prerequisites)
3638
1. [Develop and Use the Examples](#develop-and-use-the-examples)
@@ -102,7 +104,10 @@ Start with the [Hello World](hello-world) and then jump to the topic you are int
102104
- [Context Menu](context-menu)
103105
- [Custom Log Console](custom-log-console)
104106
- [Datagrid](datagrid)
105-
- [Dual Compatibility Shout Button](shout-button-message)
107+
- Dual Compatibility
108+
- [Top Area Text Widget](toparea-text-widget)
109+
- [Shout Button](shout-button-message)
110+
- [Clap Button](clap-button-message)
106111
- [Collaborative Document](documents)
107112
- [Hello World](hello-world)
108113
- [Kernel Messaging](kernel-messaging)
@@ -119,7 +124,6 @@ Start with the [Hello World](hello-world) and then jump to the topic you are int
119124
- [Signals](signals)
120125
- [State](state)
121126
- [Toolbar item](toolbar-button)
122-
- [Top Area Text Widget](toparea-text-widget)
123127
- [Widgets](widgets)
124128

125129
You can expect from each example:
@@ -181,7 +185,26 @@ Display a Datagrid as a Lumino Widget.
181185

182186
[![Datagrid](datagrid/preview.png)](datagrid)
183187

184-
### [Dual Compatibility Shout Button](shout-button-message)
188+
### Dual Compatibility
189+
190+
The dual compatibility examples demonstrates how to design an extension that can be
191+
integrated similtaneously in JupyterLab and Jupyter Notebook v7+.
192+
193+
They are listed from the simplest to the most advanced case:
194+
195+
- [Top Area Text Widget](#top-area-text-widget): Example working right away in both frontends.
196+
- [Shout Button](#shout-button): Example with a part only available in JupyterLab
197+
- [Clap Button](#clap-button-message): Example with elements added differently depending on
198+
the frontends used.
199+
200+
#### [Top Area Text Widget](toparea-text-widget)
201+
202+
A very simple example that adds a basic text widget to the top area. See [related video.](https://www.youtube.com/watch?v=mqotG1MkHa4).
203+
This example is part of the [Extension Dual Compatibility Guide](https://jupyterlab.readthedocs.io/en/latest/extension_dual_compatibility.html).
204+
205+
[![Top Area Text Widget](toparea-text-widget/preview.jpg)](toparea-text-widget)
206+
207+
#### [Shout Button](shout-button-message)
185208

186209
This example shows dual compatibility: Make an extension that is compatible
187210
with both JupyterLab and Jupyter Notebook by using optional features. Adds
@@ -191,6 +214,17 @@ Read more about this example on that page.
191214

192215
[![Dual compatibility shout button](shout-button-message/preview.jpg)](shout-button-message)
193216

217+
#### [Clap Button](clap-button-message)
218+
219+
This example shows an alternate method for achieving dual compatibility: Make an
220+
extension that is compatible with both JupyterLab and Jupyter Notebook by exporting
221+
multiple plugins and using "required" features to select different behaviors. Adds a clap button to
222+
the top area (in JupyterLab) or the right sidebar (Jupyter Notebook). This example is part
223+
of the [Extension Dual Compatibility Guide](https://jupyterlab.readthedocs.io/en/latest/extension_dual_compatibility.html).
224+
Read more about this example on that page.
225+
226+
[![Dual Compatibility Clap Button](clap-button-message/preview.jpg)](clap-button-message)
227+
194228
### [Collaborative Document](documents)
195229

196230
Create new documents and make them collaborative.
@@ -287,13 +321,6 @@ Add a new button to the notebook toolbar.
287321

288322
[![Toolbar button](toolbar-button/preview.gif)](toolbar-button)
289323

290-
### [Top Area Text Widget](toparea-text-widget)
291-
292-
A very simple example that adds a basic text widget to the top area. See [related video.](https://www.youtube.com/watch?v=mqotG1MkHa4).
293-
This example is part of the [Extension Dual Compatibility Guide](https://jupyterlab.readthedocs.io/en/latest/extension_dual_compatibility.html).
294-
295-
[![Top Area Text Widget](toparea-text-widget/preview.jpg)](toparea-text-widget)
296-
297324
### [Widgets](widgets)
298325

299326
Add a new Widget element to the main window.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
2+
_commit: v4.2.4
3+
_src_path: https://github.com/jupyterlab/extension-template
4+
author_email: ''
5+
author_name: Project Jupyter Contributors
6+
data_format: string
7+
file_extension: ''
8+
has_binder: false
9+
has_settings: false
10+
kind: frontend
11+
labextension_name: '@jupyterlab-examples/clap-button'
12+
mimetype: ''
13+
mimetype_name: ''
14+
project_short_description: Adds a clap button to the status bar (JupyterLab) or top
15+
area (Jupyter Notebook 7)
16+
python_name: jupyterlab_examples_shout_button
17+
repository: https://github.com/jupyterlab/extension-examples
18+
test: true
19+
viewer_name: ''
20+

clap-button-message/.gitignore

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
*.bundle.*
2+
lib/
3+
node_modules/
4+
*.log
5+
.eslintcache
6+
.stylelintcache
7+
*.egg-info/
8+
.ipynb_checkpoints
9+
*.tsbuildinfo
10+
jupyterlab_examples_shout_button/labextension
11+
# Version file is handled by hatchling
12+
jupyterlab_examples_shout_button/_version.py
13+
14+
# Integration tests
15+
ui-tests/test-results/
16+
ui-tests/playwright-report/
17+
18+
# Created by https://www.gitignore.io/api/python
19+
# Edit at https://www.gitignore.io/?templates=python
20+
21+
### Python ###
22+
# Byte-compiled / optimized / DLL files
23+
__pycache__/
24+
*.py[cod]
25+
*$py.class
26+
27+
# C extensions
28+
*.so
29+
30+
# Distribution / packaging
31+
.Python
32+
build/
33+
develop-eggs/
34+
dist/
35+
downloads/
36+
eggs/
37+
.eggs/
38+
lib/
39+
lib64/
40+
parts/
41+
sdist/
42+
var/
43+
wheels/
44+
pip-wheel-metadata/
45+
share/python-wheels/
46+
.installed.cfg
47+
*.egg
48+
MANIFEST
49+
50+
# PyInstaller
51+
# Usually these files are written by a python script from a template
52+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
53+
*.manifest
54+
*.spec
55+
56+
# Installer logs
57+
pip-log.txt
58+
pip-delete-this-directory.txt
59+
60+
# Unit test / coverage reports
61+
htmlcov/
62+
.tox/
63+
.nox/
64+
.coverage
65+
.coverage.*
66+
.cache
67+
nosetests.xml
68+
coverage/
69+
coverage.xml
70+
*.cover
71+
.hypothesis/
72+
.pytest_cache/
73+
74+
# Translations
75+
*.mo
76+
*.pot
77+
78+
# Scrapy stuff:
79+
.scrapy
80+
81+
# Sphinx documentation
82+
docs/_build/
83+
84+
# PyBuilder
85+
target/
86+
87+
# pyenv
88+
.python-version
89+
90+
# celery beat schedule file
91+
celerybeat-schedule
92+
93+
# SageMath parsed files
94+
*.sage.py
95+
96+
# Spyder project settings
97+
.spyderproject
98+
.spyproject
99+
100+
# Rope project settings
101+
.ropeproject
102+
103+
# Mr Developer
104+
.mr.developer.cfg
105+
.project
106+
.pydevproject
107+
108+
# mkdocs documentation
109+
/site
110+
111+
# mypy
112+
.mypy_cache/
113+
.dmypy.json
114+
dmypy.json
115+
116+
# Pyre type checker
117+
.pyre/
118+
119+
# End of https://www.gitignore.io/api/python
120+
121+
# OSX files
122+
.DS_Store
123+
124+
# Yarn cache
125+
.yarn/

clap-button-message/.prettierignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
**/node_modules
3+
**/lib
4+
**/package.json
5+
!/package.json
6+
jupyterlab_examples_shout_button

clap-button-message/.yarnrc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nodeLinker: node-modules

clap-button-message/README.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Clap Button (cross compatible extension)
2+
3+
This example defines an extension that adds a button that if clicked will
4+
display an alert to the user. In JupyterLab the button in added in the top
5+
area (next to the main menu) and in Jupyter Notebook v7+ the button is added to the rights sidebar.
6+
7+
![preview in Notebook v7+](./preview.png)
8+
9+
We strongly advice to look to those examples before diving into this one:
10+
11+
- [widgets](../widgets): The basic DOM Jupyter component.
12+
- [Simple compatibility example](../toparea-text-widget): Extension working without modification in both Notebook and JupyterLab.
13+
- [Conditional compatibility example](../shout-button-message): Extension that has
14+
a part conditionned on feature specific to JupyterLab.
15+
16+
## Jupyter Notebook / JupyterLab compatibility
17+
18+
As Jupyter Notebook 7+ is built with components from JupyterLab, and since
19+
both use the same building blocks, that means your extension can work
20+
on both (or any other frontend built with JupyterLab components) with
21+
little or no modification depending on its design.
22+
23+
In this example, you will define two different plugins that require
24+
different tokens to have a custom behavior depending on the frontend used.
25+
26+
## Require tokens
27+
28+
For JupyterLab you can require the specific
29+
token `ILabShell`.
30+
31+
```ts
32+
// src/index.ts#L48-L53
33+
34+
const pluginJupyterLab: JupyterFrontEndPlugin<void> = {
35+
id: '@jupyterlab-examples/clap-button:pluginLab',
36+
description: 'Adds a clap button to the top area JupyterLab',
37+
autoStart: true,
38+
requires: [ILabShell],
39+
activate: (app: JupyterFrontEnd, labShell: ILabShell) => {
40+
```
41+
42+
And for Jupyter Notebook, you can require the specific token `INotebookShell`.
43+
44+
```ts
45+
// src/index.ts#L68-L73
46+
47+
const pluginJupyterNotebook: JupyterFrontEndPlugin<void> = {
48+
id: '@jupyterlab-examples/clap-button:pluginNotebook',
49+
description: 'Adds a clap button to the right sidebar of Jupyter Notebook 7',
50+
autoStart: true,
51+
requires: [INotebookShell],
52+
activate: (app: JupyterFrontEnd, notebookShell: INotebookShell) => {
53+
```
54+
55+
In the two plugins, the `activate` method will receive as
56+
second argument the shell token. It is fine to not used
57+
a required token as here the goal is to allow the application
58+
to figure out if the plugin should be activated or not.
59+
60+
## Export multiple plugins
61+
62+
If your extension is defining multiple plugin, you have to
63+
return as default export of your extension package an array
64+
of plugins. In this example:
65+
66+
```ts
67+
// src/index.ts#L88-L93
68+
69+
const plugins: JupyterFrontEndPlugin<void>[] = [
70+
pluginJupyterLab,
71+
pluginJupyterNotebook
72+
];
73+
74+
export default plugins;
75+
```
76+
77+
## Where to Go Next
78+
79+
You can have more information about making extension compatible with
80+
multiple applications in the
81+
[Extension Dual Compatibility Guide](https://jupyterlab.readthedocs.io/en/latest/extension_dual_compatibility.html).

clap-button-message/install.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"packageManager": "python",
3+
"packageName": "jupyterlab_examples_shout_button",
4+
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package jupyterlab_examples_shout_button"
5+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
try:
2+
from ._version import __version__
3+
except ImportError:
4+
# Fallback when using the package in dev mode without installing
5+
# in editable mode with pip. It is highly recommended to install
6+
# the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs
7+
import warnings
8+
warnings.warn("Importing 'jupyterlab_examples_shout_button' outside a proper installation.")
9+
__version__ = "dev"
10+
11+
12+
def _jupyter_labextension_paths():
13+
return [{
14+
"src": "labextension",
15+
"dest": "@jupyterlab-examples/clap-button"
16+
}]

0 commit comments

Comments
 (0)