diff --git a/dashboard/app.js b/dashboard/app.js
index 2e10fc32..bdb21651 100644
--- a/dashboard/app.js
+++ b/dashboard/app.js
@@ -817,11 +817,11 @@ function openDrawer(id) { const i = STATE.digest.incidents.find((x) => x.incide
Original source records (${i.source_links.length})
` : `No deep links available for this incident.
`}
${(i.logs && i.logs.length) ? `Timeline · ${i.logs.length} log(s)
diff --git a/scripts/generate_dashboard_data.py b/scripts/generate_dashboard_data.py
index 1328234b..0abbed4e 100644
--- a/scripts/generate_dashboard_data.py
+++ b/scripts/generate_dashboard_data.py
@@ -345,6 +345,41 @@ def _resolve_region(name: str, latest_summary: str | None, is_disease: bool) ->
return "Global" if is_disease else "Unknown"
+_GDACS_EVENTTYPE_CODES = {
+ "Tropical Cyclone": "TC",
+ "Earthquake": "EQ",
+ "Flood": "FL",
+ "Forest Fire": "WF",
+ "Drought": "DR",
+ "Tsunami": "TS",
+ "Volcano": "VO",
+}
+
+
+def _resolve_gdacs_link(
+ raw_fields: dict[str, object],
+ source_id: str,
+ incident_type: str,
+) -> str:
+ link = raw_fields.get("link", "")
+ if link:
+ return str(link)
+ url = raw_fields.get("url")
+ if isinstance(url, dict):
+ report = url.get("report", "")
+ if report:
+ return str(report)
+ eventid = str(raw_fields.get("eventid") or source_id or "")
+ episodeid = str(raw_fields.get("episodeid") or "")
+ eventtype = _GDACS_EVENTTYPE_CODES.get(incident_type, "")
+ if eventid and episodeid and eventtype:
+ return (
+ f"https://www.gdacs.org/report.aspx?eventid={eventid}"
+ f"&episodeid={episodeid}&eventtype={eventtype}"
+ )
+ return ""
+
+
def build_incident_object(store: ContentStore, inc: dict, as_of_date: datetime) -> dict | None:
incident_id = inc["incident_id"]
reports = load_reports_for_incident(store, incident_id)
@@ -491,7 +526,7 @@ def build_incident_object(store: ContentStore, inc: dict, as_of_date: datetime)
source_links.append({
"type": "GDACS",
"label": f"{alert_label} · {rf.get('severitytext', r['name'])}" if alert_label else r["name"],
- "url": rf.get("link", ""),
+ "url": _resolve_gdacs_link(rf, r["source_id"], r["incident_type"]),
"meta": " · ".join(meta_parts) if meta_parts else "",
})
elif r["source"] == "WHO":
diff --git a/tests/integration/generate_dashboard_data_test.py b/tests/integration/generate_dashboard_data_test.py
index 31b8f17f..69925ff4 100644
--- a/tests/integration/generate_dashboard_data_test.py
+++ b/tests/integration/generate_dashboard_data_test.py
@@ -2,7 +2,7 @@
from datetime import datetime, timezone
-from scripts.generate_dashboard_data import _resolve_region, generate_md_report
+from scripts.generate_dashboard_data import _resolve_gdacs_link, _resolve_region, generate_md_report
class TestResolveRegion:
@@ -24,6 +24,31 @@ def test_disease_with_country_in_summary_returns_that_region(self) -> None:
assert _resolve_region("Disease Japan 2025-01-01", summary, True) == "Asia"
+class TestResolveGdacsLink:
+ def test_link_field_used_directly_when_present(self) -> None:
+ rf: dict[str, object] = {"link": "https://www.gdacs.org/report.aspx?eventid=1&episodeid=2&eventtype=EQ"}
+ assert _resolve_gdacs_link(rf, "1", "Earthquake") == rf["link"]
+
+ def test_url_dict_report_subkey_used_when_no_link(self) -> None:
+ rf: dict[str, object] = {"url": {"report": "https://www.gdacs.org/report.aspx?eventid=2&episodeid=3&eventtype=WF"}}
+ assert _resolve_gdacs_link(rf, "2", "Forest Fire") == "https://www.gdacs.org/report.aspx?eventid=2&episodeid=3&eventtype=WF"
+
+ def test_constructed_from_source_id_and_episodeid_for_degenerate_drought(self) -> None:
+ rf: dict[str, object] = {"alertlevel": "Green", "severity": "Minor", "population": 0, "episodeid": "14"}
+ url = _resolve_gdacs_link(rf, "1018332", "Drought")
+ assert url == "https://www.gdacs.org/report.aspx?eventid=1018332&episodeid=14&eventtype=DR"
+
+ def test_eventid_in_raw_fields_preferred_over_source_id(self) -> None:
+ rf: dict[str, object] = {"eventid": "999", "episodeid": "5", "eventtype": "FL"}
+ url = _resolve_gdacs_link(rf, "ignored", "Flood")
+ assert "eventid=999" in url
+ assert "episodeid=5" in url
+
+ def test_returns_empty_when_nothing_reconstructable(self) -> None:
+ rf: dict[str, object] = {}
+ assert _resolve_gdacs_link(rf, "", "Drought") == ""
+
+
def _make_incident(
incident_id: str = "x",
name: str = "Earthquake M7.5 Yumare, Venezuela 2026-06-24",
diff --git a/tests/integration/generate_dashboard_data_test.pyi b/tests/integration/generate_dashboard_data_test.pyi
index 00882369..78442207 100644
--- a/tests/integration/generate_dashboard_data_test.pyi
+++ b/tests/integration/generate_dashboard_data_test.pyi
@@ -6,6 +6,14 @@ class TestResolveRegion:
def test_disease_with_country_in_summary_returns_that_region(self) -> None: ...
+class TestResolveGdacsLink:
+ def test_link_field_used_directly_when_present(self) -> None: ...
+ def test_url_dict_report_subkey_used_when_no_link(self) -> None: ...
+ def test_constructed_from_source_id_and_episodeid_for_degenerate_drought(self) -> None: ...
+ def test_eventid_in_raw_fields_preferred_over_source_id(self) -> None: ...
+ def test_returns_empty_when_nothing_reconstructable(self) -> None: ...
+
+
class TestGenerateMdReportDayPrimary:
def test_day_primary_shows_3_most_recent_days(self) -> None: ...
def test_each_incident_shows_only_that_day_log(self) -> None: ...