Skip to content

Commit

Permalink
Update template
Browse files Browse the repository at this point in the history
  • Loading branch information
fcollonval committed Nov 13, 2023
1 parent 8abef3a commit cf46e13
Show file tree
Hide file tree
Showing 14 changed files with 384 additions and 94 deletions.
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
2 changes: 0 additions & 2 deletions shout-button-message/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
enableImmutableInstalls: false

nodeLinker: node-modules
106 changes: 100 additions & 6 deletions shout-button-message/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,101 @@
# Dual Compatibility Shout Button (shout_button_message)
# Shout button (cross compatible extension)

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

## 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).
4 changes: 2 additions & 2 deletions shout-button-message/install.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"packageManager": "python",
"packageName": "shout_button_message",
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package shout_button_message"
"packageName": "jupyterlab_examples_shout_button",
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package jupyterlab_examples_shout_button"
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
# 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 'shout_button_message' outside a proper installation.")
warnings.warn("Importing 'jupyterlab_examples_shout_button' outside a proper installation.")
__version__ = "dev"


def _jupyter_labextension_paths():
return [{
"src": "labextension",
"dest": "shout_button_message"
"dest": "@jupyterlab-examples/shout-button"
}]
36 changes: 22 additions & 14 deletions shout-button-message/package.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
{
"name": "shout_button_message",
"name": "@jupyterlab-examples/shout-button",
"version": "0.1.0",
"description": "An extension that adds a button and message to the right toolbar, with optional status bar widget in JupyterLab.",
"keywords": [
"jupyter",
"jupyterlab",
"jupyterlab-extension"
],
"homepage": "",
"homepage": "https://github.com/jupyterlab/extension-examples",
"bugs": {
"url": "/issues"
"url": "https://github.com/jupyterlab/extension-examples/issues"
},
"license": "BSD-3-Clause",
"author": {
"name": "My Name",
"email": "[email protected]"
},
"author": "Project Jupyter Contributors",
"files": [
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
"style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}"
Expand All @@ -25,7 +22,7 @@
"style": "style/index.css",
"repository": {
"type": "git",
"url": ".git"
"url": "https://github.com/jupyterlab/extension-examples.git"
},
"scripts": {
"build": "jlpm build:lib && jlpm build:labextension:dev",
Expand All @@ -37,7 +34,7 @@
"clean": "jlpm clean:lib",
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
"clean:lintcache": "rimraf .eslintcache .stylelintcache",
"clean:labextension": "rimraf shout_button_message/labextension shout_button_message/_version.py",
"clean:labextension": "rimraf jupyterlab_examples_shout_button/labextension jupyterlab_examples_shout_button/_version.py",
"clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache",
"eslint": "jlpm eslint:check --fix",
"eslint:check": "eslint . --cache --ext .ts,.tsx",
Expand All @@ -55,27 +52,33 @@
},
"dependencies": {
"@jupyterlab/application": "^4.0.0",
"@jupyterlab/statusbar": "^4.0.2",
"@jupyterlab/statusbar": "^4.0.0",
"@lumino/signaling": "^2.0.0",
"@lumino/widgets": "^2.0.0"
},
"devDependencies": {
"@jupyterlab/builder": "^4.0.0",
"@jupyterlab/testutils": "^4.0.0",
"@types/jest": "^29.2.0",
"@types/json-schema": "^7.0.11",
"@types/react": "^18.0.26",
"@typescript-eslint/eslint-plugin": "^5.55.0",
"@typescript-eslint/parser": "^5.55.0",
"@types/react-addons-linked-state-mixin": "^0.14.22",
"@typescript-eslint/eslint-plugin": "^6.1.0",
"@typescript-eslint/parser": "^6.1.0",
"css-loader": "^6.7.1",
"eslint": "^8.36.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.2.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.0.0",
"rimraf": "^4.4.1",
"rimraf": "^5.0.1",
"source-map-loader": "^1.0.2",
"style-loader": "^3.3.1",
"stylelint": "^15.10.1",
"stylelint-config-recommended": "^13.0.0",
"stylelint-config-standard": "^34.0.0",
"stylelint-csstree-validator": "^3.0.0",
"stylelint-prettier": "^4.0.0",
"typescript": "~5.0.2",
"yjs": "^13.5.0"
Expand All @@ -90,7 +93,7 @@
},
"jupyterlab": {
"extension": true,
"outputDir": "shout_button_message/labextension"
"outputDir": "jupyterlab_examples_shout_button/labextension"
},
"eslintIgnore": [
"node_modules",
Expand Down Expand Up @@ -175,8 +178,13 @@
"stylelint-config-standard",
"stylelint-prettier/recommended"
],
"plugins": [
"stylelint-csstree-validator"
],
"rules": {
"csstree/validator": true,
"property-no-vendor-prefix": null,
"selector-class-pattern": "^([a-z][A-z\\d]*)(-[A-z\\d]+)*$",
"selector-no-vendor-prefix": null,
"value-no-vendor-prefix": null
}
Expand Down
Loading

0 comments on commit cf46e13

Please sign in to comment.