mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-21 06:11:45 +00:00
feat(import): selective GPX/KML element import and performance improvements
Add type-selector UI in the file import modal letting users choose which GPX elements (waypoints, routes, tracks) or KML/KMZ elements (points, paths) to import. KML LineString placemarks are now imported as path places with route_geometry. Performance improvements: - Extract MemoPlaceRow with React.memo and contentVisibility:auto to cut unnecessary re-renders in PlacesSidebar - Add weatherQueue to cap concurrent weather fetches at 3 - Replace sequential per-place deletes with a single bulkDelete API call (new DELETE /places/bulk endpoint + deletePlacesMany service) - Memoize atlas/photo/weather service calls to avoid redundant requests - Add multi-select mode to PlacesSidebar for bulk operations Add large GPX/KML/KMZ fixtures for integration/perf testing and two profiler analysis scripts under scripts/.
This commit is contained in:
@@ -95,6 +95,7 @@ const WMO_DESCRIPTION_EN: Record<number, string> = {
|
||||
// ── Cache management ────────────────────────────────────────────────────
|
||||
|
||||
const weatherCache = new Map<string, { data: WeatherResult; expiresAt: number }>();
|
||||
const inFlight = new Map<string, Promise<WeatherResult>>();
|
||||
const CACHE_MAX_ENTRIES = 1000;
|
||||
const CACHE_PRUNE_TARGET = 500;
|
||||
const CACHE_CLEANUP_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
||||
@@ -146,7 +147,7 @@ export function estimateCondition(tempAvg: number, precipMm: number): string {
|
||||
|
||||
// ── getWeather ──────────────────────────────────────────────────────────
|
||||
|
||||
export async function getWeather(
|
||||
async function _getWeatherImpl(
|
||||
lat: string,
|
||||
lng: string,
|
||||
date: string | undefined,
|
||||
@@ -281,9 +282,27 @@ export async function getWeather(
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function getWeather(
|
||||
lat: string,
|
||||
lng: string,
|
||||
date: string | undefined,
|
||||
lang: string,
|
||||
): Promise<WeatherResult> {
|
||||
const ck = cacheKey(lat, lng, date);
|
||||
const cached = getCached(ck);
|
||||
if (cached) return cached;
|
||||
|
||||
const inFlightKey = `${ck}:${lang}`;
|
||||
const existing = inFlight.get(inFlightKey);
|
||||
if (existing) return existing;
|
||||
const promise = _getWeatherImpl(lat, lng, date, lang);
|
||||
inFlight.set(inFlightKey, promise);
|
||||
try { return await promise; } finally { inFlight.delete(inFlightKey); }
|
||||
}
|
||||
|
||||
// ── getDetailedWeather ──────────────────────────────────────────────────
|
||||
|
||||
export async function getDetailedWeather(
|
||||
async function _getDetailedWeatherImpl(
|
||||
lat: string,
|
||||
lng: string,
|
||||
date: string,
|
||||
@@ -434,6 +453,24 @@ export async function getDetailedWeather(
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function getDetailedWeather(
|
||||
lat: string,
|
||||
lng: string,
|
||||
date: string,
|
||||
lang: string,
|
||||
): Promise<WeatherResult> {
|
||||
const ck = `detailed_${cacheKey(lat, lng, date)}`;
|
||||
const cached = getCached(ck);
|
||||
if (cached) return cached;
|
||||
|
||||
const inFlightKey = `${ck}:${lang}`;
|
||||
const existing = inFlight.get(inFlightKey);
|
||||
if (existing) return existing;
|
||||
const promise = _getDetailedWeatherImpl(lat, lng, date, lang);
|
||||
inFlight.set(inFlightKey, promise);
|
||||
try { return await promise; } finally { inFlight.delete(inFlightKey); }
|
||||
}
|
||||
|
||||
// ── ApiError ────────────────────────────────────────────────────────────
|
||||
|
||||
export class ApiError extends Error {
|
||||
|
||||
Reference in New Issue
Block a user