fh-matui 0.9.8__py3-none-any.whl → 0.9.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fh_matui/__init__.py +1 -1
- fh_matui/datatable.py +56 -8
- {fh_matui-0.9.8.dist-info → fh_matui-0.9.9.dist-info}/METADATA +1 -1
- {fh_matui-0.9.8.dist-info → fh_matui-0.9.9.dist-info}/RECORD +8 -8
- {fh_matui-0.9.8.dist-info → fh_matui-0.9.9.dist-info}/WHEEL +0 -0
- {fh_matui-0.9.8.dist-info → fh_matui-0.9.9.dist-info}/entry_points.txt +0 -0
- {fh_matui-0.9.8.dist-info → fh_matui-0.9.9.dist-info}/licenses/LICENSE +0 -0
- {fh_matui-0.9.8.dist-info → fh_matui-0.9.9.dist-info}/top_level.txt +0 -0
fh_matui/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.9.
|
|
1
|
+
__version__ = "0.9.8"
|
fh_matui/datatable.py
CHANGED
|
@@ -22,10 +22,50 @@ from .components import *
|
|
|
22
22
|
from math import ceil
|
|
23
23
|
from urllib.parse import urlencode
|
|
24
24
|
from typing import Callable, Optional, Any
|
|
25
|
+
from dataclasses import asdict, is_dataclass
|
|
25
26
|
|
|
26
27
|
# Default page size options
|
|
27
28
|
PAGE_SIZES = [5, 10, 20, 50]
|
|
28
29
|
|
|
30
|
+
|
|
31
|
+
def _to_dict(obj: Any) -> dict:
|
|
32
|
+
"""
|
|
33
|
+
Convert any record type to dict.
|
|
34
|
+
|
|
35
|
+
Handles:
|
|
36
|
+
- dict -> pass through
|
|
37
|
+
- dataclass -> asdict()
|
|
38
|
+
- namedtuple -> _asdict()
|
|
39
|
+
- Pydantic model -> model_dump() or dict()
|
|
40
|
+
- ORM/object with __dict__ -> vars() filtered
|
|
41
|
+
- dict-like with keys -> dict()
|
|
42
|
+
- None -> {}
|
|
43
|
+
"""
|
|
44
|
+
if obj is None:
|
|
45
|
+
return {}
|
|
46
|
+
if isinstance(obj, dict):
|
|
47
|
+
return obj
|
|
48
|
+
# Dataclass
|
|
49
|
+
if is_dataclass(obj) and not isinstance(obj, type):
|
|
50
|
+
return asdict(obj)
|
|
51
|
+
# Namedtuple
|
|
52
|
+
if hasattr(obj, '_asdict'):
|
|
53
|
+
return obj._asdict()
|
|
54
|
+
# Pydantic v2
|
|
55
|
+
if hasattr(obj, 'model_dump'):
|
|
56
|
+
return obj.model_dump()
|
|
57
|
+
# Pydantic v1
|
|
58
|
+
if hasattr(obj, 'dict') and callable(getattr(obj, 'dict')):
|
|
59
|
+
return obj.dict()
|
|
60
|
+
# ORM-style objects with __dict__
|
|
61
|
+
if hasattr(obj, "__dict__"):
|
|
62
|
+
return {k: v for k, v in obj.__dict__.items() if not k.startswith("_")}
|
|
63
|
+
# Dict-like
|
|
64
|
+
if hasattr(obj, 'keys'):
|
|
65
|
+
return dict(obj)
|
|
66
|
+
return {}
|
|
67
|
+
|
|
68
|
+
|
|
29
69
|
def _safe_int(value, default):
|
|
30
70
|
"""Safely convert to positive int or return default."""
|
|
31
71
|
try:
|
|
@@ -173,6 +213,9 @@ def DataTable(
|
|
|
173
213
|
container_id = container_id or f"crud-table-{base_route.replace('/', '-').strip('-')}"
|
|
174
214
|
feedback_id = f"{container_id}-feedback"
|
|
175
215
|
|
|
216
|
+
# Auto-convert data records to dicts (supports dataclass, namedtuple, Pydantic, ORM)
|
|
217
|
+
data = [_to_dict(r) for r in data]
|
|
218
|
+
|
|
176
219
|
# Auto-generate columns from first data row if not provided
|
|
177
220
|
if columns is None and data:
|
|
178
221
|
columns = [{"key": k, "label": k.replace("_", " ").title()} for k in data[0].keys()]
|
|
@@ -279,22 +322,27 @@ def DataTable(
|
|
|
279
322
|
cls="field prefix"
|
|
280
323
|
),
|
|
281
324
|
Input(type="hidden", name="page_size", value=page_size),
|
|
282
|
-
cls="
|
|
325
|
+
cls="max"
|
|
283
326
|
)
|
|
284
327
|
|
|
328
|
+
# Build table with proper Thead/Tbody structure
|
|
329
|
+
data_table = Table(
|
|
330
|
+
Thead(Tr(*[Th(label) for label in header_labels])),
|
|
331
|
+
Tbody(*[
|
|
332
|
+
Tr(*[Td(row_dict.get(key, '')) for key in header_keys])
|
|
333
|
+
for row_dict in table_rows
|
|
334
|
+
]),
|
|
335
|
+
cls="border"
|
|
336
|
+
) if data else Div(empty_message, cls="center-align padding")
|
|
337
|
+
|
|
285
338
|
return Article(
|
|
286
339
|
Div(id=feedback_id), # Feedback container for modals/toasts
|
|
287
340
|
Div(
|
|
288
341
|
search_form,
|
|
289
342
|
create_button,
|
|
290
|
-
cls="
|
|
343
|
+
cls="row"
|
|
291
344
|
),
|
|
292
|
-
|
|
293
|
-
*table_rows,
|
|
294
|
-
headers=header_labels,
|
|
295
|
-
keys=header_keys,
|
|
296
|
-
cls="border"
|
|
297
|
-
) if data else Div(empty_message, cls="center-align padding"),
|
|
345
|
+
data_table,
|
|
298
346
|
Div(
|
|
299
347
|
Div(
|
|
300
348
|
_page_size_select(page_size, search, base_route, container_id, page_sizes),
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
fh_matui/__init__.py,sha256=
|
|
1
|
+
fh_matui/__init__.py,sha256=4eQCGJV2-GRHX8FlvA_4etK0E4LFj2or592J4aePZoA,23
|
|
2
2
|
fh_matui/_modidx.py,sha256=naHwPQ4kCo-5saE_uozmdPA881kp1gnqvKhmaG-Ya-4,23914
|
|
3
3
|
fh_matui/app_pages.py,sha256=Sn9-tgBpaPNbR-0nZtPLoSCmAWLOGB4UQ88IkFvzBRY,10361
|
|
4
4
|
fh_matui/components.py,sha256=KjdTHzWRXpVWBEIGskW1HfhjPpzRYzi6UA_yRjZyMWM,48254
|
|
5
5
|
fh_matui/core.py,sha256=xtVBN8CtC50ZJ4Iu7o-mUhaA87tWdnz8gBfKRk63Zhs,10680
|
|
6
|
-
fh_matui/datatable.py,sha256=
|
|
6
|
+
fh_matui/datatable.py,sha256=NNb6WvGZ0QY13md4itwYH4a9yKZrOdwcaDW7PGo-vQM,36558
|
|
7
7
|
fh_matui/foundations.py,sha256=b7PnObJpKN8ZAU9NzCm9xpfnHzFjjAROU7E2YvA_tj4,1820
|
|
8
8
|
fh_matui/web_pages.py,sha256=4mF-jpfVcZTVepfQ-aMGgIUp-nBp0YCkvcdsWhUYeaA,34879
|
|
9
|
-
fh_matui-0.9.
|
|
10
|
-
fh_matui-0.9.
|
|
11
|
-
fh_matui-0.9.
|
|
12
|
-
fh_matui-0.9.
|
|
13
|
-
fh_matui-0.9.
|
|
14
|
-
fh_matui-0.9.
|
|
9
|
+
fh_matui-0.9.9.dist-info/licenses/LICENSE,sha256=xV8xoN4VOL0uw9X8RSs2IMuD_Ss_a9yAbtGNeBWZwnw,11337
|
|
10
|
+
fh_matui-0.9.9.dist-info/METADATA,sha256=OGoxCFS3_qRnEJe2EkD-dMDl21lhYt5ecds1B6f5xpU,10490
|
|
11
|
+
fh_matui-0.9.9.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
12
|
+
fh_matui-0.9.9.dist-info/entry_points.txt,sha256=zn4CR4gNTiAAxbFsCxHAf2tQhtW29_YOffjbUTgeoWI,38
|
|
13
|
+
fh_matui-0.9.9.dist-info/top_level.txt,sha256=l80d5eoA2ZjqtPYwAorLMS5PiHxUxz3zKzxMJ41Xoso,9
|
|
14
|
+
fh_matui-0.9.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|