Coverage for src/lexigram/admin/lib/template/error.py: 25%
12 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 23:39 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 23:39 +0800
1"""Template utilities for lexigram-admin.
3Provides simple template rendering functions for standalone pages
4like login, error, etc. Uses StandaloneLayout for consistent styling.
5"""
7from markupsafe import escape
9from lexigram.admin.ui.layouts import (
10 StandaloneLayout,
11 StandaloneLayoutConfig,
12 StandaloneLayoutContext,
13)
16def render_error_page(
17 status_code: int = 500,
18 title: str = "Error",
19 message: str = "An error occurred",
20 details: str = "",
21 site_name: str = "Lexigram Admin",
22 icon: str = "",
23 action_text: str = "Return to Admin",
24 action_url: str = "/admin/",
25) -> str:
26 """Render a standalone error page.
28 Args:
29 status_code: HTTP status code
30 title: Error title
31 message: Error message
32 details: Additional details (hidden in production)
33 site_name: Site name for branding
34 icon: Emoji icon to display
35 action_text: Call-to-action button text
36 action_url: Call-to-action button URL
38 Returns:
39 HTML string for error page
40 """
41 config = StandaloneLayoutConfig(
42 app_name=site_name,
43 show_footer=True,
44 centered=True,
45 )
46 context = StandaloneLayoutContext(
47 page_title=title,
48 )
50 details_html = ""
51 if details:
52 details_html = f"""
53 <details class="text-left mt-4">
54 <summary class="cursor-pointer font-medium text-sm text-muted-foreground">Technical Details</summary>
55 <pre class="bg-muted text-foreground p-4 rounded-md overflow-x-auto mt-2">{escape(details)}</pre>
56 </details>
57 """
59 icon_html = (
60 f'<div style="font-size: 3rem; margin-bottom: 0.5rem;">{icon}</div>'
61 if icon
62 else ""
63 )
65 content = f"""
66 <div class="w-full max-w-2xl bg-card border border-border rounded-lg shadow-lg p-8 text-center">
67 {icon_html}
68 <div class="text-6xl font-bold text-muted-foreground mb-2">{status_code}</div>
69 <h1 class="text-2xl font-bold text-foreground mb-2">{escape(title)}</h1>
70 <p class="text-sm text-muted-foreground">{escape(message)}</p>
71 {details_html}
72 <a href="{escape(action_url)}"
73 class="inline-block px-6 py-3 rounded-md bg-primary text-primary-foreground font-medium mt-4 hover:bg-primary/90 transition-colors">{escape(action_text)}</a>
74 </div>
75 """
77 layout = StandaloneLayout(config=config, context=context)
78 return layout.render(content)