Skip to content

Commit

Permalink
Renamed the SinglePageRouter to SinglePageRouterConfig to emphasize i…
Browse files Browse the repository at this point in the history
…t is a singleton, static object created and configured once.
  • Loading branch information
Alyxion committed May 11, 2024
1 parent a112465 commit 3e5f2c2
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 24 deletions.
9 changes: 5 additions & 4 deletions examples/outlet/main.py → examples/outlet/cloud_ui/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Advanced demo showing how to use the ui.outlet and outlet.view decorators to create a nested multi-page app with a
# static header, footer and menu which is shared across all pages and hidden when the user navigates to the root page.

import os
from typing import Dict

Expand Down Expand Up @@ -54,7 +57,7 @@ def main_router(url_path: str):
with ui.link('', '/').style('text-decoration: none; color: inherit;') as lnk:
ui.html('<span style="color:white">Nice</span>'
'<span style="color:black">CLOUD</span>').classes('text-h3')
menu_visible = '/services/' in url_path # the service will make the menu visible anyway - suppresses animation
menu_visible = '/services/' in url_path # make instantly visible if the initial path is a service
menu_drawer = ui.left_drawer(bordered=True, value=menu_visible, fixed=True).classes('bg-primary')
with ui.footer():
ui.label('Copyright 2024 by My Company')
Expand All @@ -80,7 +83,6 @@ def main_app_index(menu_drawer: LeftDrawer): # main app index page
ui.label(info.title)
lnk.style('text-decoration: none; color: inherit;')
ui.label(info.description)

ui.html('<br><br>')
# add a link to the other app
ui.markdown("Click [here](/other_app) to visit the other app.")
Expand All @@ -89,7 +91,6 @@ def main_app_index(menu_drawer: LeftDrawer): # main app index page
@main_router.outlet('/services/{service_name}') # service outlet
def services_router(service_name: str, menu_drawer: LeftDrawer):
service: ServiceDefinition = services[service_name]
# update menu drawer
menu_drawer.clear()
with menu_drawer:
menu_drawer.show()
Expand Down Expand Up @@ -134,4 +135,4 @@ def sub_service_index(sub_service: SubServiceDefinition):
ui.label(sub_service.description)


ui.run(show=False)
ui.run(show=False, title='NiceCLOUD Portal')
File renamed without changes.
23 changes: 23 additions & 0 deletions examples/outlet/login/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from nicegui import ui


@ui.outlet('/')
def main_router(url_path: str):
with ui.header():
with ui.link('', '/').style('text-decoration: none; color: inherit;') as lnk:
ui.html('<span style="color:white">Nice</span>'
'<span style="color:black">CLOUD</span>').classes('text-h3')


@main_router.view('/')
def main_app_index():
# login page
ui.label('Welcome to NiceCLOUD!').classes('text-3xl')
ui.html('<br>')
ui.label('Username:')
ui.textbox('username')
ui.label('Password:')
ui.password('password')


ui.run(show=False)
2 changes: 1 addition & 1 deletion examples/single_page_router/advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from nicegui import ui
from nicegui.page import page
from nicegui.single_page_app import SinglePageApp
from nicegui.single_page_router import SinglePageRouter
from nicegui.single_page_router_config import SinglePageRouterConfig


@page('/', title='Welcome!')
Expand Down
4 changes: 2 additions & 2 deletions nicegui/elements/router_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from nicegui.single_page_target import SinglePageTarget

if TYPE_CHECKING:
from nicegui.single_page_router import SinglePageRouter
from nicegui.single_page_router_config import SinglePageRouterConfig


class RouterFrame(ui.element, component='router_frame.js'):
Expand All @@ -15,7 +15,7 @@ class RouterFrame(ui.element, component='router_frame.js'):
management to prevent the browser from reloading the whole page."""

def __init__(self,
router: "SinglePageRouter",
router: "SinglePageRouterConfig",
included_paths: Optional[list[str]] = None,
excluded_paths: Optional[list[str]] = None,
use_browser_history: bool = True,
Expand Down
8 changes: 4 additions & 4 deletions nicegui/outlet.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from typing import Callable, Any, Self, Optional, Generator

from nicegui.client import Client
from nicegui.single_page_router import SinglePageRouter
from nicegui.single_page_router_config import SinglePageRouterConfig
from nicegui.elements.router_frame import RouterFrame


class Outlet(SinglePageRouter):
class Outlet(SinglePageRouterConfig):
"""An outlet allows the creation of single page applications which do not reload the page when navigating between
different views. The outlet is a container for multiple views and can contain nested outlets.
Expand All @@ -22,7 +22,7 @@ def __init__(self,
path: str,
outlet_builder: Optional[Callable] = None,
browser_history: bool = True,
parent: Optional['SinglePageRouter'] = None,
parent: Optional['SinglePageRouterConfig'] = None,
on_instance_created: Optional[Callable] = None,
**kwargs) -> None:
"""
Expand Down Expand Up @@ -122,7 +122,7 @@ def current_url(self) -> str:
class OutletView:
"""Defines a single view / "content page" which is displayed in an outlet"""

def __init__(self, parent_outlet: SinglePageRouter, path: str, title: Optional[str] = None):
def __init__(self, parent_outlet: SinglePageRouterConfig, path: str, title: Optional[str] = None):
"""
:param parent_outlet: The parent outlet in which this view is displayed
:param path: The path of the view, relative to the base path of the outlet
Expand Down
13 changes: 7 additions & 6 deletions nicegui/single_page_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@
from fastapi.routing import APIRoute

