| from fastapi import APIRouter |
| from fastapi.responses import HTMLResponse, FileResponse |
| from pathlib import Path |
| from typing import Dict, List |
|
|
| from core.registry.tasks_registry import TASKS |
|
|
|
|
| |
| |
| |
|
|
| BASE_DIR = Path(__file__).resolve().parents[2] |
| UI_DIR = BASE_DIR / "ui" |
| INDEX_FILE = UI_DIR / "index.html" |
|
|
|
|
| |
| |
| |
|
|
| def group_tasks() -> Dict[str, List[dict]]: |
| """ |
| Converts registry → categorized UI structure. |
| """ |
|
|
| categories: Dict[str, List[dict]] = {} |
|
|
| for task in TASKS: |
| if not getattr(task, "enabled", True): |
| continue |
|
|
| category = getattr(task, "category", "general") |
|
|
| categories.setdefault(category, []).append( |
| { |
| "name": task.name, |
| "description": getattr(task, "description", ""), |
| } |
| ) |
|
|
| return categories |
|
|
|
|
| |
| |
| |
|
|
| def build_ui_router() -> APIRouter: |
| """ |
| Serves UI + dynamic UI metadata. |
| |
| Endpoints: |
| / |
| /ui |
| /ui/tasks |
| /ui/health |
| """ |
|
|
| router = APIRouter(tags=["UI"]) |
|
|
| |
| |
| |
| @router.get("/", response_class=HTMLResponse) |
| async def serve_root(): |
| """ |
| Serves index.html |
| """ |
|
|
| if not INDEX_FILE.exists(): |
| return HTMLResponse( |
| "<h1>Basyx UI Missing</h1>", |
| status_code=500, |
| ) |
|
|
| return FileResponse(INDEX_FILE) |
|
|
| |
| |
| |
| @router.get("/ui", response_class=HTMLResponse) |
| async def serve_ui(): |
| return await serve_root() |
|
|
| |
| |
| |
| @router.get("/ui/tasks") |
| async def ui_tasks(): |
| """ |
| UI fetches this to build sidebar dynamically. |
| """ |
| return group_tasks() |
|
|
| |
| |
| |
| @router.get("/ui/health") |
| async def ui_health(): |
| return { |
| "status": "ok", |
| "ui": "active", |
| "tasks": len(TASKS), |
| } |
|
|
| return router |