fix: update heatmap data conversion and improve query structure for geo heatmap
This commit is contained in:
@@ -26,8 +26,10 @@ const LeafletHeatMap: React.FC<LeafletHeatMapProps> = ({ filters, isDarkMode, on
|
||||
|
||||
// Initialize the map
|
||||
const map = L.map(mapContainerRef.current, {
|
||||
center: [0, 0],
|
||||
center: [20, 0],
|
||||
zoom: 2,
|
||||
minZoom: 2,
|
||||
maxZoom: 18,
|
||||
zoomControl: true,
|
||||
scrollWheelZoom: true,
|
||||
doubleClickZoom: true,
|
||||
@@ -35,6 +37,9 @@ const LeafletHeatMap: React.FC<LeafletHeatMapProps> = ({ filters, isDarkMode, on
|
||||
keyboard: true,
|
||||
dragging: true,
|
||||
touchZoom: true,
|
||||
worldCopyJump: true,
|
||||
maxBounds: [[-85, -Infinity], [85, Infinity]],
|
||||
maxBoundsViscosity: 1.0,
|
||||
});
|
||||
|
||||
mapRef.current = map;
|
||||
@@ -76,10 +81,10 @@ const LeafletHeatMap: React.FC<LeafletHeatMapProps> = ({ filters, isDarkMode, on
|
||||
}
|
||||
|
||||
// Create new heat layer with the data
|
||||
// Convert [lng, lat] to [lat, lng, intensity] format for leaflet.heat
|
||||
const heatData: [number, number, number][] = data.map(([lng, lat]: [number, number]) => [
|
||||
// Convert [lon, lat] to [lat, lon, intensity] format for leaflet.heat
|
||||
const heatData: [number, number, number][] = data.map(([lon, lat]: [number, number]) => [
|
||||
lat, // latitude first for leaflet.heat
|
||||
lng, // longitude second
|
||||
lon, // longitude second
|
||||
1 // intensity (weight)
|
||||
]);
|
||||
|
||||
|
||||
@@ -15,24 +15,54 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
}
|
||||
|
||||
|
||||
const dbAssets = await db.select({
|
||||
// Build query with optional LEFT JOINs based on filters
|
||||
let query = db.select({
|
||||
assetId: assets.id,
|
||||
latitude: exif.latitude,
|
||||
longitude: exif.longitude,
|
||||
}).from(assets)
|
||||
.innerJoin(exif, eq(assets.id, exif.assetId))
|
||||
.innerJoin(albumsAssetsAssets, eq(assets.id, albumsAssetsAssets.assetId))
|
||||
.innerJoin(assetFaces, eq(albumsAssetsAssets.assetId, assetFaces.assetId))
|
||||
.innerJoin(person, eq(assetFaces.personId, person.id))
|
||||
.where(
|
||||
and(
|
||||
eq(assets.ownerId, currentUser.id),
|
||||
isNotNull(exif.latitude),
|
||||
isNotNull(exif.longitude),
|
||||
albumIds?.length > 0 ? inArray(albumsAssetsAssets.albumId, [albumIds]) : undefined,
|
||||
peopleIds?.length > 0 ? inArray(person.id, [peopleIds]) : undefined
|
||||
)
|
||||
);
|
||||
.$dynamic();
|
||||
|
||||
// Only join albums table if filtering by albumIds
|
||||
if (albumIds) {
|
||||
query = query
|
||||
.innerJoin(albumsAssetsAssets, eq(assets.id, albumsAssetsAssets.assetId))
|
||||
.where(
|
||||
and(
|
||||
eq(assets.ownerId, currentUser.id),
|
||||
isNotNull(exif.latitude),
|
||||
isNotNull(exif.longitude),
|
||||
inArray(albumsAssetsAssets.albumId, [albumIds])
|
||||
)
|
||||
);
|
||||
}
|
||||
// Only join people table if filtering by peopleIds
|
||||
else if (peopleIds) {
|
||||
query = query
|
||||
.innerJoin(assetFaces, eq(assets.id, assetFaces.assetId))
|
||||
.innerJoin(person, eq(assetFaces.personId, person.id))
|
||||
.where(
|
||||
and(
|
||||
eq(assets.ownerId, currentUser.id),
|
||||
isNotNull(exif.latitude),
|
||||
isNotNull(exif.longitude),
|
||||
inArray(person.id, [peopleIds])
|
||||
)
|
||||
);
|
||||
}
|
||||
// No filters - get all assets with location
|
||||
else {
|
||||
query = query.where(
|
||||
and(
|
||||
eq(assets.ownerId, currentUser.id),
|
||||
isNotNull(exif.latitude),
|
||||
isNotNull(exif.longitude)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const dbAssets = await query;
|
||||
const heatmapData = dbAssets.map((asset) => [
|
||||
asset.longitude,
|
||||
asset.latitude,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Header from '@/components/shared/Header'
|
||||
import React, { useState } from 'react'
|
||||
import PageLayout from '@/components/layouts/PageLayout';
|
||||
import { getAssetGeoHeatmap, IHeatMapParams } from '@/handlers/api/asset.handler';
|
||||
import { IHeatMapParams } from '@/handlers/api/asset.handler';
|
||||
import { useTheme } from 'next-themes';
|
||||
import { X } from 'lucide-react';
|
||||
import AlbumDropdown from '@/components/shared/AlbumDropdown';
|
||||
@@ -15,10 +15,6 @@ const LeafletHeatMap = dynamic(() => import('../../components/LeafletHeatMap'),
|
||||
loading: () => <div className="h-full w-full flex items-center justify-center">Loading map...</div>
|
||||
});
|
||||
|
||||
interface IHeatMapProps {
|
||||
filters: IHeatMapParams;
|
||||
}
|
||||
|
||||
export default function GeoHeatmap() {
|
||||
const { theme } = useTheme();
|
||||
const [filters, setFilters] = useState<{
|
||||
|
||||
Reference in New Issue
Block a user