""" Partial routes for HTMX dynamic content loading. These routes return HTML fragments that are loaded into the page via HTMX. """ from fastapi import APIRouter, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates from app.seismo.services.snapshot import emit_status_snapshot router = APIRouter() templates = Jinja2Templates(directory="app/ui/templates") @router.get("/unknown-emitters", response_class=HTMLResponse) async def get_unknown_emitters(request: Request): """ Returns HTML partial with unknown emitters (units reporting but not in roster). Called periodically via HTMX (every 10s) from the roster page. """ snapshot = emit_status_snapshot() # Convert unknown units dict to list and add required fields unknown_list = [] for unit_id, unit_data in snapshot.get("unknown", {}).items(): unknown_list.append({ "id": unit_id, "status": unit_data["status"], "age": unit_data["age"], "fname": unit_data.get("fname", ""), }) # Sort by ID for consistent display unknown_list.sort(key=lambda x: x["id"]) return templates.TemplateResponse( "partials/unknown_emitters.html", { "request": request, "unknown_units": unknown_list } ) @router.get("/devices-all", response_class=HTMLResponse) async def get_all_devices(request: Request): """ Returns HTML partial with all devices (deployed, benched, retired, ignored). Called on page load and when filters are applied. """ snapshot = emit_status_snapshot() # Combine all units from different buckets all_units = [] # Add active units (deployed) for unit_id, unit_data in snapshot.get("active", {}).items(): unit_info = { "id": unit_id, "status": unit_data["status"], "age": unit_data["age"], "last_seen": unit_data.get("last", ""), "fname": unit_data.get("fname", ""), "deployed": True, "retired": False, "ignored": False, "note": unit_data.get("note", ""), "device_type": unit_data.get("device_type", "seismograph"), "location": unit_data.get("location", ""), "address": unit_data.get("address", ""), "coordinates": unit_data.get("coordinates", ""), "last_calibrated": unit_data.get("last_calibrated"), "next_calibration_due": unit_data.get("next_calibration_due"), "deployed_with_modem_id": unit_data.get("deployed_with_modem_id"), "ip_address": unit_data.get("ip_address"), "phone_number": unit_data.get("phone_number"), "hardware_model": unit_data.get("hardware_model"), } all_units.append(unit_info) # Add benched units (not deployed, not retired) for unit_id, unit_data in snapshot.get("benched", {}).items(): unit_info = { "id": unit_id, "status": unit_data["status"], "age": unit_data["age"], "last_seen": unit_data.get("last", ""), "fname": unit_data.get("fname", ""), "deployed": False, "retired": False, "ignored": False, "note": unit_data.get("note", ""), "device_type": unit_data.get("device_type", "seismograph"), "location": unit_data.get("location", ""), "address": unit_data.get("address", ""), "coordinates": unit_data.get("coordinates", ""), "last_calibrated": unit_data.get("last_calibrated"), "next_calibration_due": unit_data.get("next_calibration_due"), "deployed_with_modem_id": unit_data.get("deployed_with_modem_id"), "ip_address": unit_data.get("ip_address"), "phone_number": unit_data.get("phone_number"), "hardware_model": unit_data.get("hardware_model"), } all_units.append(unit_info) # Add retired units for unit_id, unit_data in snapshot.get("retired", {}).items(): unit_info = { "id": unit_id, "status": "Retired", "age": unit_data["age"], "last_seen": unit_data.get("last", ""), "fname": unit_data.get("fname", ""), "deployed": False, "retired": True, "ignored": False, "note": unit_data.get("note", ""), "device_type": unit_data.get("device_type", "seismograph"), "location": unit_data.get("location", ""), "address": unit_data.get("address", ""), "coordinates": unit_data.get("coordinates", ""), "last_calibrated": unit_data.get("last_calibrated"), "next_calibration_due": unit_data.get("next_calibration_due"), "deployed_with_modem_id": unit_data.get("deployed_with_modem_id"), "ip_address": unit_data.get("ip_address"), "phone_number": unit_data.get("phone_number"), "hardware_model": unit_data.get("hardware_model"), } all_units.append(unit_info) # Sort by ID for consistent display all_units.sort(key=lambda x: x["id"]) return templates.TemplateResponse( "partials/devices_table.html", { "request": request, "units": all_units } )