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:
jubnl
2026-04-18 01:28:37 +02:00
parent 9a31fcac7b
commit 6a718fccea
45 changed files with 22471 additions and 285 deletions
+2 -2
View File
@@ -771,7 +771,7 @@ describe('KML/KMZ Import', () => {
expect(res.body.summary.totalPlacemarks).toBe(3);
expect(res.body.summary.skippedCount).toBe(1);
expect(Array.isArray(res.body.summary.errors)).toBe(true);
expect(res.body.summary.errors.join(' ')).toContain('missing Point coordinates');
expect(res.body.summary.errors.join(' ')).toContain('unsupported geometry type');
const nested = res.body.places.find((p: any) => p.name === 'Nested Place');
expect(nested).toBeDefined();
@@ -862,7 +862,7 @@ describe('GPX Import — edge cases', () => {
.set('Cookie', authCookie(user.id))
.attach('file', emptyGpx, { filename: 'empty.gpx', contentType: 'application/gpx+xml' });
expect(res.status).toBe(400);
expect(res.body.error).toMatch(/no waypoints/i);
expect(res.body.error).toMatch(/no matching places/i);
});
});