feat: add in-line quick editing for seismograph details (cal date, notes, deployment status)

This commit is contained in:
2026-03-26 06:10:03 +00:00
parent 64d4423308
commit d135727ebd
4 changed files with 266 additions and 85 deletions

View File

@@ -3,13 +3,13 @@ Seismograph Dashboard API Router
Provides endpoints for the seismograph-specific dashboard
"""
from datetime import date
from datetime import date, datetime, timedelta
from fastapi import APIRouter, Request, Depends, Query
from fastapi import APIRouter, Request, Depends, Query, Form, HTTPException
from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session
from backend.database import get_db
from backend.models import RosterUnit
from backend.models import RosterUnit, UnitHistory, UserPreferences
from backend.templates_config import templates
router = APIRouter(prefix="/api/seismo-dashboard", tags=["seismo-dashboard"])
@@ -120,3 +120,109 @@ async def get_seismo_units(
"today": date.today()
}
)
def _get_calibration_interval(db: Session) -> int:
prefs = db.query(UserPreferences).first()
if prefs and prefs.calibration_interval_days:
return prefs.calibration_interval_days
return 365
def _row_context(request: Request, unit: RosterUnit) -> dict:
return {"request": request, "unit": unit, "today": date.today()}
@router.get("/unit/{unit_id}/view-row", response_class=HTMLResponse)
async def get_seismo_view_row(unit_id: str, request: Request, db: Session = Depends(get_db)):
unit = db.query(RosterUnit).filter(RosterUnit.id == unit_id).first()
if not unit:
raise HTTPException(status_code=404, detail="Unit not found")
return templates.TemplateResponse("partials/seismo_row_view.html", _row_context(request, unit))
@router.get("/unit/{unit_id}/edit-row", response_class=HTMLResponse)
async def get_seismo_edit_row(unit_id: str, request: Request, db: Session = Depends(get_db)):
unit = db.query(RosterUnit).filter(RosterUnit.id == unit_id).first()
if not unit:
raise HTTPException(status_code=404, detail="Unit not found")
return templates.TemplateResponse("partials/seismo_row_edit.html", _row_context(request, unit))
@router.post("/unit/{unit_id}/quick-update", response_class=HTMLResponse)
async def quick_update_seismo_unit(
unit_id: str,
request: Request,
db: Session = Depends(get_db),
status: str = Form(...),
last_calibrated: str = Form(""),
note: str = Form(""),
):
unit = db.query(RosterUnit).filter(RosterUnit.id == unit_id).first()
if not unit:
raise HTTPException(status_code=404, detail="Unit not found")
# --- Status ---
old_deployed = unit.deployed
old_out_for_cal = unit.out_for_calibration
if status == "deployed":
unit.deployed = True
unit.out_for_calibration = False
elif status == "out_for_calibration":
unit.deployed = False
unit.out_for_calibration = True
else:
unit.deployed = False
unit.out_for_calibration = False
if unit.deployed != old_deployed or unit.out_for_calibration != old_out_for_cal:
old_status = "deployed" if old_deployed else ("out_for_calibration" if old_out_for_cal else "benched")
db.add(UnitHistory(
unit_id=unit_id,
change_type="deployed_change",
field_name="status",
old_value=old_status,
new_value=status,
source="manual",
))
# --- Last calibrated ---
old_cal = unit.last_calibrated
if last_calibrated:
try:
new_cal = datetime.strptime(last_calibrated, "%Y-%m-%d").date()
except ValueError:
raise HTTPException(status_code=400, detail="Invalid date format. Use YYYY-MM-DD")
unit.last_calibrated = new_cal
unit.next_calibration_due = new_cal + timedelta(days=_get_calibration_interval(db))
else:
unit.last_calibrated = None
unit.next_calibration_due = None
if unit.last_calibrated != old_cal:
db.add(UnitHistory(
unit_id=unit_id,
change_type="calibration_status_change",
field_name="last_calibrated",
old_value=old_cal.strftime("%Y-%m-%d") if old_cal else None,
new_value=last_calibrated or None,
source="manual",
))
# --- Note ---
old_note = unit.note
unit.note = note or None
if unit.note != old_note:
db.add(UnitHistory(
unit_id=unit_id,
change_type="note_change",
field_name="note",
old_value=old_note,
new_value=unit.note,
source="manual",
))
db.commit()
db.refresh(unit)
return templates.TemplateResponse("partials/seismo_row_view.html", _row_context(request, unit))