from nicegui import core
from nicegui.single_page_router import SinglePageRouter, SinglePageRouterEntry
from nicegui.single_page_router_config import SinglePageRouterConfig, SinglePageRouterEntry


class SinglePageApp:

def __init__(self,
target: Union[SinglePageRouter, str],
target: Union[SinglePageRouterConfig, str],
page_template: Callable[[], Generator] = None,
included: Union[List[Union[Callable, str]], str, Callable] = '/*',
excluded: Union[List[Union[Callable, str]], str, Callable] = '') -> None:
"""
:param target: The SinglePageRouter which shall be used as the main router for the single page application.
Alternatively, you can pass the root path of the pages which shall be redirected to the single page router.
:param target: The SinglePageRouterConfig which shall be used as the main router for the single page
application. Alternatively, you can pass the root path of the pages which shall be redirected to the
single page router.
:param included: Optional list of masks and callables of paths to include. Default is "/*" which includes all.
If you do not want to include all relative paths, you can specify a list of masks or callables to refine the
included paths. If a callable is passed, it must be decorated with a page.
Expand All @@ -25,14 +26,14 @@ def __init__(self,
exclusion mask.
"""
if isinstance(target, str):
target = SinglePageRouter(target, page_template=page_template)
target = SinglePageRouterConfig(target, page_template=page_template)
self.single_page_router = target
self.included: List[Union[Callable, str]] = [included] if not isinstance(included, list) else included
self.excluded: List[Union[Callable, str]] = [excluded] if not isinstance(excluded, list) else excluded
self.system_excluded = ['/docs', '/redoc', '/openapi.json', '_*']

def setup(self):
"""Registers the SinglePageRouter with the @page decorator to handle all routes defined by the router"""
"""Registers the SinglePageRouterConfig with the @page decorator to handle all routes defined by the router"""
self.reroute_pages()
self.single_page_router.setup_pages(force=True)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ def create_path_mask(path: str) -> str:
return re.sub(r'{[^}]+}', '*', path)


class SinglePageRouter:
"""The SinglePageRouter allows the development of a Single Page Application (SPA).
class SinglePageRouterConfig:
"""The SinglePageRouterConfig allows the development of a Single Page Application (SPA).
SPAs are web applications which load a single HTML page and dynamically update the content of the page.
This allows faster page switches and a more dynamic user experience."""

def __init__(self,
path: str,
browser_history: bool = True,
parent: Optional["SinglePageRouter"] = None,
parent: Optional["SinglePageRouterConfig"] = None,
page_template: Optional[Callable[[], Generator]] = None,
on_instance_created: Optional[Callable] = None,
**kwargs) -> None:
Expand All @@ -78,7 +78,7 @@ def __init__(self,
self.parent_router = parent
if self.parent_router is not None:
self.parent_router._register_child_router(self)
self.child_routers: List['SinglePageRouter'] = []
self.child_routers: List['SinglePageRouterConfig'] = []
self.page_kwargs = kwargs

def setup_pages(self, force=False) -> Self:
Expand Down Expand Up @@ -220,6 +220,6 @@ def insert_content_area(self,
content.navigate_to(initial_url, _server_side=False, sync=True)
return content

def _register_child_router(self, router: 'SinglePageRouter') -> None:
def _register_child_router(self, router: 'SinglePageRouterConfig') -> None:
"""Registers a child router to the parent router"""
self.child_routers.append(router)
4 changes: 2 additions & 2 deletions nicegui/single_page_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Dict, Optional, TYPE_CHECKING, Self

if TYPE_CHECKING:
from nicegui.single_page_router import SinglePageRouterEntry, SinglePageRouter
from nicegui.single_page_router_config import SinglePageRouterEntry, SinglePageRouterConfig


class SinglePageTarget:
Expand All @@ -15,7 +15,7 @@ def __init__(self,
entry: Optional['SinglePageRouterEntry'] = None,
fragment: Optional[str] = None,
query_string: Optional[str] = None,
router: Optional['SinglePageRouter'] = None):
router: Optional['SinglePageRouterConfig'] = None):
"""
:param path: The path of the URL
:param entry: Predefined entry, e.g. targeting a Callable
Expand Down

0 comments on commit 3e5f2c2

Please sign in to comment.