Coverage for src/lexigram/admin/dashboard/page_renderer.py: 94%
18 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 14:56 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 14:56 +0800
1"""Host-side renderer for structured management page content.
3``PageContent`` is the only way management pages reach the browser. This module
4builds the page shell (header + body + pagination) via ``lexigram-ui``; the body
5is rendered by ``render_content`` exactly like dashboard widgets.
6"""
8from __future__ import annotations
10from starlette.responses import HTMLResponse
12from lexigram.admin.dashboard.content_renderer import render_content
13from lexigram.contracts.admin.page_content import PageContent, PaginationContent
14from lexigram.ui import PageSizeSelector, PaginationLinks, el, raw, render_to_string
17def _render_pagination(pagination: PaginationContent) -> str:
18 """Render the "Showing X to Y of Z" block + pager + page-size selector."""
19 total = pagination.total
20 if total <= 0:
21 return ""
22 total_pages = max(1, (total + pagination.per_page - 1) // pagination.per_page)
23 start_item = (pagination.page - 1) * pagination.per_page + 1
24 end_item = min(pagination.page * pagination.per_page, total)
25 return render_to_string(
26 el(
27 "div",
28 {
29 "class": (
30 "flex items-center justify-between border-t border-border "
31 "bg-background px-4 py-3 mt-4"
32 ),
33 },
34 el(
35 "p",
36 {
37 "class": (
38 "text-[11px] uppercase tracking-wider "
39 "text-[var(--muted-foreground)] font-semibold"
40 ),
41 },
42 "Showing ",
43 el("span", {"class": "font-bold"}, str(start_item)),
44 " to ",
45 el("span", {"class": "font-bold"}, str(end_item)),
46 " of ",
47 el("span", {"class": "font-bold"}, str(total)),
48 " results",
49 ),
50 el(
51 "div",
52 {"class": "flex items-center space-x-4"},
53 PaginationLinks(
54 page=pagination.page,
55 total_pages=total_pages,
56 per_page=pagination.per_page,
57 base_url=pagination.base_url,
58 ),
59 PageSizeSelector(
60 per_page=pagination.per_page,
61 base_url=pagination.base_url,
62 ),
63 ),
64 )
65 )
68def render_page_content(content: PageContent) -> HTMLResponse:
69 """Render structured page content to an HTML response."""
70 body_html = render_content(content.body)
71 pagination_html = (
72 _render_pagination(content.pagination) if content.pagination else ""
73 )
74 html = render_to_string(
75 el(
76 "div",
77 {"class": "space-y-6"},
78 el(
79 "h1",
80 {"class": "text-2xl font-semibold tracking-tight"},
81 content.title,
82 ),
83 el(
84 "div",
85 {"id": "table-data"},
86 raw(body_html),
87 raw(pagination_html),
88 ),
89 )
90 )
91 return HTMLResponse(html)