Skip to content

Commit

Permalink
Added clap-button-message widget example. (#244)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
3 people authored Nov 27, 2023
1 parent f3b2b0b commit 6f7b031
Show file tree
Hide file tree
Showing 29 changed files with 950 additions and 23 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
fail-fast: false
matrix:
example:
- clap-button-message
- codemirror-extension
- command-palette
- commands
Expand Down Expand Up @@ -102,7 +103,7 @@ jobs:
python -m pip install --upgrade pip "jupyterlab>=4.0.0"
# This is challenging to test in collaboration;
# got trouble with the file ID service and the uncontrolled auto-save
# - if: steps.filter.outputs.extension == 'true' && matrix.example == 'documents'
# - if: steps.filter.outputs.extension == 'true' && matrix.example == 'clap-button-message'
# run: |
# python -m pip install jupyter-collaboration
- name: Build the extension
Expand All @@ -121,6 +122,11 @@ jobs:
run: |
jupyter labextension list 2>&1 | tee labextension.list
cat labextension.list | grep -ie "@jupyterlab-examples/*.*OK"
# clap-button-message example will have one plugin failing as it is requiring a
# Jupyter Notebook specific token. This is expected. Hence we need to skip this
# test for that example
- if: steps.filter.outputs.extension == 'true' && matrix.example != 'clap-button-message'
run: |
python -m jupyterlab.browser_check
- name: Install galata
Expand Down
51 changes: 39 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
1. [Context Menu](#context-menu)
1. [Custom Log Console](#custom-log-console)
1. [Datagrid](#datagrid)
1. [Dual Compatibility Shout Button](#dual-compatibility-shout-button)
1. [Dual Compatibility](#dual-compatibility)
1. [Top Area Text Widget](#top-area-text-widget)
1. [Shout Button](#shout-button)
1. [Clap Button](#clap-button-message)
1. [Collaborative Document](#collaborative-document)
1. _[Hello World](#hello-world)_
1. [Kernel Messaging](#kernel-messaging)
Expand All @@ -30,7 +33,6 @@
1. [Signals](#signals)
1. [State](#state)
1. [Toolbar Item](#toolbar-item)
1. [Top Area Text Widget](#top-area-text-widget)
1. [Widgets](#widgets)
1. [Prerequisites](#prerequisites)
1. [Develop and Use the Examples](#develop-and-use-the-examples)
Expand Down Expand Up @@ -102,7 +104,10 @@ Start with the [Hello World](hello-world) and then jump to the topic you are int
- [Context Menu](context-menu)
- [Custom Log Console](custom-log-console)
- [Datagrid](datagrid)
- [Dual Compatibility Shout Button](shout-button-message)
- Dual Compatibility
- [Top Area Text Widget](toparea-text-widget)
- [Shout Button](shout-button-message)
- [Clap Button](clap-button-message)
- [Collaborative Document](documents)
- [Hello World](hello-world)
- [Kernel Messaging](kernel-messaging)
Expand All @@ -119,7 +124,6 @@ Start with the [Hello World](hello-world) and then jump to the topic you are int
- [Signals](signals)
- [State](state)
- [Toolbar item](toolbar-button)
- [Top Area Text Widget](toparea-text-widget)
- [Widgets](widgets)

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

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

### [Dual Compatibility Shout Button](shout-button-message)
### Dual Compatibility

The dual compatibility examples demonstrates how to design an extension that can be
integrated similtaneously in JupyterLab and Jupyter Notebook v7+.

They are listed from the simplest to the most advanced case:

- [Top Area Text Widget](#top-area-text-widget): Example working right away in both frontends.
- [Shout Button](#shout-button): Example with a part only available in JupyterLab
- [Clap Button](#clap-button-message): Example with elements added differently depending on
the frontends used.

#### [Top Area Text Widget](toparea-text-widget)

A very simple example that adds a basic text widget to the top area. See [related video.](https://www.youtube.com/watch?v=mqotG1MkHa4).
This example is part of the [Extension Dual Compatibility Guide](https://jupyterlab.readthedocs.io/en/latest/extension_dual_compatibility.html).

[![Top Area Text Widget](toparea-text-widget/preview.jpg)](toparea-text-widget)

#### [Shout Button](shout-button-message)

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

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

#### [Clap Button](clap-button-message)

This example shows an alternate method for achieving dual compatibility: Make an
extension that is compatible with both JupyterLab and Jupyter Notebook by exporting
multiple plugins and using "required" features to select different behaviors. Adds a clap button to
the top area (in JupyterLab) or the right sidebar (Jupyter Notebook). This example is part
of the [Extension Dual Compatibility Guide](https://jupyterlab.readthedocs.io/en/latest/extension_dual_compatibility.html).
Read more about this example on that page.

[![Dual Compatibility Clap Button](clap-button-message/preview.jpg)](clap-button-message)

### [Collaborative Document](documents)

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

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

### [Top Area Text Widget](toparea-text-widget)

A very simple example that adds a basic text widget to the top area. See [related video.](https://www.youtube.com/watch?v=mqotG1MkHa4).
This example is part of the [Extension Dual Compatibility Guide](https://jupyterlab.readthedocs.io/en/latest/extension_dual_compatibility.html).

[![Top Area Text Widget](toparea-text-widget/preview.jpg)](toparea-text-widget)

### [Widgets](widgets)

Add a new Widget element to the main window.
Expand Down
20 changes: 20 additions & 0 deletions clap-button-message/.copier-answers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
_commit: v4.2.4
_src_path: https://github.com/jupyterlab/extension-template
author_email: ''
author_name: Project Jupyter Contributors
data_format: string
file_extension: ''
has_binder: false
has_settings: false
kind: frontend
labextension_name: '@jupyterlab-examples/clap-button'
mimetype: ''
mimetype_name: ''
project_short_description: Adds a clap button to the status bar (JupyterLab) or top
area (Jupyter Notebook 7)
python_name: jupyterlab_examples_shout_button
repository: https://github.com/jupyterlab/extension-examples
test: true
viewer_name: ''

125 changes: 125 additions & 0 deletions clap-button-message/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
*.bundle.*
lib/
node_modules/
*.log
.eslintcache
.stylelintcache
*.egg-info/
.ipynb_checkpoints
*.tsbuildinfo
jupyterlab_examples_shout_button/labextension
# Version file is handled by hatchling
jupyterlab_examples_shout_button/_version.py

# Integration tests
ui-tests/test-results/
ui-tests/playwright-report/

# Created by https://www.gitignore.io/api/python
# Edit at https://www.gitignore.io/?templates=python

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage/
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# Mr Developer
.mr.developer.cfg
.project
.pydevproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# End of https://www.gitignore.io/api/python

# OSX files
.DS_Store

# Yarn cache
.yarn/
6 changes: 6 additions & 0 deletions clap-button-message/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
**/node_modules
**/lib
**/package.json
!/package.json
jupyterlab_examples_shout_button
1 change: 1 addition & 0 deletions clap-button-message/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
81 changes: 81 additions & 0 deletions clap-button-message/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Clap Button (cross compatible extension)

This example defines an extension that adds a button that if clicked will
display an alert to the user. In JupyterLab the button in added in the top
area (next to the main menu) and in Jupyter Notebook v7+ the button is added to the rights sidebar.

![preview in Notebook v7+](./preview.png)

We strongly advice to look to those examples before diving into this one:

- [widgets](../widgets): The basic DOM Jupyter component.
- [Simple compatibility example](../toparea-text-widget): Extension working without modification in both Notebook and JupyterLab.
- [Conditional compatibility example](../shout-button-message): Extension that has
a part conditionned on feature specific to JupyterLab.

## Jupyter Notebook / JupyterLab compatibility

As Jupyter Notebook 7+ is built with components from JupyterLab, and since
both use the same building blocks, that means your extension can work
on both (or any other frontend built with JupyterLab components) with
little or no modification depending on its design.

In this example, you will define two different plugins that require
different tokens to have a custom behavior depending on the frontend used.

## Require tokens

For JupyterLab you can require the specific
token `ILabShell`.

```ts
// src/index.ts#L48-L53

const pluginJupyterLab: JupyterFrontEndPlugin<void> = {
id: '@jupyterlab-examples/clap-button:pluginLab',
description: 'Adds a clap button to the top area JupyterLab',
autoStart: true,
requires: [ILabShell],
activate: (app: JupyterFrontEnd, labShell: ILabShell) => {
```
And for Jupyter Notebook, you can require the specific token `INotebookShell`.
```ts
// src/index.ts#L68-L73

const pluginJupyterNotebook: JupyterFrontEndPlugin<void> = {
id: '@jupyterlab-examples/clap-button:pluginNotebook',
description: 'Adds a clap button to the right sidebar of Jupyter Notebook 7',
autoStart: true,
requires: [INotebookShell],
activate: (app: JupyterFrontEnd, notebookShell: INotebookShell) => {
```
In the two plugins, the `activate` method will receive as
second argument the shell token. It is fine to not used
a required token as here the goal is to allow the application
to figure out if the plugin should be activated or not.
## Export multiple plugins
If your extension is defining multiple plugin, you have to
return as default export of your extension package an array
of plugins. In this example:
```ts
// src/index.ts#L88-L93

const plugins: JupyterFrontEndPlugin<void>[] = [
pluginJupyterLab,
pluginJupyterNotebook
];

export default plugins;
```
## Where to Go Next
You can have more information about making extension compatible with
multiple applications in the
[Extension Dual Compatibility Guide](https://jupyterlab.readthedocs.io/en/latest/extension_dual_compatibility.html).
5 changes: 5 additions & 0 deletions clap-button-message/install.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"packageManager": "python",
"packageName": "jupyterlab_examples_shout_button",
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package jupyterlab_examples_shout_button"
}
16 changes: 16 additions & 0 deletions clap-button-message/jupyterlab_examples_shout_button/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
try:
from ._version import __version__
except ImportError:
# Fallback when using the package in dev mode without installing
# in editable mode with pip. It is highly recommended to install
# the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs
import warnings
warnings.warn("Importing 'jupyterlab_examples_shout_button' outside a proper installation.")
__version__ = "dev"


def _jupyter_labextension_paths():
return [{
"src": "labextension",
"dest": "@jupyterlab-examples/clap-button"
}]
Loading

0 comments on commit 6f7b031

Please sign in to comment.