v1.4.0: модули с веб-UI, правое меню, расширенные тесты
Реестр MODULE_MOUNTS: API, ui_router, фрагменты главной, EventBus. Главная и страницы модулей с правой навигацией из реестра; wrap_module_html_page. Ingress: публикация alert.received после сохранения в БД. Документация MODULES.md; pytest покрывает API, UI и навигацию. Made-with: Cursor
This commit is contained in:
71
onguard24/modules/registry.py
Normal file
71
onguard24/modules/registry.py
Normal file
@ -0,0 +1,71 @@
|
||||
"""Единая точка регистрации модулей: API, веб-UI и подписки на события.
|
||||
|
||||
Новый модуль: файл в `onguard24/modules/`, запись в `MODULE_MOUNTS` — см. docs/MODULES.md.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import APIRouter
|
||||
from starlette.requests import Request
|
||||
|
||||
from onguard24.domain.events import EventBus
|
||||
from onguard24.modules import contacts, schedules, statusboard
|
||||
|
||||
# async (Request) -> str — фрагмент HTML для главной страницы (опционально)
|
||||
HomeFragment = Callable[[Request], Awaitable[str]]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ModuleMount:
|
||||
"""Один модуль: API под url_prefix, UI под /ui/modules/{slug}."""
|
||||
|
||||
router: APIRouter
|
||||
url_prefix: str
|
||||
register_events: Callable[[EventBus], None]
|
||||
slug: str
|
||||
title: str
|
||||
ui_router: APIRouter | None = None
|
||||
render_home_fragment: HomeFragment | None = None
|
||||
|
||||
|
||||
def _mounts() -> list[ModuleMount]:
|
||||
return [
|
||||
ModuleMount(
|
||||
router=schedules.router,
|
||||
url_prefix="/api/v1/modules/schedules",
|
||||
register_events=schedules.register_events,
|
||||
slug="schedules",
|
||||
title="Календарь дежурств",
|
||||
ui_router=schedules.ui_router,
|
||||
render_home_fragment=schedules.render_home_fragment,
|
||||
),
|
||||
ModuleMount(
|
||||
router=contacts.router,
|
||||
url_prefix="/api/v1/modules/contacts",
|
||||
register_events=contacts.register_events,
|
||||
slug="contacts",
|
||||
title="Контакты",
|
||||
ui_router=contacts.ui_router,
|
||||
render_home_fragment=contacts.render_home_fragment,
|
||||
),
|
||||
ModuleMount(
|
||||
router=statusboard.router,
|
||||
url_prefix="/api/v1/modules/statusboard",
|
||||
register_events=statusboard.register_events,
|
||||
slug="statusboard",
|
||||
title="Светофор",
|
||||
ui_router=statusboard.ui_router,
|
||||
render_home_fragment=statusboard.render_home_fragment,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
MODULE_MOUNTS: list[ModuleMount] = _mounts()
|
||||
|
||||
|
||||
def register_module_events(bus: EventBus) -> None:
|
||||
for m in MODULE_MOUNTS:
|
||||
m.register_events(bus)
|
||||
Reference in New Issue
Block a user