seismo fleet roster repaired and visible.
This commit is contained in:
@@ -34,6 +34,7 @@ from app.seismo.routers import (
|
||||
activity as seismo_activity,
|
||||
seismo_dashboard as seismo_seismo_dashboard,
|
||||
settings as seismo_settings,
|
||||
partials as seismo_partials,
|
||||
)
|
||||
from app.seismo import routes as seismo_legacy_routes
|
||||
|
||||
@@ -104,6 +105,7 @@ app.include_router(seismo_dashboard_tabs.router)
|
||||
app.include_router(seismo_activity.router)
|
||||
app.include_router(seismo_seismo_dashboard.router)
|
||||
app.include_router(seismo_settings.router)
|
||||
app.include_router(seismo_partials.router, prefix="/partials")
|
||||
app.include_router(seismo_legacy_routes.router)
|
||||
|
||||
# SLM Feature Module APIs
|
||||
|
||||
140
app/seismo/routers/partials.py
Normal file
140
app/seismo/routers/partials.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""
|
||||
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
|
||||
}
|
||||
)
|
||||
@@ -11,7 +11,7 @@ from app.seismo.database import get_db
|
||||
from app.seismo.models import RosterUnit
|
||||
|
||||
router = APIRouter(prefix="/api/seismo-dashboard", tags=["seismo-dashboard"])
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
templates = Jinja2Templates(directory="app/ui/templates")
|
||||
|
||||
|
||||
@router.get("/stats", response_class=HTMLResponse)
|
||||
|
||||
Reference in New Issue
Block a user