krishnadhulipalla commited on
Commit
5a4439e
·
1 Parent(s): 1c2899b

Updated Google maps API key

Browse files
backend/app/config/settings.py CHANGED
@@ -1,7 +1,7 @@
1
  # backend/app/config/settings.py
2
  from __future__ import annotations
3
  from pathlib import Path
4
- from pydantic import Field
5
  from pydantic_settings import BaseSettings, SettingsConfigDict
6
  import os, tempfile
7
 
@@ -41,7 +41,6 @@ def _default_data_dir() -> Path:
41
  w = _try_writable(p)
42
  if w:
43
  return w
44
- # As a last resort, raise a clear error
45
  raise RuntimeError(f"No writable DATA_DIR found. Tried: {candidates!r}")
46
 
47
  def _default_uploads_dir() -> Path:
@@ -63,6 +62,16 @@ class Settings(BaseSettings):
63
  OPENAI_MODEL_AGENT: str = "gpt-4o"
64
  OPENAI_MODEL_CLASSIFIER: str = "gpt-4o-mini"
65
 
 
 
 
 
 
 
 
 
 
 
66
  # Paths
67
  DATA_DIR: Path = Field(default_factory=_default_data_dir)
68
  REPORTS_DB: Path | None = None
@@ -75,7 +84,7 @@ class Settings(BaseSettings):
75
  DEFAULT_LIMIT: int = 10
76
  MAX_AGE_HOURS: int = 48
77
 
78
- # Optional extras you had in .env
79
  firms_map_key: str | None = None
80
  gdacs_rss_url: str | None = "https://www.gdacs.org/xml/rss.xml"
81
  nvidia_api_key: str | None = None
 
1
  # backend/app/config/settings.py
2
  from __future__ import annotations
3
  from pathlib import Path
4
+ from pydantic import Field, AliasChoices
5
  from pydantic_settings import BaseSettings, SettingsConfigDict
6
  import os, tempfile
7
 
 
41
  w = _try_writable(p)
42
  if w:
43
  return w
 
44
  raise RuntimeError(f"No writable DATA_DIR found. Tried: {candidates!r}")
45
 
46
  def _default_uploads_dir() -> Path:
 
62
  OPENAI_MODEL_AGENT: str = "gpt-4o"
63
  OPENAI_MODEL_CLASSIFIER: str = "gpt-4o-mini"
64
 
65
+ # ✅ Google Maps (read from multiple env names for safety)
66
+ google_maps_api_key: str | None = Field(
67
+ default=None,
68
+ validation_alias=AliasChoices("VITE_GOOGLE_MAPS_API_KEY", "GOOGLE_MAPS_API_KEY"),
69
+ )
70
+ google_maps_map_id: str | None = Field(
71
+ default=None,
72
+ validation_alias=AliasChoices("VITE_GOOGLE_MAPS_MAP_ID", "VITE_GOOGLE_MAPS_MAP_IDY", "GOOGLE_MAPS_MAP_ID"),
73
+ )
74
+
75
  # Paths
76
  DATA_DIR: Path = Field(default_factory=_default_data_dir)
77
  REPORTS_DB: Path | None = None
 
84
  DEFAULT_LIMIT: int = 10
85
  MAX_AGE_HOURS: int = 48
86
 
87
+ # Optional extras
88
  firms_map_key: str | None = None
89
  gdacs_rss_url: str | None = "https://www.gdacs.org/xml/rss.xml"
90
  nvidia_api_key: str | None = None
backend/app/routers/config.py CHANGED
@@ -1,3 +1,4 @@
 
1
  from fastapi import APIRouter
2
  from ..config.settings import settings
3
 
@@ -6,5 +7,7 @@ router = APIRouter(prefix="/config", tags=["config"])
6
  @router.get("/runtime")
7
  def runtime_config():
8
  # Only the fields you need in the client
9
- return {"VITE_GOOGLE_MAPS_API_KEY": settings.google_maps_api_key,
10
- "VITE_GOOGLE_MAPS_MAP_ID": settings.google_maps_map_id}
 
 
 
1
+ # backend/app/routers/config.py
2
  from fastapi import APIRouter
3
  from ..config.settings import settings
4
 
 
7
  @router.get("/runtime")
8
  def runtime_config():
9
  # Only the fields you need in the client
10
+ return {
11
+ "VITE_GOOGLE_MAPS_API_KEY": settings.google_maps_api_key,
12
+ "VITE_GOOGLE_MAPS_MAP_ID": settings.google_maps_map_id,
13
+ }
web/src/components/map/MapCanvas.tsx CHANGED
@@ -1,10 +1,6 @@
1
- import {
2
- APIProvider,
3
- Map,
4
- AdvancedMarker,
5
- // useMap,
6
- } from "@vis.gl/react-google-maps";
7
- // import { useEffect } from "react";
8
  import SearchControl from "./controls/SearchControl";
9
  import MyLocationControl from "./controls/MyLocationControl";
10
  import SingleSelect from "./controls/SingleSelect";
