dynamic dashboard initial

This commit is contained in:
2025-11-04 19:33:47 +01:00
parent 69e07056a1
commit ca623121a3
15 changed files with 1774 additions and 7 deletions

View File

@@ -1,11 +1,17 @@
"""UI main entry point."""
import logging
from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from apps.ui.api_client import fetch_devices, fetch_layout
logger = logging.getLogger(__name__)
# Initialize FastAPI app
app = FastAPI(
title="Home Automation UI",
@@ -17,18 +23,91 @@ app = FastAPI(
templates_dir = Path(__file__).parent / "templates"
templates = Jinja2Templates(directory=str(templates_dir))
# Setup static files
static_dir = Path(__file__).parent / "static"
static_dir.mkdir(exist_ok=True)
app.mount("/static", StaticFiles(directory=str(static_dir)), name="static")
@app.get("/", response_class=HTMLResponse)
async def index(request: Request) -> HTMLResponse:
"""Render the main UI page.
"""Redirect to dashboard.
Args:
request: The FastAPI request object
Returns:
HTMLResponse: Rendered HTML template
HTMLResponse: Rendered dashboard
"""
return templates.TemplateResponse("index.html", {"request": request})
return await dashboard(request)
@app.get("/dashboard", response_class=HTMLResponse)
async def dashboard(request: Request) -> HTMLResponse:
"""Render the dashboard with rooms and devices.
Args:
request: The FastAPI request object
Returns:
HTMLResponse: Rendered dashboard template
"""
try:
# Load layout from API
layout_data = fetch_layout()
# Fetch devices from API (now includes features)
api_devices = fetch_devices()
# Create device lookup by device_id
device_map = {d["device_id"]: d for d in api_devices}
# Build rooms with merged device data
rooms = []
for room in layout_data.get("rooms", []):
devices = []
for tile in room.get("devices", []):
# Merge tile data with API device data
device_data = {
"device_id": tile["device_id"],
"title": tile["title"],
"icon": tile["icon"],
"rank": tile["rank"],
}
# Add type, name, and features from API if available
if tile["device_id"] in device_map:
api_device = device_map[tile["device_id"]]
device_data["type"] = api_device.get("type")
device_data["name"] = api_device.get("name")
device_data["features"] = api_device.get("features", {})
else:
device_data["features"] = {}
devices.append(device_data)
# Sort devices by rank (ascending)
devices.sort(key=lambda d: d["rank"])
rooms.append({
"name": room["name"],
"devices": devices
})
logger.info(f"Rendering dashboard with {len(rooms)} rooms")
return templates.TemplateResponse("dashboard.html", {
"request": request,
"rooms": rooms
})
except Exception as e:
logger.error(f"Error rendering dashboard: {e}", exc_info=True)
# Fallback to empty dashboard
return templates.TemplateResponse("dashboard.html", {
"request": request,
"rooms": []
})
def main() -> None: