Backend (incident_correlator.py):
- Create path (line ~1274): title only uses "at {location}" when location_coords is also set
- Update path (line ~1226): same guard — best_coords must be truthy alongside best_location
Frontend (MapView.tsx):
- Desktop sidebar: cards with location_coords → <button> fly-to; cards without → <a href> that navigates to the incident page with "View details →" text
- Mobile drawer: same split — with coords fly-to+close, without coords navigate via <a>
- Removed the "no coords" italic placeholder text; the card behavior itself makes it clear
This commit is contained in:
@@ -1223,7 +1223,7 @@ async def _update_incident(
|
|||||||
talkgroup_name
|
talkgroup_name
|
||||||
or (f"TGID {talkgroup_id}" if talkgroup_id else inc.get("title", "").split(" — ")[-1])
|
or (f"TGID {talkgroup_id}" if talkgroup_id else inc.get("title", "").split(" — ")[-1])
|
||||||
)
|
)
|
||||||
if primary_tag and best_location and primary_tag.lower() != best_location.lower():
|
if primary_tag and best_location and best_coords and primary_tag.lower() != best_location.lower():
|
||||||
updates["title"] = f"{primary_tag} at {best_location}"
|
updates["title"] = f"{primary_tag} at {best_location}"
|
||||||
elif primary_tag and tg_label:
|
elif primary_tag and tg_label:
|
||||||
updates["title"] = f"{primary_tag} — {tg_label}"
|
updates["title"] = f"{primary_tag} — {tg_label}"
|
||||||
@@ -1271,7 +1271,7 @@ async def _create_incident(
|
|||||||
# Build a descriptive title from tags + location when available
|
# Build a descriptive title from tags + location when available
|
||||||
content_tags = [t for t in tags if t != "auto-generated"]
|
content_tags = [t for t in tags if t != "auto-generated"]
|
||||||
primary_tag = _tag_to_title(content_tags[0]) if content_tags else None
|
primary_tag = _tag_to_title(content_tags[0]) if content_tags else None
|
||||||
if primary_tag and location and primary_tag.lower() != location.lower():
|
if primary_tag and location and location_coords and primary_tag.lower() != location.lower():
|
||||||
title = f"{primary_tag} at {location}"
|
title = f"{primary_tag} at {location}"
|
||||||
elif primary_tag:
|
elif primary_tag:
|
||||||
title = f"{primary_tag} — {tg_label}"
|
title = f"{primary_tag} — {tg_label}"
|
||||||
|
|||||||
@@ -518,16 +518,9 @@ export default function MapView({ nodes, activeCalls, incidents = [], lastUpdate
|
|||||||
const color = INCIDENT_COLORS[inc.type ?? "other"] ?? INCIDENT_COLORS.other;
|
const color = INCIDENT_COLORS[inc.type ?? "other"] ?? INCIDENT_COLORS.other;
|
||||||
const age = inc.started_at ? timeAgo(new Date(inc.started_at)) : null;
|
const age = inc.started_at ? timeAgo(new Date(inc.started_at)) : null;
|
||||||
const unitCount = inc.units?.length ?? 0;
|
const unitCount = inc.units?.length ?? 0;
|
||||||
return (
|
const baseClass = "w-full text-left bg-gray-950/85 backdrop-blur-sm border rounded-lg px-3 py-2 text-xs font-mono hover:brightness-110 transition-all";
|
||||||
<div
|
const cardBody = (
|
||||||
key={inc.incident_id}
|
<>
|
||||||
className="w-full text-left bg-gray-950/85 backdrop-blur-sm border rounded-lg px-3 py-2 text-xs font-mono hover:brightness-110 transition-all"
|
|
||||||
style={{ borderColor: color + "55" }}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
onClick={() => handleIncidentSelect(inc)}
|
|
||||||
className="w-full text-left"
|
|
||||||
>
|
|
||||||
<div className="flex items-center gap-1.5 mb-0.5">
|
<div className="flex items-center gap-1.5 mb-0.5">
|
||||||
<span
|
<span
|
||||||
className="inline-block w-2 h-2 rounded-sm flex-shrink-0"
|
className="inline-block w-2 h-2 rounded-sm flex-shrink-0"
|
||||||
@@ -553,16 +546,31 @@ export default function MapView({ nodes, activeCalls, incidents = [], lastUpdate
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!inc.location_coords && (
|
{!inc.location_coords && (
|
||||||
<p className="text-gray-700 italic mt-0.5">no coords</p>
|
<p className="text-[10px] text-blue-700 mt-1">View details →</p>
|
||||||
)}
|
)}
|
||||||
</button>
|
</>
|
||||||
<a
|
);
|
||||||
href={`/incidents/${inc.incident_id}`}
|
if (inc.location_coords) {
|
||||||
className="block text-[10px] text-blue-700 hover:text-blue-500 mt-1 transition-colors"
|
return (
|
||||||
|
<button
|
||||||
|
key={inc.incident_id}
|
||||||
|
onClick={() => handleIncidentSelect(inc)}
|
||||||
|
className={baseClass}
|
||||||
|
style={{ borderColor: color + "55" }}
|
||||||
>
|
>
|
||||||
View details →
|
{cardBody}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
key={inc.incident_id}
|
||||||
|
href={`/incidents/${inc.incident_id}`}
|
||||||
|
className={`block ${baseClass}`}
|
||||||
|
style={{ borderColor: color + "55" }}
|
||||||
|
>
|
||||||
|
{cardBody}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@@ -580,6 +588,16 @@ export default function MapView({ nodes, activeCalls, incidents = [], lastUpdate
|
|||||||
<div className="bg-gray-950/95 border-t border-gray-800 max-h-52 overflow-y-auto px-3 py-2 space-y-1.5">
|
<div className="bg-gray-950/95 border-t border-gray-800 max-h-52 overflow-y-auto px-3 py-2 space-y-1.5">
|
||||||
{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;
|
||||||
|
const label = (
|
||||||
|
<>
|
||||||
|
<span className="font-semibold" style={{ color }}>
|
||||||
|
{inc.type ?? "other"}
|
||||||
|
</span>
|
||||||
|
{" — "}
|
||||||
|
<span className="text-white">{inc.title ?? "Incident"}</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
if (inc.location_coords) {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={inc.incident_id}
|
key={inc.incident_id}
|
||||||
@@ -590,13 +608,20 @@ export default function MapView({ nodes, activeCalls, incidents = [], lastUpdate
|
|||||||
className="w-full text-left border rounded px-2 py-1.5 text-xs font-mono"
|
className="w-full text-left border rounded px-2 py-1.5 text-xs font-mono"
|
||||||
style={{ borderColor: color + "55" }}
|
style={{ borderColor: color + "55" }}
|
||||||
>
|
>
|
||||||
<span className="font-semibold" style={{ color }}>
|
{label}
|
||||||
{inc.type ?? "other"}
|
|
||||||
</span>
|
|
||||||
{" — "}
|
|
||||||
<span className="text-white">{inc.title ?? "Incident"}</span>
|
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
key={inc.incident_id}
|
||||||
|
href={`/incidents/${inc.incident_id}`}
|
||||||
|
className="block w-full text-left border rounded px-2 py-1.5 text-xs font-mono"
|
||||||
|
style={{ borderColor: color + "55" }}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user