import html import json from starlette.requests import Request from onguard24.modules.registry import MODULE_MOUNTS from onguard24.modules.ui_support import APP_SHELL_CSS, nav_rail_html, safe_fragment from onguard24.status_snapshot import build def _row(name: str, value: object) -> str: label = html.escape(name) if value == "disabled": badge = 'не настроено' return f"{label}{badge}" if isinstance(value, dict): st = value.get("status", "?") if st == "ok": badge = 'OK' elif st == "reachable": badge = 'доступен' elif st == "error": badge = 'ошибка' else: badge = f'{html.escape(str(st))}' extra = {k: v for k, v in value.items() if k != "status"} detail_html = "" if extra: detail_html = ( f'
'
                f"{html.escape(json.dumps(extra, ensure_ascii=False, indent=2))}"
                f"
" ) return f"{label}{badge}{detail_html}" badge = html.escape(str(value)) return f"{label}{badge}" async def _module_sections_html(request: Request) -> str: """Блоки модулей на главной: фрагменты изолированы (ошибка одного не роняет страницу).""" blocks: list[str] = [] for m in MODULE_MOUNTS: title = html.escape(m.title) slug_e = html.escape(m.slug) full_url = f"/ui/modules/{m.slug}/" if m.render_home_fragment: inner = await safe_fragment(m.slug, m.render_home_fragment, request) else: inner = '

Превью не задано — откройте полный интерфейс.

' foot = "" if m.ui_router: foot = ( f'" ) blocks.append( f'
' f'

{title}

' f'
{inner}
' f"{foot}" f"
" ) grid = "".join(blocks) return ( '
' "

Модули

" f'
{grid}
' "
" ) async def render_root_page(request: Request) -> str: data = await build(request) rows = "" for key in ("database", "vault", "grafana", "forgejo"): if key in data: rows += _row(key, data[key]) payload = html.escape(json.dumps(data, ensure_ascii=False, indent=2)) modules_html = await _module_sections_html(request) rail = nav_rail_html(None) return f""" onGuard24

onGuard24

Проверки доступа

{rows}
{modules_html}

Полный ответ /api/v1/status

{payload}
{rail}
"""