feat: portal-wide device selector — session-based, all pages now use selected device
- _portal_device_id() reads from session, falls back to DEVICE_NAME env var - GET/POST /api/v1/portal/select-device for selector data + set - Dropdown in server base.html topbar, JS populates from API, page reloads on change - All portal pages (overview, trips, dashcam, DTC, device settings) now use selected device
This commit is contained in:
+46
-1
@@ -74,12 +74,57 @@ login_manager.init_app(app)
|
||||
|
||||
|
||||
def _portal_device_id():
|
||||
"""Return the device id for the configured device name (single Pi setup)."""
|
||||
"""Return the device id for the user's selected device, falling back to
|
||||
the DEVICE_NAME env var default. Selection is stored in the Flask session
|
||||
so it persists across pages without a URL parameter on every link."""
|
||||
# Check session first (user explicitly picked a device)
|
||||
session_id = session.get("selected_device_id")
|
||||
if session_id is not None:
|
||||
dev = db.get_device_by_id(session_id)
|
||||
if dev is not None:
|
||||
return dev["id"]
|
||||
# Selected device was deleted — clear stale session entry
|
||||
session.pop("selected_device_id", None)
|
||||
# Fall back to configured default
|
||||
name = os.environ.get("DEVICE_NAME", "yaris-2013")
|
||||
dev = db.get_device_by_name(name)
|
||||
return dev["id"] if dev else None
|
||||
|
||||
|
||||
@app.get("/api/v1/portal/select-device")
|
||||
@require_login
|
||||
def portal_select_device_state():
|
||||
"""Return current selection and available devices for the dropdown."""
|
||||
devices = device_registry.list_devices()
|
||||
configured_name = os.environ.get("DEVICE_NAME", "yaris-2013")
|
||||
for device in devices:
|
||||
device["portal_default"] = device["name"] == configured_name
|
||||
current_id = session.get("selected_device_id")
|
||||
return jsonify(
|
||||
devices=devices,
|
||||
selected_device_id=current_id,
|
||||
configured_device_name=configured_name,
|
||||
)
|
||||
|
||||
|
||||
@app.post("/api/v1/portal/select-device")
|
||||
@require_login
|
||||
def portal_select_device():
|
||||
"""Set the active device for the current session."""
|
||||
body = request.get_json(silent=True) or {}
|
||||
device_id = body.get("device_id")
|
||||
if device_id is None:
|
||||
session.pop("selected_device_id", None)
|
||||
session.pop("selected_device_name", None)
|
||||
return jsonify(status="ok", message="Device selection cleared.")
|
||||
dev = db.get_device_by_id(int(device_id))
|
||||
if dev is None:
|
||||
return jsonify(error="Device not found"), 404
|
||||
session["selected_device_id"] = dev["id"]
|
||||
session["selected_device_name"] = dev["device_name"] or dev["name"]
|
||||
return jsonify(status="ok", device_id=dev["id"], device_name=dev["device_name"] or dev["name"])
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health():
|
||||
"""Unauthenticated liveness check - used by docker-compose healthcheck
|
||||
|
||||
Reference in New Issue
Block a user