chore: Remove reporter map dependencies

This commit is contained in:
Janez T
2026-04-04 10:01:03 +02:00
parent d431a79aa8
commit 4690ceead1
3 changed files with 0 additions and 134 deletions

View File

@@ -11,14 +11,11 @@
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@tailwindcss/vite": "^4.1.18",
"@types/leaflet": "^1.9.21",
"astro": "^5.17.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"leaflet": "^1.9.4",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-leaflet": "^5.0.0",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.18",
},
@@ -279,8 +276,6 @@
"@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
"@react-leaflet/core": ["@react-leaflet/core@3.0.0", "", { "peerDependencies": { "leaflet": "^1.9.0", "react": "^19.0.0", "react-dom": "^19.0.0" } }, "sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ=="],
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="],
"@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="],
@@ -397,12 +392,8 @@
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
"@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
"@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
"@types/leaflet": ["@types/leaflet@1.9.21", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w=="],
"@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
@@ -673,8 +664,6 @@
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
"leaflet": ["leaflet@1.9.4", "", {}, "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="],
"lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
@@ -865,8 +854,6 @@
"react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
"react-leaflet": ["react-leaflet@5.0.0", "", { "dependencies": { "@react-leaflet/core": "^3.0.0" }, "peerDependencies": { "leaflet": "^1.9.0", "react": "^19.0.0", "react-dom": "^19.0.0" } }, "sha512-CWbTpr5vcHw5bt9i4zSlPEVQdTVcML390TjeDG0cK59z1ylexpqC6M1PJFjV8jD7CF+ACBFsLIDs6DRMoLEofw=="],
"react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="],
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],

View File

@@ -19,14 +19,11 @@
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@tailwindcss/vite": "^4.1.18",
"@types/leaflet": "^1.9.21",
"astro": "^5.17.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"leaflet": "^1.9.4",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-leaflet": "^5.0.0",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.18"
},

View File

@@ -34,14 +34,6 @@ type ChartPoint = {
reports: number;
};
type LocationPoint = {
key6: string;
city: string;
country: string;
latitude: number;
longitude: number;
};
type AppVersionEntry = {
version: string;
reporters: number;
@@ -81,7 +73,6 @@ type DashboardResponse = {
pathModeTotals: PathModeEntry[];
recentReporters: ReporterSummary[];
chartPoints: ChartPoint[];
locationPoints: LocationPoint[];
appVersions: AppVersionEntry[];
trafficComposition: TrafficComposition;
multiHopRatio: MultiHopRatio;
@@ -395,18 +386,6 @@ export function DashboardShell() {
{/* Map + Traffic trend */}
<section className="space-y-4">
<Card>
<CardHeader>
<CardTitle>Reporter Locations</CardTitle>
<CardDescription>
Approximate locations from Cloudflare edge nodes, not device GPS.
</CardDescription>
</CardHeader>
<CardContent>
<ReporterMap locations={summary?.locationPoints ?? []} />
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Observations Over Time</CardTitle>
@@ -795,103 +774,6 @@ function EmptyState({ label }: { label: string }) {
);
}
function ReporterMap({ locations }: { locations: LocationPoint[] }) {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
if (!mounted || typeof window === "undefined") {
return (
<div className="flex min-h-[360px] items-center justify-center rounded-xl bg-secondary/30 text-sm text-muted-foreground">
Loading map...
</div>
);
}
return <LeafletMap locations={locations} />;
}
function LeafletMap({ locations }: { locations: LocationPoint[] }) {
const [leaflet, setLeaflet] = useState<{
MapContainer: typeof import("react-leaflet").MapContainer;
TileLayer: typeof import("react-leaflet").TileLayer;
CircleMarker: typeof import("react-leaflet").CircleMarker;
Tooltip: typeof import("react-leaflet").Tooltip;
L: typeof import("leaflet");
} | null>(null);
useEffect(() => {
Promise.all([
import("react-leaflet"),
import("leaflet"),
]).then(([rl, L]) => {
setLeaflet({
MapContainer: rl.MapContainer,
TileLayer: rl.TileLayer,
CircleMarker: rl.CircleMarker,
Tooltip: rl.Tooltip,
L: L.default ?? L,
});
});
}, []);
if (!leaflet) {
return (
<div className="flex min-h-[360px] items-center justify-center rounded-xl bg-secondary/30 text-sm text-muted-foreground">
Loading map...
</div>
);
}
const { MapContainer, TileLayer, CircleMarker, Tooltip } = leaflet;
const center: [number, number] = locations.length
? [
locations.reduce((s, l) => s + l.latitude, 0) / locations.length,
locations.reduce((s, l) => s + l.longitude, 0) / locations.length,
]
: [46.0, 14.5];
return (
<>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<div className="overflow-hidden rounded-xl">
<MapContainer
center={center}
zoom={locations.length > 1 ? 4 : 8}
scrollWheelZoom={true}
style={{ height: 360, width: "100%" }}
attributionControl={true}
>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{locations.map((loc) => (
<CircleMarker
key={`${loc.latitude}-${loc.longitude}-${loc.city}`}
center={[loc.latitude, loc.longitude]}
radius={8}
pathOptions={{
color: "hsl(217, 91%, 60%)",
fillColor: "hsl(217, 91%, 70%)",
fillOpacity: 0.6,
weight: 2,
}}
>
<Tooltip>
{loc.city}, {loc.country}
</Tooltip>
</CircleMarker>
))}
</MapContainer>
</div>
</>
);
}
function formatRelative(value: string) {
const diffMs = Date.now() - new Date(value).getTime();
const diffMin = Math.floor(diffMs / 60000);