Skip to content

Commit

Permalink
Merge remote-tracking branch 'nicegui/main' into feature/client_data
Browse files Browse the repository at this point in the history
  • Loading branch information
Alyxion committed May 3, 2024
2 parents d5a9009 + 4a225aa commit ef5ab9d
Show file tree
Hide file tree
Showing 90 changed files with 1,057 additions and 450 deletions.
33 changes: 15 additions & 18 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,6 @@ default_language_version:
default_install_hook_types: [pre-commit, pre-push]
default_stages: [commit]

exclusions: &exclusions
exclude: |
(?x)^(
nicegui/elements/lib/.*|
nicegui/static/es-module-shims\.js|
nicegui/static/fonts/.*|
nicegui/static/fonts\.css|
nicegui/static/lang/.*|
nicegui/static/quasar\..*|
nicegui/static/socket\..*|
nicegui/static/tailwindcss\..*|
nicegui/static/vue\..*|
website/static/fuse\.js\@.*|
examples/fullcalendar/lib/.*
)$
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.5
Expand All @@ -29,7 +13,20 @@ repos:
rev: v4.6.0
hooks:
- id: trailing-whitespace
<<: *exclusions
exclude: &exclusions |
(?x)^(
nicegui/elements/lib/.*|
nicegui/static/es-module-shims\.js|
nicegui/static/fonts/.*|
nicegui/static/fonts\.css|
nicegui/static/lang/.*|
nicegui/static/quasar\..*|
nicegui/static/socket\..*|
nicegui/static/tailwindcss\..*|
nicegui/static/vue\..*|
website/static/fuse\.js\@.*|
examples/fullcalendar/lib/.*
)$
- id: end-of-file-fixer
<<: *exclusions
exclude: *exclusions
- id: double-quote-string-fixer
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"--disable=C0301", // Line too long (exceeds character limit)
"--disable=C0302", // Too many lines in module
"--disable=R0801", // Similar lines in files
"--disable=R0901", // Too many ancestors
"--disable=R0902", // Too many instance attributes
"--disable=R0903", // Too few public methods
"--disable=R0904", // Too many public methods
Expand Down
6 changes: 3 additions & 3 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ authors:
given-names: Rodja
orcid: https://orcid.org/0009-0009-4735-6227
title: 'NiceGUI: Web-based user interfaces with Python. The nice way.'
version: v1.4.21
date-released: '2024-04-12'
version: v1.4.23
date-released: '2024-04-25'
url: https://github.com/zauberzeug/nicegui
doi: 10.5281/zenodo.10965450
doi: 10.5281/zenodo.11068110
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ We're always looking for bug fixes, performance improvements, and new features.

The simplest way to setup a fully functioning development environment is to start our Dev Container in VS Code:

1. Ensure you have VS Code, Docker and the Remote-Containers extension installed.
1. Ensure you have VS Code, Docker and the Dev Containers extension installed.
2. Open the project root directory in VS Code.
3. Press `F1`, type `Remote-Containers: Open Folder in Container`, and hit enter (or use the bottom-left corner icon in VS Code to reopen in container).
3. Press `F1`, type `Dev Containers: Open Folder in Container`, and hit enter (or use the bottom-left corner icon in VS Code to reopen in container).
4. Wait until image has been build.
5. Happy coding.

Expand Down
6 changes: 3 additions & 3 deletions examples/chat_app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import List, Tuple
from uuid import uuid4

from nicegui import Client, ui
from nicegui import ui

messages: List[Tuple[str, str, str, str]] = []

Expand All @@ -16,7 +16,7 @@ def chat_messages(own_id: str) -> None:


@ui.page('/')
async def main(client: Client):
async def main():
def send() -> None:
stamp = datetime.utcnow().strftime('%X')
messages.append((user_id, avatar, text.value, stamp))
Expand All @@ -36,7 +36,7 @@ def send() -> None:
ui.markdown('simple chat app built with [NiceGUI](https://nicegui.io)') \
.classes('text-xs self-end mr-8 m-[-1em] text-primary')

