Coverage for src / lexigram / ui / molecules / realtime.py: 34%
29 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-10 04:11 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-10 04:11 +0800
1"""Real-time UI components for Lexigram Admin."""
3from __future__ import annotations
5from typing import Any
7from lexigram.ui.core.base import Component, el
8from lexigram.ui.htmx.attrs import hx_get, hx_swap, hx_target, hx_trigger
11class RealTimeFeed(Component):
12 """A component that polls or uses SSE to update its content in real-time.
14 Example:
15 ```python
16 feed = RealTimeFeed(
17 url="/admin//updates",
18 interval="5s",
19 content=el("p", "Waiting for updates...")
20 )
21 ```
22 """
24 def __init__(
25 self,
26 url: str,
27 interval: str | None = "10s",
28 use_sse: bool = False,
29 content: Any = None,
30 **props: Any,
31 ) -> None:
32 super().__init__(**props)
33 self.url = url
34 self.interval = interval
35 self.use_sse = use_sse
36 self.initial_content = content or el(
37 "div",
38 {"class": "animate-pulse h-4 bg-muted rounded w-3/4"},
39 )
41 def render(self) -> Any:
42 attrs = {
43 "class": "real-time-feed",
44 "id": self.props.get("id", "feed-" + str(id(self))),
45 }
47 if self.use_sse:
48 attrs.update(
49 {"hx-ext": "sse", "sse-connect": self.url, "sse-swap": "message"},
50 )
51 elif self.interval:
52 attrs.update(hx_get(self.url))
53 attrs.update(hx_trigger(f"every {self.interval}"))
54 attrs.update(hx_target("this"))
55 attrs.update(hx_swap("innerHTML"))
57 return el("div", attrs, self.initial_content)
60class LiveCounter(Component):
61 """A simple counter that updates in real-time."""
63 def __init__(self, label: str, url: str, interval: str = "5s", **props: Any):
64 super().__init__(**props)
65 self.label = label
66 self.url = url
67 self.interval = interval
69 def render(self) -> Any:
70 return el(
71 "div",
72 {
73 "class": "p-4 bg-card rounded-lg shadow sm:p-6 transition-colors duration-300",
74 },
75 el(
76 "dt",
77 {"class": "text-sm font-medium text-muted-foreground truncate"},
78 self.label,
79 ),
80 el(
81 "dd",
82 {"class": "mt-1 text-3xl font-semibold text-foreground"},
83 RealTimeFeed(url=self.url, interval=self.interval, content="--"),
84 ),
85 )