Coverage for src / lexigram / admin / ui / organisms / data_table / states.py: 38%

24 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-13 22:14 +0800

1"""State rendering for data table component (skeleton, error states).""" 

2 

3from __future__ import annotations 

4 

5from typing import Any 

6 

7from lexigram.admin.config import TableConfiguration 

8from lexigram.ui import ActionButton, EmptyState, ErrorState, Skeleton, TableState, el 

9 

10 

11class StateRenderer: 

12 """Renders different states for data table (loading, error, empty).""" 

13 

14 def __init__(self, config: TableConfiguration, state: TableState): 

15 self.config = config 

16 self.state = state 

17 

18 def render_skeleton(self) -> Any: 

19 """Render loading skeleton.""" 

20 skeleton_rows = [] 

21 for _i in range(min(5, self.state.per_page)): 

22 cells = [] 

23 if self.config.resource_prefix: 

24 cells.append( 

25 el( 

26 "td", 

27 Skeleton(variant="rectangular", width="16px", height="16px"), 

28 class_="px-3 sm:px-6 py-4", 

29 ), 

30 ) 

31 for _ in self.config.columns: 

32 cells.append( 

33 el( 

34 "td", 

35 Skeleton(variant="text", width="80%"), 

36 class_="px-3 sm:px-6 py-4", 

37 ), 

38 ) 

39 if self.config.resource_prefix: 

40 cells.append( 

41 el( 

42 "td", 

43 Skeleton(variant="text", width="60px"), 

44 class_="px-3 sm:px-6 py-4", 

45 ), 

46 ) 

47 skeleton_rows.append( 

48 el( 

49 "tr", 

50 *cells, 

51 class_="border-b border-border", 

52 ), 

53 ) 

54 return el( 

55 "div", 

56 el( 

57 "table", 

58 el("tbody", *skeleton_rows, class_="bg-card"), 

59 class_="w-full", 

60 aria_label="Loading data", 

61 ), 

62 aria_busy="true", 

63 class_="overflow-x-auto", 

64 ) 

65 

66 def render_error(self, error: Any) -> Any: 

67 """Render error state.""" 

68 return ErrorState( 

69 title="Failed to load data", 

70 message=str(error), 

71 action=ActionButton( 

72 label="Retry", 

73 color="primary", 

74 onclick="window.location.reload()", 

75 ).render(), 

76 ) 

77 

78 def render_empty(self) -> Any: 

79 """Render empty state.""" 

80 return EmptyState( 

81 title="No results found", 

82 message="Try adjusting your filters or search terms.", 

83 icon="🔍", 

84 )