@@ -18,16 +14,10 @@ import FirmsLayer from "./overlays/FirmsLayer";
18
  import TractsLayer from "./overlays/TractsLayer";
19
  import LegendControl from "./controls/LegendControl";
20
 
21
- // function PanOnSelect({ ll }: { ll: [number, number] | null }) {
22
- // const map = useMap();
23
- // useEffect(() => {
24
- // if (!map || !ll) return;
25
- // map.panTo({ lat: ll[0], lng: ll[1] });
26
- // const z = map.getZoom?.() ?? 0;
27
- // if (z < 14) map.setZoom(14); // tweak 14–16 as you like
28
- // }, [map, ll]);
29
- // return null;
30
- // }
31
 
32
  export default function MapCanvas({
33
  selectedLL,
@@ -48,20 +38,32 @@ export default function MapCanvas({
48
  firms: FC | null;
49
  reports: FC;
50
  }) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  return (
52
- <APIProvider
53
- apiKey={GMAPS_KEY}
54
- libraries={["places", "marker", "geometry"]}
55
- >
56
  <Map
57
  className="map"
58
- mapId={MAP_ID}
59
  defaultCenter={{ lat: 39, lng: -98 }}
60
  defaultZoom={4}
61
  gestureHandling="greedy"
62
  disableDefaultUI={false}
63
  >
64
- {/* <PanOnSelect ll={selectedLL} /> */}
65
  <SearchControl onPlace={setSelected} />
66
  <MyLocationControl onLocated={setSelected} />
67
  <SingleSelect onPick={setSelected} />
@@ -81,6 +83,7 @@ export default function MapCanvas({
81
  firms={firms}
82
  minZoom={9}
83
  />
 
84
  {selectedLL && (
85
  <EmojiMarker
86
  position={{ lat: selectedLL[0], lng: selectedLL[1] }}
@@ -152,7 +155,7 @@ export default function MapCanvas({
152
  );
153
  })}
154
 
155
- {/* User reports (keep your AdvancedMarker + ReportIcon) */}
156
  {reports.features.map((f, i) => {
157
  if (f.geometry?.type !== "Point") return null;
158
  const [lng, lat] = f.geometry.coordinates as [number, number];
 
1
+ // web/src/components/map/MapCanvas.tsx
2
+ import { APIProvider, Map, AdvancedMarker } from "@vis.gl/react-google-maps";
3
+ import { useEffect, useState } from "react";
 
 
 
 
4
  import SearchControl from "./controls/SearchControl";
5
  import MyLocationControl from "./controls/MyLocationControl";
6
  import SingleSelect from "./controls/SingleSelect";
 
14
  import TractsLayer from "./overlays/TractsLayer";
15
  import LegendControl from "./controls/LegendControl";
16
 
17
+ type RuntimeCfg = {
18
+ VITE_GOOGLE_MAPS_API_KEY?: string;
19
+ VITE_GOOGLE_MAPS_MAP_ID?: string;
20
+ };
 
 
 
 
 
 
21
 
22
  export default function MapCanvas({
23
  selectedLL,
 
38
  firms: FC | null;
39
  reports: FC;
40
  }) {
41
+ const [cfg, setCfg] = useState<RuntimeCfg | null>(null);
42
+ const [err, setErr] = useState<string | null>(null);
43
+
44
+ useEffect(() => {
45
+ fetch("/config/runtime", { cache: "no-store" })
46
+ .then((r) => (r.ok ? r.json() : Promise.reject(new Error(r.statusText))))
47
+ .then(setCfg)
48
+ .catch((e) => setErr(e.message));
49
+ }, []);
50
+
51
+ const apiKey = cfg?.VITE_GOOGLE_MAPS_API_KEY || GMAPS_KEY;
52
+ const mapId = cfg?.VITE_GOOGLE_MAPS_MAP_ID || MAP_ID || undefined;
53
+
54
+ if (err) return <div>Map config error: {err}</div>;
55
+ if (!apiKey) return <div>Loading map…</div>;
56
+
57
  return (
58
+ <APIProvider apiKey={apiKey} libraries={["places", "marker", "geometry"]}>
 
 
 
59
  <Map
60
  className="map"
61
+ mapId={mapId}
62
  defaultCenter={{ lat: 39, lng: -98 }}
63
  defaultZoom={4}
64
  gestureHandling="greedy"
65
  disableDefaultUI={false}
66
  >
 
67
  <SearchControl onPlace={setSelected} />
68
  <MyLocationControl onLocated={setSelected} />
69
  <SingleSelect onPick={setSelected} />
 
83
  firms={firms}
84
  minZoom={9}
85
  />
86
+
87
  {selectedLL && (
88
  <EmojiMarker
89
  position={{ lat: selectedLL[0], lng: selectedLL[1] }}
 
155
  );
156
  })}
157
 
158
+ {/* User reports */}
159
  {reports.features.map((f, i) => {
160
  if (f.geometry?.type !== "Point") return null;
161
  const [lng, lat] = f.geometry.coordinates as [number, number];