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:
@@ -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:
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
Reference in New Issue
Block a user