Coverage for src / lexigram / admin / ui / organisms / data_table / coordinator.py: 33%

33 statements  

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

1"""Data table coordinator component.""" 

2 

3from __future__ import annotations 

4 

5from typing import Any 

6 

7from lexigram.admin.config import TableConfiguration 

8from lexigram.admin.ui.organisms.data_table.actions import ActionManager 

9from lexigram.admin.ui.organisms.data_table.permissions import PermissionManager 

10from lexigram.admin.ui.organisms.data_table.rendering import DataTableRenderer 

11from lexigram.ui import Component, TableState 

12 

13 

14class DataTable(Component): 

15 """ 

16 Main DataTable Coordinator. 

17 Handles configuration, state management, and dispatches rendering to specific views. 

18 """ 

19 

20 def __init__( 

21 self, 

22 columns: list | None = None, 

23 data: list[dict] | None = None, 

24 state: TableState | None = None, 

25 config: TableConfiguration | None = None, 

26 # Legacy params 

27 page: int = 1, 

28 per_page: int = 20, 

29 total: int | None = None, 

30 filters: dict | None = None, 

31 resource_prefix: str | None = None, 

32 sort_by: str | None = None, 

33 sort_order: str = "asc", 

34 actions: list | None = None, 

35 header_actions: list | None = None, 

36 bulk_actions: list | None = None, 

37 filter_options: dict | None = None, 

38 layout_type: str | None = None, 

39 data_view: str | None = None, 

40 next_cursor: str | None = None, 

41 summary: dict[str, Any] | None = None, 

42 **props, 

43 ) -> None: 

44 super().__init__(**props) 

45 

46 # Resolve Configuration 

47 if config: 

48 self.config = config 

49 else: 

50 self.config = TableConfiguration( 

51 columns=columns or [], 

52 actions=actions or [], 

53 header_actions=header_actions or [], 

54 bulk_actions=bulk_actions or [], 

55 filter_options=filter_options, 

56 resource_prefix=resource_prefix, 

57 resource_name=props.get("resource_name"), 

58 default_view=data_view or "tabular", 

59 default_layout=layout_type or "stack", 

60 default_sort_by=sort_by, 

61 default_sort_order=sort_order, 

62 ) 

63 

64 # Resolve State 

65 if state: 

66 self.state = state 

67 else: 

68 self.state = TableState( 

69 search=filters.get("search", "") if filters else "", 

70 sort_by=sort_by, 

71 sort_order=sort_order, 

72 page=page, 

73 per_page=per_page, 

74 filters=filters or {}, 

75 view=data_view or self.config.default_view, 

76 layout=layout_type or self.config.default_layout, 

77 ) 

78 

79 self.data = data or [] 

80 self.total = total 

81 self.user = props.get("user") 

82 self.loading = props.get("loading", False) 

83 self.error = props.get("error") 

84 self.next_cursor = next_cursor 

85 self.summary = summary 

86 self.props = props 

87 

88 # Initialize permission manager 

89 self.permission_manager = PermissionManager( 

90 self.user, 

91 self.config.resource_name, 

92 ) 

93 self.permissions = self.permission_manager.check_permissions() 

94 

95 # Configure actions 

96 self.action_manager = ActionManager(self.config, self.permissions) 

97 self.action_manager.configure_actions() 

98 

99 # Show delete based on permissions 

100 self.show_delete = ( 

101 props.get("show_delete", True) and self.permissions["can_delete"] 

102 ) 

103 

104 def render(self) -> Any: 

105 """Render the data table using the modular renderer.""" 

106 renderer = DataTableRenderer( 

107 data=self.data, 

108 config=self.config, 

109 state=self.state, 

110 total=self.total, 

111 user=self.user, 

112 loading=self.loading, 

113 error=self.error, 

114 next_cursor=self.next_cursor, 

115 summary=self.summary, 

116 props=self.props, 

117 ) 

118 return renderer.render() 

119 

120 

121__all__ = ["DataTable"]