Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added shout-button-message widget example. #243

Merged
merged 19 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ jobs:
- notifications
- react-widget
- settings
- shout-button-message
- signals
- state
- toolbar-button
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
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. [Collaborative Document](#collaborative-document)
1. _[Hello World](#hello-world)_
1. [Kernel Messaging](#kernel-messaging)
Expand Down Expand Up @@ -101,6 +102,7 @@ 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)
- [Collaborative Document](documents)
- [Hello World](hello-world)
- [Kernel Messaging](kernel-messaging)
Expand Down Expand Up @@ -179,6 +181,16 @@ Display a Datagrid as a Lumino Widget.

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

### [Dual Compatibility 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
a shout button to the right sidebar, and if running in JupyterLab, also adds
a status bar widget. 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 shout button](shout-button-message/preview.jpg)](shout-button-message)

### [Collaborative Document](documents)

Create new documents and make them collaborative.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"react-widget",
"server-extension",
"settings",
"shout-button-message",
"signals",
"state",
"toolbar-button",
Expand Down
20 changes: 20 additions & 0 deletions shout-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/shout-button'
mimetype: ''
mimetype_name: ''
project_short_description: An extension that adds a button and message to the right
toolbar, with optional status bar widget in JupyterLab.
python_name: jupyterlab_examples_shout_button
repository: https://github.com/jupyterlab/extension-examples
test: true
viewer_name: ''

125 changes: 125 additions & 0 deletions shout-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 shout-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 shout-button-message/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
106 changes: 106 additions & 0 deletions shout-button-message/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Shout button (cross compatible extension)

This example defines an extension that adds a button in the right sidebar that
if clicked will display an alert to the user and in JupyterLab will update
a widget in the status bar.

![preview](./preview.jpg)

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

- [signals](../signals/): Communication between JavaScript objects.
- [widgets](../widgets): The basic DOM Jupyter component

## 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.

This example has a part specific to JupyterLab. This translate by having
optional dependency for your extension plugin.

```ts
// src/index.ts#L120-L120

optional: [IStatusBar],
```

If your dependency is optional, the object pass to the `activate` method
will be `null` if no other plugin provides it.

```ts
// src/index.ts#L124-L124

activate: (app: JupyterFrontEnd, statusBar: IStatusBar | null) => {
```

## Add the button in the sidebar

You can add a widget to the right sidebar through the application shell:

```ts
// src/index.ts#L128-L131

const shoutWidget: ShoutWidget = new ShoutWidget();
shoutWidget.id = 'JupyterShoutWidget'; // Widgets need an id

app.shell.add(shoutWidget, 'right');
```

The `ShoutWidget` is a widget that contains a button that when clicked
emit a signal `messageShouted` that any callback can listen to to react
to it and display an alert to the user.

```ts
// src/index.ts#L99-L103

shout() {
this._lastShoutTime = new Date();
this._messageShouted.emit(this._lastShoutTime);
window.alert('Shouting at ' + this._lastShoutTime);
}
```

## Connect the button and the status bar

The status bar does not exist in all Jupyter applications (e.g. in
Jupyter Notebook). So a good practice is to make that dependency
optional and test for it to be non-null to carry related action:

```ts
// src/index.ts#L135-L135

if (statusBar) {
```

In this specific case, the action is to create a widget to add to the
status bar. You can achieve that by calling the `registerStatusItem`
method from the status bar object.

```ts
// src/index.ts#L136-L138

const statusBarWidget = new ShoutStatusBarSummary();

statusBar.registerStatusItem('shoutStatusBarSummary', {
```

If you want to react to a click on the button, you can `connect` to the
widget `messageShouted` signal. In which for example, you update the
text displayed in the status bar.

```ts
// src/index.ts#L142-L144

// Connect to the messageShouted to be notified when a new message
// is published and react to it by updating the status bar widget.
shoutWidget.messageShouted.connect((widget: ShoutWidget, time: Date) => {
```

## 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 shout-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 shout-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/shout-button"
}]
Loading
Loading