diff --git a/backend/requirements.txt b/backend/requirements.txt index 8f02d27..3c16605 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -13,4 +13,5 @@ black isort huggingface_hub datasets -transformers \ No newline at end of file +transformers +pydantic[email] \ No newline at end of file diff --git a/dashboard/app.js b/dashboard/app.js index 1669f72..797992e 100644 --- a/dashboard/app.js +++ b/dashboard/app.js @@ -320,6 +320,25 @@ function App(){ window.open(`https://www.google.com/maps/search/?api=1&query=${lat},${lng}`, '_blank'); }; + const navigateToLocation = (r) => { + const map = mapRef.current; + if (!map || !r.location) return; + + const { lat, lng } = r.location; + const currentZoom = map.getZoom(); + const targetZoom = 20; // Maximum zoom level for focusing on a specific location + + // First zoom out a bit for animation effect, then zoom to target + map.flyTo([lat, lng], targetZoom, { + animate: true, + duration: 1.5, + easeLinearity: 0.25 + }); + + // Also set the selected item to show details + setSelected(r); + }; + return (
@@ -411,7 +430,13 @@ function App(){
{t(`category.${r.category}`) || r.category}
-
{t(`category.${r.category}`) || r.category}
+
navigateToLocation(r)} + title="Click to view on map" + > + {t(`category.${r.category}`) || r.category} +
{t(`severity.${r.severity}`) || r.severity} {t(`status.${r.status}`) || r.status} diff --git a/dashboard/styles.css b/dashboard/styles.css index 9b8673b..4019d6a 100644 --- a/dashboard/styles.css +++ b/dashboard/styles.css @@ -120,6 +120,19 @@ button.chip[aria-pressed="false"]{opacity:0.55;filter:grayscale(0.15)} .thumb{width:56px;height:56px;border-radius:6px;background:linear-gradient(180deg,#eef2ff,#fff);display:flex;align-items:center;justify-content:center;color:#0f172a;font-weight:700} .item-main{flex:1;min-width:0} .item-title{font-weight:600;text-overflow:ellipsis;overflow:hidden;white-space:nowrap} +.item-title.clickable{ + cursor:pointer; + transition:all 0.2s ease; + border-radius:4px; + padding:2px 4px; + margin:-2px -4px; +} +.item-title.clickable:hover{ + background-color:rgba(14,165,164,0.1); + color:var(--accent); + transform:translateY(-1px); + box-shadow:0 2px 8px rgba(14,165,164,0.15); +} .item-meta{display:flex;gap:8px;align-items:center;margin-top:6px;font-size:12px;color:var(--muted)} .item-actions{display:flex;align-items:center}