Skip to content

Commit 710f1f5

Browse files
olivermeyerclaude
andcommitted
feat(gui): default page title to context name
All five page_* decorators and GUINamespace methods now accept title: str | None = None. When None, the wrapper resolves the title lazily at request time via get_context().name.title(), ensuring every page gets a sensible default without callers having to repeat the project name. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c22b79e commit 710f1f5

3 files changed

Lines changed: 131 additions & 25 deletions

File tree

ATTRIBUTIONS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6684,7 +6684,7 @@ multidict implementation
66846684

66856685
```
66866686

6687-
## nicegui (3.9.0) - UNKNOWN
6687+
## nicegui (3.10.0) - UNKNOWN
66886688

66896689
Create web-based user interfaces with Python. The nice way.
66906690

src/aignostics_foundry_core/gui/auth.py

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def dashboard(user: dict) -> None:
5151
from loguru import logger
5252

5353
from aignostics_foundry_core.api.auth import AUTH0_ROLE_ADMIN, AuthSettings, get_auth_client
54+
from aignostics_foundry_core.foundry import get_context
5455
from aignostics_foundry_core.sentry import set_sentry_user
5556
from aignostics_foundry_core.settings import load_settings
5657

@@ -81,7 +82,7 @@ class _PageEntry:
8182

8283
access: AccessLevel
8384
path: str
84-
title: str
85+
title: str | None # None → resolved at request time from get_context().name.title()
8586
func: Callable[..., Any]
8687

8788

@@ -220,7 +221,7 @@ async def require_gui_user(request: Request, return_to: str | None = None) -> di
220221

221222
def _actualize_public(
222223
path: str,
223-
title: str = "",
224+
title: str | None = None,
224225
frame_func: FrameFunc = None,
225226
) -> Callable[..., Callable[[Request], Awaitable[None]]]:
226227
"""Register a public NiceGUI page immediately with the given frame_func.
@@ -235,8 +236,9 @@ def decorator(
235236
) -> Callable[[Request], Awaitable[None]]:
236237
@ui.page(path, response_timeout=RESPONSE_TIMEOUT)
237238
async def wrapper(request: Request) -> None:
239+
resolved_title = title if title is not None else get_context().name.title()
238240
user = await get_gui_user(request)
239-
with frame_func(title, user=user) if frame_func is not None else contextlib.nullcontext():
241+
with frame_func(resolved_title, user=user) if frame_func is not None else contextlib.nullcontext():
240242
await _invoke_page_func(func, user)
241243

242244
wrapper.__name__ = func.__name__
@@ -250,7 +252,7 @@ async def wrapper(request: Request) -> None:
250252

251253
def _actualize_authenticated(
252254
path: str,
253-
title: str = "",
255+
title: str | None = None,
254256
frame_func: FrameFunc = None,
255257
) -> Callable[..., Callable[[Request], Awaitable[None]]]:
256258
"""Register an authenticated NiceGUI page immediately with the given frame_func.
@@ -265,10 +267,11 @@ def decorator(
265267
) -> Callable[[Request], Awaitable[None]]:
266268
@ui.page(path, response_timeout=RESPONSE_TIMEOUT)
267269
async def wrapper(request: Request) -> None:
270+
resolved_title = title if title is not None else get_context().name.title()
268271
user = await require_gui_user(request)
269272
if not user:
270273
return
271-
with frame_func(title, user=user) if frame_func is not None else contextlib.nullcontext():
274+
with frame_func(resolved_title, user=user) if frame_func is not None else contextlib.nullcontext():
272275
await _invoke_page_func(func, user)
273276

274277
wrapper.__name__ = func.__name__
@@ -282,7 +285,7 @@ async def wrapper(request: Request) -> None:
282285

283286
def _actualize_admin(
284287
path: str,
285-
title: str = "",
288+
title: str | None = None,
286289
frame_func: FrameFunc = None,
287290
) -> Callable[..., Callable[[Request], Awaitable[None]]]:
288291
"""Register an admin-only NiceGUI page immediately with the given frame_func.
@@ -297,18 +300,19 @@ def decorator(
297300
) -> Callable[[Request], Awaitable[None]]:
298301
@ui.page(path, response_timeout=RESPONSE_TIMEOUT)
299302
async def wrapper(request: Request) -> None:
303+
resolved_title = title if title is not None else get_context().name.title()
300304
user = await require_gui_user(request)
301305
if not user:
302306
return
303307

304308
auth_settings = load_settings(AuthSettings)
305309
role = user.get(auth_settings.auth0_role_claim)
306310
if role != AUTH0_ROLE_ADMIN:
307-
with frame_func(title, user=user) if frame_func is not None else contextlib.nullcontext():
311+
with frame_func(resolved_title, user=user) if frame_func is not None else contextlib.nullcontext():
308312
ui.label(f"{MSG_403_FORBIDDEN} - Admin access required").classes(CLASS_FORBIDDEN_ERROR)
309313
return
310314

311-
with frame_func(title, user=user) if frame_func is not None else contextlib.nullcontext():
315+
with frame_func(resolved_title, user=user) if frame_func is not None else contextlib.nullcontext():
312316
await _invoke_page_func(func, user)
313317

314318
wrapper.__name__ = func.__name__
@@ -322,7 +326,7 @@ async def wrapper(request: Request) -> None:
322326

323327
def _actualize_internal(
324328
path: str,
325-
title: str = "",
329+
title: str | None = None,
326330
frame_func: FrameFunc = None,
327331
) -> Callable[..., Callable[[Request], Awaitable[None]]]:
328332
"""Register an internal-org-only NiceGUI page immediately with the given frame_func.
@@ -337,18 +341,19 @@ def decorator(
337341
) -> Callable[[Request], Awaitable[None]]:
338342
@ui.page(path, response_timeout=RESPONSE_TIMEOUT)
339343
async def wrapper(request: Request) -> None:
344+
resolved_title = title if title is not None else get_context().name.title()
340345
user = await require_gui_user(request)
341346
if not user:
342347
return
343348

344349
auth_settings = load_settings(AuthSettings)
345350
org_id = user.get("org_id")
346351
if org_id != auth_settings.internal_org_id:
347-
with frame_func(title, user=user) if frame_func is not None else contextlib.nullcontext():
352+
with frame_func(resolved_title, user=user) if frame_func is not None else contextlib.nullcontext():
348353
ui.label(f"{MSG_403_FORBIDDEN} - Internal access required").classes(CLASS_FORBIDDEN_ERROR)
349354
return
350355

351-
with frame_func(title, user=user) if frame_func is not None else contextlib.nullcontext():
356+
with frame_func(resolved_title, user=user) if frame_func is not None else contextlib.nullcontext():
352357
await _invoke_page_func(func, user)
353358

354359
wrapper.__name__ = func.__name__
@@ -362,7 +367,7 @@ async def wrapper(request: Request) -> None:
362367

363368
def _actualize_internal_admin(
364369
path: str,
365-
title: str = "",
370+
title: str | None = None,
366371
frame_func: FrameFunc = None,
367372
) -> Callable[..., Callable[[Request], Awaitable[None]]]:
368373
"""Register an internal-org admin-only NiceGUI page immediately with the given frame_func.
@@ -377,6 +382,7 @@ def decorator(
377382
) -> Callable[[Request], Awaitable[None]]:
378383
@ui.page(path, response_timeout=RESPONSE_TIMEOUT)
379384
async def wrapper(request: Request) -> None:
385+
resolved_title = title if title is not None else get_context().name.title()
380386
user = await require_gui_user(request)
381387
if not user:
382388
return
@@ -386,11 +392,11 @@ async def wrapper(request: Request) -> None:
386392
role = user.get(auth_settings.auth0_role_claim)
387393

388394
if org_id != auth_settings.internal_org_id or role != AUTH0_ROLE_ADMIN:
389-
with frame_func(title, user=user) if frame_func is not None else contextlib.nullcontext():
395+
with frame_func(resolved_title, user=user) if frame_func is not None else contextlib.nullcontext():
390396
ui.label(f"{MSG_403_FORBIDDEN} - Internal admin access required").classes(CLASS_FORBIDDEN_ERROR)
391397
return
392398

393-
with frame_func(title, user=user) if frame_func is not None else contextlib.nullcontext():
399+
with frame_func(resolved_title, user=user) if frame_func is not None else contextlib.nullcontext():
394400
await _invoke_page_func(func, user)
395401

396402
wrapper.__name__ = func.__name__
@@ -408,7 +414,7 @@ async def wrapper(request: Request) -> None:
408414
# ---------------------------------------------------------------------------
409415

410416

411-
def page_public(path: str, title: str = "") -> Callable[..., Any]:
417+
def page_public(path: str, title: str | None = None) -> Callable[..., Any]:
412418
"""Decorator that registers a public page in the global registry.
413419
414420
The route is NOT registered with NiceGUI immediately. Call
@@ -418,6 +424,7 @@ def page_public(path: str, title: str = "") -> Callable[..., Any]:
418424
Args:
419425
path: The URL path for the page.
420426
title: The title passed to the frame function when the page is actualized.
427+
Defaults to the project name from ``get_context()`` when omitted.
421428
422429
Returns:
423430
A decorator that records the page function in the registry and returns
@@ -437,7 +444,7 @@ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
437444
return decorator
438445

439446

440-
def page_authenticated(path: str, title: str = "") -> Callable[..., Any]:
447+
def page_authenticated(path: str, title: str | None = None) -> Callable[..., Any]:
441448
"""Decorator that registers an authenticated page in the global registry.
442449
443450
The route is NOT registered with NiceGUI immediately. Call
@@ -447,6 +454,7 @@ def page_authenticated(path: str, title: str = "") -> Callable[..., Any]:
447454
Args:
448455
path: The URL path for the page.
449456
title: The title passed to the frame function when the page is actualized.
457+
Defaults to the project name from ``get_context()`` when omitted.
450458
451459
Returns:
452460
A decorator that records the page function in the registry and returns
@@ -466,7 +474,7 @@ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
466474
return decorator
467475

468476

469-
def page_admin(path: str, title: str = "") -> Callable[..., Any]:
477+
def page_admin(path: str, title: str | None = None) -> Callable[..., Any]:
470478
"""Decorator that registers an admin-only page in the global registry.
471479
472480
The route is NOT registered with NiceGUI immediately. Call
@@ -476,6 +484,7 @@ def page_admin(path: str, title: str = "") -> Callable[..., Any]:
476484
Args:
477485
path: The URL path for the page.
478486
title: The title passed to the frame function when the page is actualized.
487+
Defaults to the project name from ``get_context()`` when omitted.
479488
480489
Returns:
481490
A decorator that records the page function in the registry and returns
@@ -495,7 +504,7 @@ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
495504
return decorator
496505

497506

498-
def page_internal(path: str, title: str = "") -> Callable[..., Any]:
507+
def page_internal(path: str, title: str | None = None) -> Callable[..., Any]:
499508
"""Decorator that registers an internal-org-only page in the global registry.
500509
501510
The route is NOT registered with NiceGUI immediately. Call
@@ -505,6 +514,7 @@ def page_internal(path: str, title: str = "") -> Callable[..., Any]:
505514
Args:
506515
path: The URL path for the page.
507516
title: The title passed to the frame function when the page is actualized.
517+
Defaults to the project name from ``get_context()`` when omitted.
508518
509519
Returns:
510520
A decorator that records the page function in the registry and returns
@@ -524,7 +534,7 @@ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
524534
return decorator
525535

526536

527-
def page_internal_admin(path: str, title: str = "") -> Callable[..., Any]:
537+
def page_internal_admin(path: str, title: str | None = None) -> Callable[..., Any]:
528538
"""Decorator that registers an internal-org admin-only page in the global registry.
529539
530540
The route is NOT registered with NiceGUI immediately. Call
@@ -534,6 +544,7 @@ def page_internal_admin(path: str, title: str = "") -> Callable[..., Any]:
534544
Args:
535545
path: The URL path for the page.
536546
title: The title passed to the frame function when the page is actualized.
547+
Defaults to the project name from ``get_context()`` when omitted.
537548
538549
Returns:
539550
A decorator that records the page function in the registry and returns
@@ -596,7 +607,7 @@ def __init__(self, frame_func: FrameFunc = None) -> None:
596607
def public(
597608
self,
598609
path: str,
599-
title: str = "",
610+
title: str | None = None,
600611
) -> Callable[..., Callable[[Request], Awaitable[None]]]:
601612
"""Decorator for public NiceGUI pages.
602613
@@ -606,6 +617,7 @@ def public(
606617
Args:
607618
path: The URL path for the page.
608619
title: The title passed to the frame function (if configured).
620+
Defaults to the project name from ``get_context()`` when omitted.
609621
610622
Returns:
611623
A decorator that wraps the page function.
@@ -615,7 +627,7 @@ def public(
615627
def authenticated(
616628
self,
617629
path: str,
618-
title: str = "",
630+
title: str | None = None,
619631
) -> Callable[..., Callable[[Request], Awaitable[None]]]:
620632
"""Decorator for authenticated NiceGUI pages.
621633
@@ -625,6 +637,7 @@ def authenticated(
625637
Args:
626638
path: The URL path for the page.
627639
title: The title passed to the frame function (if configured).
640+
Defaults to the project name from ``get_context()`` when omitted.
628641
629642
Returns:
630643
A decorator that wraps the page function.
@@ -634,7 +647,7 @@ def authenticated(
634647
def admin(
635648
self,
636649
path: str,
637-
title: str = "",
650+
title: str | None = None,
638651
) -> Callable[..., Callable[[Request], Awaitable[None]]]:
639652
"""Decorator for admin-only NiceGUI pages.
640653
@@ -644,6 +657,7 @@ def admin(
644657
Args:
645658
path: The URL path for the page.
646659
title: The title passed to the frame function (if configured).
660+
Defaults to the project name from ``get_context()`` when omitted.
647661
648662
Returns:
649663
A decorator that wraps the page function.
@@ -653,7 +667,7 @@ def admin(
653667
def internal(
654668
self,
655669
path: str,
656-
title: str = "",
670+
title: str | None = None,
657671
) -> Callable[..., Callable[[Request], Awaitable[None]]]:
658672
"""Decorator for internal-org-only NiceGUI pages.
659673
@@ -663,6 +677,7 @@ def internal(
663677
Args:
664678
path: The URL path for the page.
665679
title: The title passed to the frame function (if configured).
680+
Defaults to the project name from ``get_context()`` when omitted.
666681
667682
Returns:
668683
A decorator that wraps the page function.
@@ -672,7 +687,7 @@ def internal(
672687
def internal_admin(
673688
self,
674689
path: str,
675-
title: str = "",
690+
title: str | None = None,
676691
) -> Callable[..., Callable[[Request], Awaitable[None]]]:
677692
"""Decorator for internal-org admin-only NiceGUI pages.
678693
@@ -682,6 +697,7 @@ def internal_admin(
682697
Args:
683698
path: The URL path for the page.
684699
title: The title passed to the frame function (if configured).
700+
Defaults to the project name from ``get_context()`` when omitted.
685701
686702
Returns:
687703
A decorator that wraps the page function.

0 commit comments

Comments
 (0)