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
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-13 22:14 +0800
1"""Data table coordinator component."""
3from __future__ import annotations
5from typing import Any
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
14class DataTable(Component):
15 """
16 Main DataTable Coordinator.
17 Handles configuration, state management, and dispatches rendering to specific views.
18 """
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)
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 )
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 )
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
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()
95 # Configure actions
96 self.action_manager = ActionManager(self.config, self.permissions)
97 self.action_manager.configure_actions()
99 # Show delete based on permissions
100 self.show_delete = (
101 props.get("show_delete", True) and self.permissions["can_delete"]
102 )
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()
121__all__ = ["DataTable"]