await client.connected() # chat_messages(...) uses run_javascript which is only possible after connecting
await ui.context.client.connected() # chat_messages(...) uses run_javascript which is only possible after connecting
with ui.column().classes('w-full max-w-2xl mx-auto items-stretch'):
chat_messages(user_id)

Expand Down
6 changes: 3 additions & 3 deletions examples/descope_auth/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from descope import AuthException, DescopeClient

from nicegui import Client, app, helpers, ui
from nicegui import app, helpers, ui

DESCOPE_ID = os.environ.get('DESCOPE_PROJECT_ID', '')

Expand Down Expand Up @@ -52,7 +52,7 @@ class page(ui.page):
LOGIN_PATH = '/login'

def __call__(self, func: Callable[..., Any]) -> Callable[..., Any]:
async def content(client: Client):
async def content():
ui.add_head_html('<script src="https://unpkg.com/@descope/web-component@latest/dist/index.js"></script>')
ui.add_head_html('<script src="https://unpkg.com/@descope/web-js-sdk@latest/dist/index.umd.js"></script>')
ui.add_body_html(f'''
Expand All @@ -61,7 +61,7 @@ async def content(client: Client):
const sessionToken = sdk.getSessionToken()
</script>
''')
await client.connected()
await ui.context.client.connected()
if await self._is_logged_in():
if self.path == self.LOGIN_PATH:
self._refresh()
Expand Down
6 changes: 3 additions & 3 deletions examples/download_text_as_file/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

from fastapi.responses import StreamingResponse

from nicegui import Client, app, ui
from nicegui import app, ui


@ui.page('/')
async def index(client: Client):
async def index():
download_path = f'/download/{uuid.uuid4()}.txt'

@app.get(download_path)
Expand All @@ -21,7 +21,7 @@ def download():
ui.button('Download', on_click=lambda: ui.download(download_path))

# cleanup the download route after the client disconnected
await client.disconnected()
await ui.context.client.disconnected()
app.routes[:] = [route for route in app.routes if route.path != download_path]

ui.run()
13 changes: 8 additions & 5 deletions examples/infinite_scroll/main.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
#!/usr/bin/env python3
import time

from nicegui import Client, ui
from nicegui import ui


@ui.page('/')
async def page(client: Client):
async def page():
async def check():
if await ui.run_javascript('window.pageYOffset >= document.body.offsetHeight - 2 * window.innerHeight'):
ui.image(f'https://picsum.photos/640/360?{time.time()}')
await client.connected()
try:
if await ui.run_javascript('window.pageYOffset >= document.body.offsetHeight - 2 * window.innerHeight'):
ui.image(f'https://picsum.photos/640/360?{time.time()}')
except TimeoutError:
pass # the client might have disconnected
await ui.context.client.connected()
ui.timer(0.1, check)


Expand Down
24 changes: 24 additions & 0 deletions examples/modularization/api_router_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import theme
from message import message

from nicegui import APIRouter, ui

# NOTE: the APIRouter does not yet work with NiceGUI On Air (see https://github.com/zauberzeug/nicegui/discussions/2792)
router = APIRouter(prefix='/c')


@router.page('/')
def example_page():
with theme.frame('- Page C -'):
message('Page C')
ui.label('This page and its subpages are created using an APIRouter.')
ui.link('Item 1', '/c/items/1').classes('text-xl text-grey-8')
ui.link('Item 2', '/c/items/2').classes('text-xl text-grey-8')
ui.link('Item 3', '/c/items/3').classes('text-xl text-grey-8')


@router.page('/items/{item_id}', dark=True)
def item(item_id: str):
with theme.frame(f'- Page C{item_id} -'):
message(f'Item #{item_id}')
ui.link('go back', router.prefix).classes('text-xl text-grey-8')
18 changes: 18 additions & 0 deletions examples/modularization/class_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import theme
from message import message

