فهرست منبع

WIP Pages Element

- Socket connections still TODO
Christoph Trappe 3 سال پیش
والد
کامیت
b5dfba5408
9فایلهای تغییر یافته به همراه65 افزوده شده و 27 حذف شده
  1. 10 2
      main.py
  2. 1 1
      nicegui/__init__.py
  3. 2 2
      nicegui/elements/element.py
  4. 1 1
      nicegui/elements/log.py
  5. 42 0
      nicegui/elements/page.py
  6. 1 1
      nicegui/elements/scene_object3d.py
  7. 6 17
      nicegui/nicegui.py
  8. 1 3
      nicegui/run.py
  9. 1 0
      nicegui/ui.py

+ 10 - 2
main.py

@@ -1,5 +1,5 @@
 #!/usr/bin/env python3
-from nicegui import ui, wp
+from nicegui import ui, initial_page
 from contextlib import contextmanager
 import inspect
 from nicegui.elements.markdown import Markdown
@@ -11,7 +11,7 @@ import re
 import asyncio
 
 # add docutils css to webpage
-wp.head_html += docutils.core.publish_parts('', writer_name='html')['stylesheet']
+initial_page.head_html += docutils.core.publish_parts('', writer_name='html')['stylesheet']
 
 @contextmanager
 def example(content: Union[Element, str]):
@@ -346,4 +346,12 @@ with example(lifecycle):
 
     ui.on_startup(counter())
 
+with example(ui.page):
+
+    with ui.page('/other_page') as other:
+        ui.label('Welcome on the other side')
+        ui.link('GO TO MAIN PAGE', '/').classes('text-decoration: underline text-blue')
+
+    ui.link('Visit other page', '/other_page').classes('text-decoration: underline text-blue')
+
 ui.run()

+ 1 - 1
nicegui/__init__.py

@@ -1,2 +1,2 @@
-from nicegui.nicegui import app, ui, wp
+from nicegui.nicegui import app, ui, initial_page
 from nicegui import elements

+ 2 - 2
nicegui/elements/element.py

@@ -3,7 +3,7 @@ from binding.binding import BindableProperty
 
 class Element:
 
-    wp: None
+    wp_stack = []
     view_stack = []
 
     visible = BindableProperty
@@ -14,7 +14,7 @@ class Element:
 
         self.parent_view = self.view_stack[-1]
         self.parent_view.add(view)
-        view.add_page(self.wp)
+        view.add_page(self.wp_stack[-1])
         self.view = view
 
         self.visible = True

+ 1 - 1
nicegui/elements/log.py

@@ -28,7 +28,7 @@ class Log(Element):
 
         await asyncio.gather(*[
             self.view.run_method(f'push("{urllib.parse.quote(line)}")', socket)
-            for socket in WebPage.sockets[Element.wp.page_id].values()
+            for socket in WebPage.sockets[Element.wp_stack[-1].page_id].values()
         ])
 
     def push(self, line: str):

+ 42 - 0
nicegui/elements/page.py

@@ -0,0 +1,42 @@
+import justpy as jp
+
+from .element import Element
+from pygments.formatters import HtmlFormatter
+
+
+class Page(jp.QuasarPage):
+
+    def __init__(self, route: str = '', title: str = 'NiceGUI', favicon: str = 'favicon.ico', **kwargs):
+        """Page
+
+        Creates a new page at the given path.
+
+        :param route: the route of the new page. All paths must start with '/', otherwise an error occurs.
+        """
+        super().__init__(**kwargs)
+
+        self.delete_flag = False
+        self.title = title
+        self.favicon = favicon
+
+        self.tailwind = True  # use Tailwind classes instead of Quasars
+        self.css = HtmlFormatter().get_style_defs('.codehilite')
+        self.head_html += '''
+            <script>
+                confirm = () => { setTimeout(location.reload.bind(location), 100); return false; };
+            </script>
+        '''  # avoid confirmation dialog for reload
+
+        self.view = jp.Div(a=self, classes='q-ma-md column items-start', style='row-gap: 1em')
+        self.view.add_page(self)
+
+        jp.Route(route, lambda: self)
+
+    def __enter__(self):
+        Element.wp_stack.append(self)
+        Element.view_stack.append(self.view)
+        return self
+
+    def __exit__(self, *_):
+        Element.wp_stack.pop()
+        Element.view_stack.pop()

+ 1 - 1
nicegui/elements/scene_object3d.py

@@ -34,7 +34,7 @@ class Object3D:
         return self
 
     def run_command(self, command: str, socket=None):
-        sockets = [socket] if socket else WebPage.sockets.get(Element.wp.page_id, {}).values()
+        sockets = [socket] if socket else WebPage.sockets.get(Element.wp_stack[-1].page_id, {}).values()
         for socket in sockets:
             asyncio.get_event_loop().create_task(self.view.run_method(command, socket))
 

+ 6 - 17
nicegui/nicegui.py

@@ -2,25 +2,11 @@
 from typing import Awaitable, Callable
 import asyncio
 import binding
-from pygments.formatters import HtmlFormatter
+
 from .ui import Ui  # NOTE: before justpy
 import justpy as jp
-from .elements.element import Element
 from .timer import Timer
 
-wp = jp.QuasarPage(delete_flag=False, title=Ui.config.title, favicon=Ui.config.favicon)
-wp.tailwind = True  # use Tailwind classes instead of Quasars
-wp.css = HtmlFormatter().get_style_defs('.codehilite')
-wp.head_html += '''
-    <script>
-        confirm = () => { setTimeout(location.reload.bind(location), 100); return false; };
-    </script>
-'''  # avoid confirmation dialog for reload
-
-main = jp.Div(a=wp, classes='q-ma-md column items-start', style='row-gap: 1em')
-main.add_page(wp)
-
-jp.justpy(lambda: wp, start_server=False)
 
 async def binding_loop():
     while True:
@@ -46,8 +32,11 @@ def shutdown():
     [t() for t in Ui.shutdown_tasks if isinstance(t, Callable)]
     [t.cancel() for t in tasks]
 
-Element.wp = wp
-Element.view_stack = [main]
 
 app = jp.app
 ui = Ui()
+
+initial_page = ui.page('/', ui.config.title, ui.config.favicon)
+initial_page.__enter__()
+jp.justpy(lambda: initial_page, start_server=False)
+

+ 1 - 3
nicegui/run.py

@@ -13,11 +13,9 @@ if not config.interactive and config.reload and not inspect.stack()[-2].filename
     uvicorn.run('nicegui:app', host=config.host, port=config.port, lifespan='on', reload=True)
     sys.exit()
 
-def run(self, *, host='0.0.0.0', port=80, title='NiceGUI', favicon='favicon.ico', reload=True, show=True):
+def run(self, *, host='0.0.0.0', port=80, reload=True, show=True):
 
     if config.interactive or reload == False:  # NOTE: if reload == True we already started uvicorn above
         if show:
             webbrowser.open(f'http://{host if host != "0.0.0.0" else "127.0.0.1"}:{port}/')
-        Element.wp.title = title
-        Element.wp.favicon = favicon
         uvicorn.run(jp.app, host=host, port=port, lifespan='on')

+ 1 - 0
nicegui/ui.py

@@ -18,6 +18,7 @@ class Ui:
     from .elements.menu import Menu as menu
     from .elements.notify import Notify as notify
     from .elements.number import Number as number
+    from .elements.page import Page as page
     from .elements.radio import Radio as radio
     from .elements.scene import Scene as scene
     from .elements.select import Select as select