fix: map overlay clicks, layer overlap, fan spacing, geocoding radius

- Move incident panel to left side (was topright, conflicting with LayersControl)
- Move legend to bottom-right, raise auto-fit button to clear it
- Tighten fan card step 7→5px for closer grouping
- Geocoding: remove bounded=1 hard clip, widen bias radius 0.1°→0.5° (~55km)
  so addresses like "34 Carlton Drive" resolve outside the node's immediate area
This commit is contained in:
Logan
2026-05-24 00:20:11 -04:00
parent 4fc44dcc86
commit 1071bcd3e8
2 changed files with 9 additions and 9 deletions
+2 -2
View File
@@ -52,7 +52,7 @@ Talkgroup: {talkgroup_name}
{ten_codes_block}{vocabulary_block}{transcript_block}""" {ten_codes_block}{vocabulary_block}{transcript_block}"""
# Nominatim viewbox half-width in degrees (~11 km at mid-latitudes) # Nominatim viewbox half-width in degrees (~11 km at mid-latitudes)
_GEO_DELTA = 0.1 _GEO_DELTA = 0.5 # ~55 km bias radius; viewbox used as preference, not hard bound
# node_id → state abbreviation/name from one-time reverse geocode # node_id → state abbreviation/name from one-time reverse geocode
_node_state_cache: dict[str, str] = {} _node_state_cache: dict[str, str] = {}
@@ -231,7 +231,7 @@ async def _geocode_location(
"format": "json", "format": "json",
"limit": 1, "limit": 1,
"viewbox": viewbox, "viewbox": viewbox,
"bounded": 1, "bounded": 0, # viewbox biases results but doesn't hard-clip them
} }
headers = {"User-Agent": "DRB-Dispatch/1.0 (public-safety radio monitor)"} headers = {"User-Agent": "DRB-Dispatch/1.0 (public-safety radio monitor)"}
try: try:
+7 -7
View File
@@ -65,7 +65,7 @@ function incidentIcon(type: string | null): L.DivIcon {
function nodeFanIcon(members: NodeRecord[]): L.DivIcon { function nodeFanIcon(members: NodeRecord[]): L.DivIcon {
const n = members.length; const n = members.length;
const CARD = 13; const CARD = 13;
const STEP = 7; const STEP = 5;
const totalW = CARD + (n - 1) * STEP; const totalW = CARD + (n - 1) * STEP;
const maxRot = Math.min(28, n * 7); const maxRot = Math.min(28, n * 7);
const cards = members const cards = members
@@ -251,7 +251,7 @@ function FanIncidentLayer({
); );
const incById = useMemo( const incById = useMemo(
() => new Map(plotted.map((p) => [p.id, p.inc])), () => new Map(plotted.map((p: { id: string; lat: number; lng: number; inc: IncidentRecord }) => [p.id, p.inc])),
[plotted] [plotted]
); );
@@ -454,14 +454,14 @@ export default function MapView({ nodes, activeCalls, incidents = [], lastUpdate
<button <button
onClick={handleFitAll} onClick={handleFitAll}
title="Fit all markers in view" title="Fit all markers in view"
className="absolute bottom-[4.5rem] right-3 z-[1001] w-8 h-8 bg-gray-950/90 border border-gray-700 rounded text-white text-base leading-none hover:bg-gray-800 transition-colors flex items-center justify-center select-none" className="absolute bottom-[9.5rem] right-3 z-[1001] w-8 h-8 bg-gray-950/90 border border-gray-700 rounded text-white text-base leading-none hover:bg-gray-800 transition-colors flex items-center justify-center select-none"
> >
</button> </button>
)} )}
{/* ── Legend ──────────────────────────────────────────────────────────── */} {/* ── Legend — bottom-right to avoid incident panel on left ────────────── */}
<div className="absolute bottom-8 left-3 z-[1001] bg-gray-950/90 border border-gray-800 rounded-lg px-3 py-2 text-xs font-mono pointer-events-none space-y-1"> <div className="absolute bottom-8 right-3 z-[1001] bg-gray-950/90 border border-gray-800 rounded-lg px-3 py-2 text-xs font-mono pointer-events-none space-y-1">
<div className="flex items-center gap-2"><span className="text-green-400"></span> Online</div> <div className="flex items-center gap-2"><span className="text-green-400"></span> Online</div>
<div className="flex items-center gap-2"><span className="text-orange-400"></span> Recording</div> <div className="flex items-center gap-2"><span className="text-orange-400"></span> Recording</div>
<div className="flex items-center gap-2"><span className="text-indigo-400"></span> Unconfigured</div> <div className="flex items-center gap-2"><span className="text-indigo-400"></span> Unconfigured</div>
@@ -476,8 +476,8 @@ export default function MapView({ nodes, activeCalls, incidents = [], lastUpdate
{/* ── Incident overlay panel ───────────────────────────────────────────── */} {/* ── Incident overlay panel ───────────────────────────────────────────── */}
{incidents.length > 0 && ( {incidents.length > 0 && (
<> <>
{/* Desktop: right sidebar */} {/* Desktop: left sidebar — kept away from the LayersControl (topright) */}
<div className="absolute top-14 right-3 bottom-[4.5rem] z-[1001] hidden md:flex flex-col w-56 overflow-y-auto space-y-1.5"> <div className="absolute top-3 left-3 bottom-[4.5rem] z-[1001] hidden md:flex flex-col w-56 gap-1.5 overflow-y-auto">
{incidents.map((inc) => { {incidents.map((inc) => {
const color = INCIDENT_COLORS[inc.type ?? "other"] ?? INCIDENT_COLORS.other; const color = INCIDENT_COLORS[inc.type ?? "other"] ?? INCIDENT_COLORS.other;
return ( return (