mirror of
https://github.com/rio-labs/rio.git
synced 2026-02-20 05:08:37 -06:00
@page now supports an explicit order
This commit is contained in:
11
rio/app.py
11
rio/app.py
@@ -141,9 +141,10 @@ class App:
|
||||
name: str | None = None,
|
||||
description: str | None = None,
|
||||
icon: ImageLike | None = None,
|
||||
pages: Iterable[rio.ComponentPage]
|
||||
pages: Iterable[rio.ComponentPage | rio.Redirect]
|
||||
| os.PathLike
|
||||
| Literal["auto"] = "auto",
|
||||
| str
|
||||
| None = None,
|
||||
on_app_start: rio.EventHandler[App] = None,
|
||||
on_app_close: rio.EventHandler[App] = None,
|
||||
on_session_start: rio.EventHandler[rio.Session] = None,
|
||||
@@ -193,7 +194,7 @@ class App:
|
||||
|
||||
Per default, rio scans your project's "pages" directory for
|
||||
components decorated with `@rio.page` and turns them into pages. To
|
||||
override the location of this directory, you can pass in a file
|
||||
override the location of this directory, you can provide a custom
|
||||
path.
|
||||
|
||||
`on_app_start`: A function that will be called when the app is first
|
||||
@@ -321,12 +322,12 @@ class App:
|
||||
def _load_pages(self) -> None:
|
||||
pages: Iterable[rio.ComponentPage | rio.Redirect]
|
||||
|
||||
if self._raw_pages == "auto":
|
||||
if self._raw_pages is None:
|
||||
pages = routing.auto_detect_pages(
|
||||
self._module_path / "pages",
|
||||
package=f"{self._module_path.stem}.pages",
|
||||
)
|
||||
elif isinstance(self._raw_pages, os.PathLike):
|
||||
elif isinstance(self._raw_pages, (os.PathLike, str)):
|
||||
pages = routing.auto_detect_pages(Path(self._raw_pages))
|
||||
else:
|
||||
pages = self._raw_pages # type: ignore (wtf?)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import math
|
||||
import typing as t
|
||||
import warnings
|
||||
from collections.abc import Callable, Iterable, Sequence
|
||||
@@ -129,6 +130,10 @@ class ComponentPage:
|
||||
guard: Callable[[rio.GuardEvent], None | rio.URL | str] | None = None
|
||||
meta_tags: dict[str, str] = field(default_factory=dict)
|
||||
|
||||
# This is used to allow users to order pages when using the `rio.page`
|
||||
# decorator. It's not public, but simply a convenient place to store this.
|
||||
_page_order_: int | None = field(default=None, init=False)
|
||||
|
||||
if not t.TYPE_CHECKING:
|
||||
page_url: str | None = None
|
||||
|
||||
@@ -330,8 +335,11 @@ def page(
|
||||
icon: str = DEFAULT_ICON,
|
||||
guard: (Callable[[GuardEvent], None | rio.URL | str] | None) = None,
|
||||
meta_tags: dict[str, str] | None = None,
|
||||
order: int | None = None,
|
||||
):
|
||||
""" """
|
||||
"""
|
||||
TODO
|
||||
"""
|
||||
|
||||
def decorator(build: C) -> C:
|
||||
nonlocal name, url_segment
|
||||
@@ -358,10 +366,44 @@ def page(
|
||||
return decorator
|
||||
|
||||
|
||||
def _page_sort_key(page: rio.ComponentPage) -> tuple:
|
||||
"""
|
||||
Returns a key that can be used to sort pages.
|
||||
"""
|
||||
return (
|
||||
# Any explicit ordering takes precedence
|
||||
math.inf if page._page_order_ is None else page._page_order_,
|
||||
# Put the home page first
|
||||
not page.url_segment == "",
|
||||
# Then sort by name
|
||||
page.name,
|
||||
)
|
||||
|
||||
|
||||
def auto_detect_pages(
|
||||
directory: Path,
|
||||
*,
|
||||
package: str | None = None,
|
||||
) -> list[rio.ComponentPage]:
|
||||
# Find all pages using the iterator method
|
||||
pages = list(
|
||||
_auto_detect_pages_iter(
|
||||
directory,
|
||||
package=package,
|
||||
)
|
||||
)
|
||||
|
||||
# Sort them
|
||||
pages.sort(key=_page_sort_key)
|
||||
|
||||
# Done
|
||||
return pages
|
||||
|
||||
|
||||
def _auto_detect_pages_iter(
|
||||
directory: Path,
|
||||
*,
|
||||
package: str | None = None,
|
||||
) -> Iterable[rio.ComponentPage]:
|
||||
try:
|
||||
contents = list(directory.iterdir())
|
||||
|
||||
@@ -22,7 +22,7 @@ def guard(event: rio.GuardEvent) -> str | None:
|
||||
|
||||
## Parameters
|
||||
|
||||
`event`: The event that triggered the guard containing the `session` and `active_pages`.
|
||||
`event`: The event that triggered the guard containing the `session` and `active_pages`.
|
||||
"""
|
||||
# If the user is already logged in, there is no reason to show the login page.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user