from nicegui import ui


class ClassExample:

def __init__(self) -> None:
"""The page is created as soon as the class is instantiated.
This can obviously also be done in a method, if you want to decouple the instantiation of the object from the page creation.
"""
@ui.page('/b')
def page_b():
with theme.frame('- Page B -'):
message('Page B')
ui.label('This page is defined in a class.')
21 changes: 0 additions & 21 deletions examples/modularization/example_c.py

This file was deleted.

17 changes: 0 additions & 17 deletions examples/modularization/example_pages.py

This file was deleted.

12 changes: 12 additions & 0 deletions examples/modularization/function_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import theme
from message import message

from nicegui import ui


def create() -> None:
@ui.page('/a')
def page_a():
with theme.frame('- Page A -'):
message('Page A')
ui.label('This page is defined in a function.')
3 changes: 3 additions & 0 deletions examples/modularization/home_page.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from message import message

from nicegui import ui


def content() -> None:
message('This is the home page.').classes('font-bold')
ui.label('Use the menu on the top right to navigate.')
18 changes: 11 additions & 7 deletions examples/modularization/main.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
#!/usr/bin/env python3
import example_c
import example_pages
import api_router_example
import class_example
import function_example
import home_page
import theme

from nicegui import app, ui


# here we use our custom page decorator directly and just put the content creation into a separate function
# Example 1: use a custom page decorator directly and putting the content creation into a separate function
@ui.page('/')
def index_page() -> None:
with theme.frame('Homepage'):
home_page.content()


# this call shows that you can also move the whole page creation into a separate file
example_pages.create()
# Example 2: use a function to move the whole page creation into a separate file
function_example.create()

# we can also use the APIRouter as described in https://nicegui.io/documentation/page#modularize_with_apirouter
app.include_router(example_c.router)
# Example 3: use a class to move the whole page creation into a separate file
class_example.ClassExample()

# Example 4: use APIRouter as described in https://nicegui.io/documentation/page#modularize_with_apirouter
app.include_router(api_router_example.router)

ui.run(title='Modularization Example')
8 changes: 5 additions & 3 deletions examples/modularization/theme.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@


@contextmanager
def frame(navtitle: str):
def frame(navigation_title: str):
"""Custom page frame to share the same styling and behavior across all pages"""
ui.colors(primary='#6E93D6', secondary='#53B689', accent='#111B1E', positive='#53B689')
with ui.header().classes('justify-between text-white'):
with ui.header():
ui.label('Modularization Example').classes('font-bold')
ui.label(navtitle)
ui.space()
ui.label(navigation_title)
ui.space()
with ui.row():
menu()
with ui.column().classes('absolute-center items-center'):
Expand Down
37 changes: 37 additions & 0 deletions examples/zeromq/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Zeromq Example

This example is a basic Zeromq implementation with NiceGUI.
It shows how to stream data from a ZeroMQ socket to a NiceGUI plot.

In order to do this, the zmq Python library is used to create a publisher and a subscriber.
The main interesting aspect is that the zmq.async library is used to create a subscriber that can be used in an asyncio loop, which is necessary to run the NiceGUI server.

## Running the example

There are two components to this example: the publisher and the NiceGUI server.

In addition to the normal NiceGUI dependencies, the zmq library must be installed (see requirements.txt).

### Running the publisher

The publisher is a simple Python script that sends random data to a ZeroMQ socket.
To run it, simply execute the following command:

```bash
python zmq-server.py
```

### Running the NiceGUI server

The NiceGUI server is a Python script that creates a plot and updates it with data from the ZeroMQ socket.
To run it, execute the following command:

```bash
python main.py
```

### Results

Once both the publisher and GUI server are running, you will see an updating plot on the UI.

![plot](images/plot.png)
Binary file added examples/zeromq/images/plot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit ef5ab9d

Please sign in to comment.