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

1"""Template utilities for lexigram-admin. 

2 

3Provides simple template rendering functions for standalone pages 

4like login, error, etc. Uses StandaloneLayout for consistent styling. 

5""" 

6 

7from markupsafe import escape 

8 

9from lexigram.admin.ui.layouts import ( 

10 StandaloneLayout, 

11 StandaloneLayoutConfig, 

12 StandaloneLayoutContext, 

13) 

14 

15 

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. 

27 

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 

37 

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 ) 

49 

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 """ 

58 

59 icon_html = ( 

60 f'<div style="font-size: 3rem; margin-bottom: 0.5rem;">{icon}</div>' 

61 if icon 

62 else "" 

63 ) 

64 

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 """ 

76 

77 layout = StandaloneLayout(config=config, context=context) 

78 return layout.render(content)