Coverage for src / lexigram / admin / contributors / core.py: 60%
48 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"""Core admin contributor — built-in dashboard surfaces."""
3from __future__ import annotations
5from collections.abc import Sequence
6from typing import TYPE_CHECKING, cast
8from lexigram.admin.dashboard.chart_widget import ChartWidget
9from lexigram.contracts.admin.contributor import BaseAdminContributor
10from lexigram.contracts.admin.errors import AdminError, WidgetNotFoundError
11from lexigram.contracts.admin.types import (
12 AdminHealthDefinition,
13 DashboardWidgetDefinition,
14 NavigationContribution,
15 WidgetCategory,
16 WidgetParams,
17 WidgetSize,
18 WidgetViewModel,
19)
20from lexigram.contracts.core.result import Result
21from lexigram.result import Err, Ok
22from lexigram.ui import ChartConfig, ChartDataPoint, ChartType
24if TYPE_CHECKING:
25 from lexigram.contracts.core.di import ContainerResolverProtocol
28class CoreAdminContributor(BaseAdminContributor):
29 """Built-in contributor providing core dashboard surfaces.
31 Provides the framework health overview widget, the main dashboard
32 navigation entry, and the system-wide health check surface.
33 """
35 name = "core"
36 display_name = "Core"
37 group = "system"
38 icon = "layout-dashboard"
39 priority = 0
41 def __init__(self) -> None:
42 self._container: ContainerResolverProtocol | None = None
44 async def on_admin_boot(self, container: object) -> None:
45 self._container = container # type: ignore[assignment]
47 def get_dashboard_widgets(self) -> Sequence[DashboardWidgetDefinition]:
48 """Return core dashboard widgets: health overview, recent activity, and metrics."""
49 return [
50 DashboardWidgetDefinition(
51 name="health",
52 title="Framework Health",
53 contributor="core",
54 render_endpoint="/admin/core/widgets/health",
55 size=WidgetSize.FULL,
56 category=WidgetCategory.HEALTH,
57 refresh_interval_seconds=10,
58 order=0,
59 icon="heart-pulse",
60 description="Aggregated health status of all framework providers.",
61 ),
62 DashboardWidgetDefinition(
63 name="activity",
64 title="Recent Activity",
65 contributor="core",
66 render_endpoint="/admin/core/widgets/activity",
67 size=WidgetSize.LARGE,
68 category=WidgetCategory.ACTIVITY,
69 refresh_interval_seconds=15,
70 order=90,
71 icon="activity",
72 description="Recent admin operations and system events.",
73 ),
74 DashboardWidgetDefinition(
75 name="chart_metrics",
76 title="Framework Metrics",
77 contributor="core",
78 render_endpoint="/admin/core/widgets/chart_metrics",
79 size=WidgetSize.FULL,
80 category=WidgetCategory.METRICS,
81 refresh_interval_seconds=30,
82 order=50,
83 icon="bar-chart-3",
84 description="Key framework performance metrics visualized.",
85 ),
86 ]
88 def get_navigation_items(self) -> Sequence[NavigationContribution]:
89 """Return core navigation: Dashboard link."""
90 return [
91 NavigationContribution(
92 label="Dashboard",
93 url="/admin/",
94 icon="layout-dashboard",
95 group="",
96 order=0,
97 ),
98 ]
100 def get_health_definitions(self) -> Sequence[AdminHealthDefinition]:
101 """Return core health definitions."""
102 return [
103 AdminHealthDefinition(
104 name="admin_core",
105 contributor="core",
106 component="Admin Core",
107 check_endpoint="/admin/core/health/admin_core",
108 icon="shield-check",
109 description="Admin panel core services health.",
110 ),
111 ]
113 async def render_widget(
114 self,
115 widget_name: str,
116 params: WidgetParams,
117 resolver: ContainerResolverProtocol | None = None,
118 ) -> Result[WidgetViewModel, AdminError]:
119 """Render core widgets.
121 Args:
122 widget_name: Name of the widget to render.
123 params: Widget parameters.
125 Returns:
126 Result containing a WidgetViewModel with rendered HTML in ``body``,
127 or WidgetNotFoundError if the widget is not found.
128 """
130 if widget_name == "health":
131 return cast(
132 "Result[WidgetViewModel, AdminError]",
133 Ok(WidgetViewModel(body=self._render_health_widget())),
134 )
135 if widget_name == "activity":
136 return cast(
137 "Result[WidgetViewModel, AdminError]",
138 Ok(WidgetViewModel(body=self._render_activity_widget())),
139 )
140 if widget_name == "chart_metrics":
141 return cast(
142 "Result[WidgetViewModel, AdminError]",
143 Ok(WidgetViewModel(body=self._render_chart_metrics_widget())),
144 )
145 result: Result[WidgetViewModel, AdminError] = cast(
146 "Result[WidgetViewModel, AdminError]",
147 Err(WidgetNotFoundError(self.name, widget_name)),
148 )
149 return result
151 def _render_health_widget(self) -> str:
152 """Render the framework health widget."""
153 return '<div class="widget framework-health"><div class="status healthy"><span class="indicator"></span>Healthy</div></div>'
155 def _render_activity_widget(self) -> str:
156 """Render the recent activity widget."""
157 return '<div class="widget recent-activity"><ul class="activity-list"><li class="activity-item">No recent activity</li></ul></div>'
159 def _render_chart_metrics_widget(self) -> str:
160 """Render the framework metrics bar chart widget."""
161 data = [
162 ChartDataPoint(label="Active Users", value=847, color="blue"),
163 ChartDataPoint(label="Requests/min", value=2341, color="green"),
164 ChartDataPoint(label="Error Rate", value=1.2, color="red"),
165 ChartDataPoint(label="Avg Latency", value=45, color="amber"),
166 ChartDataPoint(label="Memory %", value=68, color="purple"),
167 ]
168 chart = ChartWidget(
169 title="Framework Metrics",
170 chart_type=ChartType.BAR,
171 data=data,
172 chart_config=ChartConfig(
173 show_grid=True,
174 show_labels=True,
175 animate=True,
176 height="200px",
177 ),
178 refresh_interval=30,
179 col_span=1,
180 )
181 return str(chart)
183 async def render_health_check(
184 self,
185 check_name: str,
186 ) -> Result[str, AdminError]:
187 """Render health check for admin core.
189 Args:
190 check_name: Name of the health check.
192 Returns:
193 Result with rendered HTML or error.
194 """
195 if check_name == "admin_core":
196 return cast(
197 "Result[str, AdminError]",
198 Ok(
199 '<div class="health-check admin-core"><span class="status healthy">Admin Core Operational</span></div>'
200 ),
201 )
202 return cast(
203 "Result[str, AdminError]",
204 Err(AdminError(f"Unknown health check: {check_name}")),
205 )
208__all__ = ["CoreAdminContributor"]