From ef8e0d1bfa70c73d71c3c936522a8faa751d8ae8 Mon Sep 17 00:00:00 2001 From: Logan Date: Mon, 25 May 2026 14:19:21 -0400 Subject: [PATCH] =?UTF-8?q?revert:=20remove=20leaflet.gridlayer.googlemuta?= =?UTF-8?q?nt=20=E2=80=94=20incompatible=20with=20Next.js=2015=20bundler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The package consistently throws 'L.GridLayer.GoogleMutant is not a constructor' due to L-instance conflicts in the webpack bundle, despite multiple workaround attempts. Removed package, transpilePackages entry, type stub, env var, and all related component code. Traffic overlay dropped; geocoding (backend) unaffected. --- drb-c2-core/.env.example | 4 ++ drb-frontend/components/MapView.tsx | 67 +------------------ drb-frontend/next.config.mjs | 2 +- drb-frontend/package.json | 3 +- .../types/leaflet.gridlayer.googlemutant.d.ts | 4 -- 5 files changed, 7 insertions(+), 73 deletions(-) delete mode 100644 drb-frontend/types/leaflet.gridlayer.googlemutant.d.ts diff --git a/drb-c2-core/.env.example b/drb-c2-core/.env.example index cdf398f..c7fbc8a 100644 --- a/drb-c2-core/.env.example +++ b/drb-c2-core/.env.example @@ -18,6 +18,10 @@ GCS_BUCKET=your-bucket-name # How long (seconds) before a node is marked offline if no checkin received NODE_OFFLINE_THRESHOLD=90 +# Google Maps — for geocoding location strings extracted from transcripts +# Enable "Geocoding API" in Cloud Console for this key +GOOGLE_MAPS_API_KEY= + # OpenAI — for transcription (Whisper), intelligence extraction, embeddings, and summaries OPENAI_API_KEY= SUMMARY_INTERVAL_MINUTES=15 diff --git a/drb-frontend/components/MapView.tsx b/drb-frontend/components/MapView.tsx index 18242df..69d2881 100644 --- a/drb-frontend/components/MapView.tsx +++ b/drb-frontend/components/MapView.tsx @@ -1,6 +1,6 @@ "use client"; -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { FeatureGroup, LayersControl, @@ -145,54 +145,6 @@ function computeGroups( return result; } -// ── Google Maps traffic layer via leaflet-google-mutant ─────────────────────── -// Uses dynamic import so the side-effect augments the same L instance at runtime, -// avoiding the "GoogleMutant is not a constructor" error from static top-level imports. -function GoogleTrafficManager({ enabled }: { enabled: boolean }) { - const map = useMap(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const layerRef = useRef(null); - const scriptLoadedRef = useRef(false); - - useEffect(() => { - if (!enabled) { - if (layerRef.current) { map.removeLayer(layerRef.current); layerRef.current = null; } - return; - } - - const key = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY; - if (!key) return; - - function mountLayer() { - import("leaflet.gridlayer.googlemutant").then(() => { - if (layerRef.current) return; // already mounted - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const layer = (L as any).gridLayer.googleMutant({ type: "roadmap" }); - layer.addGoogleLayer("TrafficLayer"); - map.addLayer(layer); - layerRef.current = layer; - }); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - if ((window as any).google?.maps) { - mountLayer(); - } else if (!scriptLoadedRef.current) { - scriptLoadedRef.current = true; - const script = document.createElement("script"); - script.src = `https://maps.googleapis.com/maps/api/js?key=${key}&loading=async`; - script.async = true; - script.onload = mountLayer; - document.head.appendChild(script); - } - - return () => { - if (layerRef.current) { map.removeLayer(layerRef.current); layerRef.current = null; } - }; - }, [enabled, map]); - - return null; -} // ── MapRefCapture — exposes L.Map instance to parent ───────────────────────── function MapRefCapture({ onReady }: { onReady: (m: L.Map) => void }) { @@ -391,7 +343,6 @@ export default function MapView({ nodes, activeCalls, incidents = [], lastUpdate return () => clearInterval(id); }, []); - const [trafficEnabled, setTrafficEnabled] = useState(false); // Live clock for TOC situational awareness useEffect(() => { @@ -489,9 +440,6 @@ export default function MapView({ nodes, activeCalls, incidents = [], lastUpdate - {/* Traffic managed outside LayersControl to avoid L-instance conflicts */} - - {/* Overlay: Weather Radar — NEXRAD via Iowa Env Mesonet; key forces remount on refresh */} )} - {process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY && ( - - )} {/* ── Clock — bottom-left for TOC situational awareness ───────────────── */} diff --git a/drb-frontend/next.config.mjs b/drb-frontend/next.config.mjs index fd65644..0242696 100644 --- a/drb-frontend/next.config.mjs +++ b/drb-frontend/next.config.mjs @@ -1,7 +1,7 @@ /** @type {import('next').NextConfig} */ const nextConfig = { output: "standalone", - transpilePackages: ["leaflet", "react-leaflet", "leaflet.gridlayer.googlemutant"], + transpilePackages: ["leaflet", "react-leaflet"], }; export default nextConfig; diff --git a/drb-frontend/package.json b/drb-frontend/package.json index 267c7d3..24bdca5 100644 --- a/drb-frontend/package.json +++ b/drb-frontend/package.json @@ -14,8 +14,7 @@ "react-dom": "^18.3.0", "firebase": "^10.12.0", "leaflet": "^1.9.4", - "leaflet.gridlayer.googlemutant": "0.16.0", - "react-leaflet": "^4.2.1" +"react-leaflet": "^4.2.1" }, "devDependencies": { "typescript": "^5.4.0", diff --git a/drb-frontend/types/leaflet.gridlayer.googlemutant.d.ts b/drb-frontend/types/leaflet.gridlayer.googlemutant.d.ts deleted file mode 100644 index e5d46de..0000000 --- a/drb-frontend/types/leaflet.gridlayer.googlemutant.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module "leaflet.gridlayer.googlemutant" { - // Side-effect import — augments L.gridLayer with googleMutant factory. - // No public API is consumed directly from this module. -}