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 7 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, letting users fly to a conflict zone and render live KML geometry natively via DeckGL's Previously-flagged concerns have all been addressed in this revision:
Key changes:
One P1 issue remains: Confidence Score: 4/5Safe to merge after the one-line fix resetting conflictLegendEntries at the top of loadConflictKml All previously-flagged concerns have been addressed. One P1 remains: stale legend swatches appear when a KML fetch fails mid-session and the user subsequently toggles a map layer. The fix is trivial (add a single reset line). Everything else is clean: the CORS proxy is well-guarded, the config-driven architecture works correctly, and the KML parser handles the Google My Maps format as tested. src/components/DeckGLMap.ts — loadConflictKml method (lines 3702-3705) Important Files Changed
Sequence DiagramsequenceDiagram
actor User
participant Dropdown as Conflicts Dropdown
participant DeckGLMap
participant DirectFetch as Direct fetch (browser)
participant Proxy as /api/gmaps-kml (Edge Fn)
participant Google as Google My Maps
User->>Dropdown: Select conflict scene
Dropdown->>DeckGLMap: activateConflictScene(id)
DeckGLMap->>DeckGLMap: flyTo(lat/lon/zoom)
DeckGLMap->>DirectFetch: fetch(kmlUrl)
alt CORS blocked — TypeError thrown
DirectFetch-->>DeckGLMap: throw TypeError
DeckGLMap->>Proxy: GET /api/gmaps-kml?url=...
Proxy->>Proxy: Validate hostname + https: protocol
Proxy->>Proxy: checkRateLimit(req)
Proxy->>Google: fetch(kmlUrl, User-Agent)
Google-->>Proxy: KML text
Proxy-->>DeckGLMap: 200 KML (CORS + Cache-Control headers)
else Direct fetch succeeds
DirectFetch-->>DeckGLMap: KML text
end
DeckGLMap->>DeckGLMap: parseKmlToGeoJson(text)
DeckGLMap->>DeckGLMap: deriveConflictLegendEntries(...)
DeckGLMap->>DeckGLMap: updateLegend() + render()
Greploops — Automatically fix all review issues by running Reviews (3): Last reviewed commit: "merge(main): resolve DeckGLMap.ts confli..." | 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 |
…rlay fields and legend renderer
5dc099c to
05ac620
Compare
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.