Spaces:
Sleeping
Sleeping
Commit
·
2224ec6
1
Parent(s):
7d9d335
Added Map api key
Browse files- backend/app/config/settings.py +4 -0
- backend/app/main.py +2 -1
- backend/app/routers/config.py +10 -0
- web/src/components/map/MapCanvas.tsx +23 -3
backend/app/config/settings.py
CHANGED
|
@@ -53,6 +53,10 @@ class Settings(BaseSettings):
|
|
| 53 |
firms_map_key: str | None = None
|
| 54 |
gdacs_rss_url: str | None = "https://www.gdacs.org/xml/rss.xml"
|
| 55 |
nvidia_api_key: str | None = None
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
|
| 57 |
def ensure_dirs(self) -> None:
|
| 58 |
if self.REPORTS_DB is None:
|
|
|
|
| 53 |
firms_map_key: str | None = None
|
| 54 |
gdacs_rss_url: str | None = "https://www.gdacs.org/xml/rss.xml"
|
| 55 |
nvidia_api_key: str | None = None
|
| 56 |
+
|
| 57 |
+
google_maps_api_key: str | None = Field(default=None, alias="VITE_GOOGLE_MAPS_API_KEY")
|
| 58 |
+
google_maps_map_id: str | None = Field(default=None, alias="VITE_GOOGLE_MAPS_MAP_IDY")
|
| 59 |
+
|
| 60 |
|
| 61 |
def ensure_dirs(self) -> None:
|
| 62 |
if self.REPORTS_DB is None:
|
backend/app/main.py
CHANGED
|
@@ -16,13 +16,14 @@ app.add_middleware(
|
|
| 16 |
app.mount("/uploads", StaticFiles(directory=str(settings.UPLOADS_DIR)), name="uploads")
|
| 17 |
|
| 18 |
# Routers
|
| 19 |
-
from .routers import chat, reports, feeds, uploads # noqa
|
| 20 |
from .routers.feeds import updates as updates_router
|
| 21 |
app.include_router(chat.router)
|
| 22 |
app.include_router(reports.router)
|
| 23 |
app.include_router(feeds.router)
|
| 24 |
app.include_router(updates_router)
|
| 25 |
app.include_router(uploads.router)
|
|
|
|
| 26 |
|
| 27 |
if settings.FRONTEND_DIST.exists():
|
| 28 |
app.mount("/", StaticFiles(directory=str(settings.FRONTEND_DIST), html=True), name="spa")
|
|
|
|
| 16 |
app.mount("/uploads", StaticFiles(directory=str(settings.UPLOADS_DIR)), name="uploads")
|
| 17 |
|
| 18 |
# Routers
|
| 19 |
+
from .routers import chat, reports, feeds, uploads, config # noqa
|
| 20 |
from .routers.feeds import updates as updates_router
|
| 21 |
app.include_router(chat.router)
|
| 22 |
app.include_router(reports.router)
|
| 23 |
app.include_router(feeds.router)
|
| 24 |
app.include_router(updates_router)
|
| 25 |
app.include_router(uploads.router)
|
| 26 |
+
app.include_router(config.router)
|
| 27 |
|
| 28 |
if settings.FRONTEND_DIST.exists():
|
| 29 |
app.mount("/", StaticFiles(directory=str(settings.FRONTEND_DIST), html=True), name="spa")
|
backend/app/routers/config.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter
|
| 2 |
+
from ..config.settings import settings
|
| 3 |
+
|
| 4 |
+
router = APIRouter(prefix="/config", tags=["config"])
|
| 5 |
+
|
| 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}
|
web/src/components/map/MapCanvas.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
| 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";
|
|
@@ -27,6 +27,11 @@ function PanOnSelect({ ll }: { ll: [number, number] | null }) {
|
|
| 27 |
return null;
|
| 28 |
}
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
export default function MapCanvas({
|
| 31 |
selectedLL,
|
| 32 |
selectedMeta,
|
|
@@ -46,11 +51,26 @@ export default function MapCanvas({
|
|
| 46 |
firms: FC | null;
|
| 47 |
reports: FC;
|
| 48 |
}) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
return (
|
| 50 |
-
<APIProvider
|
|
|
|
|
|
|
|
|
|
| 51 |
<Map
|
| 52 |
className="map"
|
| 53 |
-
mapId={MAP_ID}
|
| 54 |
defaultCenter={{ lat: 39, lng: -98 }}
|
| 55 |
defaultZoom={4}
|
| 56 |
gestureHandling="greedy"
|
|
|
|
| 4 |
AdvancedMarker,
|
| 5 |
useMap,
|
| 6 |
} from "@vis.gl/react-google-maps";
|
| 7 |
+
import { useEffect, useState } from "react";
|
| 8 |
import SearchControl from "./controls/SearchControl";
|
| 9 |
import MyLocationControl from "./controls/MyLocationControl";
|
| 10 |
import SingleSelect from "./controls/SingleSelect";
|
|
|
|
| 27 |
return null;
|
| 28 |
}
|
| 29 |
|
| 30 |
+
type RuntimeCfg = {
|
| 31 |
+
VITE_GOOGLE_MAPS_API_KEY?: string;
|
| 32 |
+
VITE_GOOGLE_MAPS_MAP_ID?: string;
|
| 33 |
+
};
|
| 34 |
+
|
| 35 |
export default function MapCanvas({
|
| 36 |
selectedLL,
|
| 37 |
selectedMeta,
|
|
|
|
| 51 |
firms: FC | null;
|
| 52 |
reports: FC;
|
| 53 |
}) {
|
| 54 |
+
const [cfg, setCfg] = useState<RuntimeCfg | null>(null);
|
| 55 |
+
const [err, setErr] = useState<string | null>(null);
|
| 56 |
+
|
| 57 |
+
useEffect(() => {
|
| 58 |
+
fetch("/config/runtime", { cache: "no-store" })
|
| 59 |
+
.then((r) => (r.ok ? r.json() : Promise.reject(new Error(r.statusText))))
|
| 60 |
+
.then(setCfg)
|
| 61 |
+
.catch((e) => setErr(e.message));
|
| 62 |
+
}, []);
|
| 63 |
+
|
| 64 |
+
if (err) return <div>Map config error: {err}</div>;
|
| 65 |
+
if (!cfg?.VITE_GOOGLE_MAPS_API_KEY) return <div>Loading map…</div>;
|
| 66 |
return (
|
| 67 |
+
<APIProvider
|
| 68 |
+
apiKey={cfg.VITE_GOOGLE_MAPS_API_KEY || GMAPS_KEY}
|
| 69 |
+
libraries={["places", "marker"]}
|
| 70 |
+
>
|
| 71 |
<Map
|
| 72 |
className="map"
|
| 73 |
+
mapId={cfg.VITE_GOOGLE_MAPS_MAP_ID || MAP_ID || undefined}
|
| 74 |
defaultCenter={{ lat: 39, lng: -98 }}
|
| 75 |
defaultZoom={4}
|
| 76 |
gestureHandling="greedy"
|