refactor: Clean checkin override parsing and require node type in frontend configuration modal
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone, timedelta
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
from app.config import settings
|
from app.config import settings
|
||||||
@@ -117,14 +117,17 @@ class MQTTHandler:
|
|||||||
# Approved but not yet configured — restore reachable status after reboot
|
# Approved but not yet configured — restore reachable status after reboot
|
||||||
updates["status"] = "unconfigured"
|
updates["status"] = "unconfigured"
|
||||||
|
|
||||||
node_type = payload.get("node_type", existing.get("node_type", "fixed"))
|
node_type = payload.get("node_type") or existing.get("node_type") or "fixed"
|
||||||
enforce_timeout = payload.get("enforce_override_timeout", existing.get("enforce_override_timeout", True))
|
enforce_timeout = payload.get("enforce_override_timeout")
|
||||||
is_overridden = payload.get("is_overridden", False)
|
if enforce_timeout is None:
|
||||||
override_system_id = payload.get("override_system_id")
|
enforce_timeout = existing.get("enforce_override_timeout", True)
|
||||||
|
|
||||||
updates["node_type"] = node_type
|
updates["node_type"] = node_type
|
||||||
updates["enforce_override_timeout"] = enforce_timeout
|
updates["enforce_override_timeout"] = enforce_timeout
|
||||||
|
|
||||||
|
is_overridden = payload.get("is_overridden", False)
|
||||||
|
override_system_id = payload.get("override_system_id")
|
||||||
|
|
||||||
if node_type == "portable":
|
if node_type == "portable":
|
||||||
updates["is_overridden"] = False
|
updates["is_overridden"] = False
|
||||||
updates["override_system_id"] = None
|
updates["override_system_id"] = None
|
||||||
@@ -138,7 +141,6 @@ class MQTTHandler:
|
|||||||
existing_override_id = existing.get("override_system_id")
|
existing_override_id = existing.get("override_system_id")
|
||||||
if enforce_timeout:
|
if enforce_timeout:
|
||||||
if not existing_timeout or existing_override_id != override_system_id:
|
if not existing_timeout or existing_override_id != override_system_id:
|
||||||
from datetime import timedelta
|
|
||||||
updates["override_timeout_at"] = (now + timedelta(hours=24)).isoformat()
|
updates["override_timeout_at"] = (now + timedelta(hours=24)).isoformat()
|
||||||
else:
|
else:
|
||||||
updates["override_timeout_at"] = None
|
updates["override_timeout_at"] = None
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export function NodeConfigModal({ node, systems, onClose }: Props) {
|
|||||||
const [systemId, setSystemId] = useState(node.assigned_system_id ?? "");
|
const [systemId, setSystemId] = useState(node.assigned_system_id ?? "");
|
||||||
const [preset, setPreset] = useState(node.hardware_preset ?? "rtl-sdr-v3");
|
const [preset, setPreset] = useState(node.hardware_preset ?? "rtl-sdr-v3");
|
||||||
const [ppm, setPpm] = useState(node.ppm_override ? String(node.ppm_override) : "0");
|
const [ppm, setPpm] = useState(node.ppm_override ? String(node.ppm_override) : "0");
|
||||||
const [nodeType, setNodeType] = useState(node.node_type ?? "fixed");
|
const [nodeType, setNodeType] = useState(node.node_type ?? "");
|
||||||
const [enforceTimeout, setEnforceTimeout] = useState(node.enforce_override_timeout ?? true);
|
const [enforceTimeout, setEnforceTimeout] = useState(node.enforce_override_timeout ?? true);
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
@@ -107,12 +107,14 @@ export function NodeConfigModal({ node, systems, onClose }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs text-gray-400 mb-1">Node Type</label>
|
<label className="block text-xs text-gray-400 mb-1">Node Type *</label>
|
||||||
<select
|
<select
|
||||||
value={nodeType}
|
value={nodeType}
|
||||||
onChange={(e) => setNodeType(e.target.value)}
|
onChange={(e) => setNodeType(e.target.value)}
|
||||||
className="w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-indigo-500"
|
className="w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-indigo-500"
|
||||||
|
required
|
||||||
>
|
>
|
||||||
|
<option value="">Select node type...</option>
|
||||||
<option value="fixed">Fixed Node (Standard)</option>
|
<option value="fixed">Fixed Node (Standard)</option>
|
||||||
<option value="portable">Portable Node (Handheld)</option>
|
<option value="portable">Portable Node (Handheld)</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -138,7 +140,7 @@ export function NodeConfigModal({ node, systems, onClose }: Props) {
|
|||||||
<div className="flex gap-3 pt-1">
|
<div className="flex gap-3 pt-1">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={saving || !systemId}
|
disabled={saving || !systemId || !nodeType}
|
||||||
className="flex-1 bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white rounded-lg py-2 text-sm font-semibold transition-colors"
|
className="flex-1 bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white rounded-lg py-2 text-sm font-semibold transition-colors"
|
||||||
>
|
>
|
||||||
{saving ? "Saving…" : "Assign & Configure"}
|
{saving ? "Saving…" : "Assign & Configure"}
|
||||||
|
|||||||
Reference in New Issue
Block a user