feat(map): add conflict KML overlay system with native WebGL rendering#2452
feat(map): add conflict KML overlay system with native WebGL rendering#2452Ahmadhamdan47 wants to merge 6 commits intokoala73:mainfrom
Conversation
|
@Ahmadhamdan47 is attempting to deploy a commit to the Elie Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryThis PR introduces a config-driven conflict KML overlay system for the map: a new ⚔ Conflicts dropdown lets users fly to a conflict zone and load a live KML file rendered natively via All previous review concerns have been resolved in this iteration:
Remaining finding:
Confidence Score: 5/5Safe to merge — all prior P0/P1 concerns have been addressed; the one remaining finding is a misleading JSDoc comment with no runtime impact. Every previously flagged issue (rate limiting, method guard, protocol validation, dev proxy allowlist, ellipsis logic, folderTranslations coupling) has been correctly resolved. The only outstanding finding is an incorrect documentation comment on src/config/conflicts.ts — the Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant ConflictSelect as ⚔ Conflicts Dropdown
participant DeckGLMap
participant Browser as Browser fetch()
participant Proxy as /api/gmaps-kml (Edge Fn)
participant Google as www.google.com
User->>ConflictSelect: select scene
ConflictSelect->>DeckGLMap: activateConflictScene(id)
DeckGLMap->>DeckGLMap: flyTo(lat, lon, zoom)
DeckGLMap->>Browser: fetch(kmlUrl) direct
alt CORS allowed
Browser->>Google: GET kmlUrl
Google-->>Browser: KML text
Browser-->>DeckGLMap: text
else CORS blocked (TypeError)
Browser-->>DeckGLMap: throws
DeckGLMap->>Proxy: GET /api/gmaps-kml?url=…
Note over Proxy: checkRateLimit, GET-only,<br/>hostname + https allowlist
Proxy->>Google: GET kmlUrl
Google-->>Proxy: KML text
Proxy-->>DeckGLMap: KML text (CORS headers added)
end
DeckGLMap->>DeckGLMap: parseKmlToGeoJson(text)
DeckGLMap->>DeckGLMap: deriveConflictLegendEntries()
DeckGLMap->>DeckGLMap: createConflictOverlayLayer() → GeoJsonLayer
DeckGLMap->>DeckGLMap: updateLegend() → conflict-kml-legend panel
Reviews (2): Last reviewed commit: "fix(tests): register gmaps-kml.js in leg..." | Re-trigger Greptile |
- api/gmaps-kml.js: reject non-GET methods (405), add rate limiting via shared _rate-limit.js helper, enforce https: protocol on allowlisted URLs - vite.config.ts: mirror production allowlist (hostname + https: guard) in dev proxy so disallowed URLs fail locally as they would in production - src/config/conflicts.ts: add folderTranslations to ConflictSceneConfig so legend mappings live alongside other scene data; move Arabic->English translations from DeckGLMap into the south-lebanon entry - src/components/DeckGLMap.ts: remove CONFLICT_FOLDER_TRANSLATIONS static; thread folderTranslations through loadConflictKml -> deriveConflictLegendEntries; fix ellipsis check to use cleanDesc.length instead of raw HTML desc.length
…e sidecar origin-substitution test
SebastienMelki
left a comment
There was a problem hiding this comment.
Solid implementation — config-driven KML overlay system with WebGL rendering via GeoJsonLayer, no new npm deps. Greptile 5/5. One nit: the JSDoc on folderTranslations in src/config/conflicts.ts says folders not listed are hidden, but actually all non-Point geometry is rendered regardless — folderTranslations only controls legend panel entries. Please fix that comment before merge. LGTM otherwise.
done |
Summary
Introduces a fully data-driven conflict overlay system on the map. A new ⚔ Conflicts dropdown in the map header (next to the regional selector) lets users fly to a conflict area and load a live KML overlay rendered natively in WebGL via
GeoJsonLayer— no new npm dependencies added; KML is parsed entirely client-side using the built-inDOMParser.Geometry is rendered using the source map's own colors — lines for front lines, polygons for control zones. A dedicated conflict legend panel (bottom-right) appears when an overlay is active, showing only curated, translated folder entries. Selecting the blank option clears the overlay and hides the legend.
A standalone
/api/gmaps-kmlEdge Function proxies KML requests that are CORS-blocked in the browser, currently allowlisted towww.google.comonly.The initial scene — Israeli invasion of South Lebanon / Gaza — is sourced from [ArabOSINT](https://x.com/Arabosint's public Google My Maps. Credit and thanks to ArabOSINT for making this data openly available.
Type of change
Affected areas
/api/*) — new/api/gmaps-kmlCORS proxysrc/config/conflicts.tsFiles changed
src/config/conflicts.tsConflictSceneConfiginterface +CONFLICT_SCENESarrayapi/gmaps-kml.jswww.google.comsrc/components/DeckGLMap.tsGeoJsonLayerrenderer, conflict legend,activateConflictScene()public methodsrc/components/MapContainer.tsactivateConflictScene()through the unified map APIsrc/app/panel-layout.tssrc/app/event-handlers.tssrc/config/index.tsCONFLICT_SCENES/ConflictSceneConfigsrc/styles/main.cssvite.config.ts/api/gmaps-kmldocs/data-sources.mdxMaintainer guide — adding or changing conflict sources
The system is fully config-driven. All scenes live in one file; no other code changes are needed when adding new entries.
1. Add a scene to
src/config/conflicts.ts2. Getting the KML URL from a Google My Maps
https://www.google.com/maps/d/u/0/viewer?mid=XXXX&...)mid=valuehttps://www.google.com/maps/d/kml?mid=XXXX&forcekml=1kmlUrl3. Using any other public KML URL
Any publicly accessible KML URL works — not just Google My Maps:
If the URL is CORS-blocked, the proxy handles it automatically. For non-Google domains, extend
ALLOWED_HOSTNAMESinapi/gmaps-kml.js.4. Controlling legend entries
Add a
folderTranslationsmap to the scene entry insrc/config/conflicts.ts.Only folders listed there appear in the legend. Unlisted folders still render on
the map — they are simply omitted from the legend panel.