fix(sidebar,map,duplicates): flatten sidebar hierarchy, filter by user basePath, fix map coordinates

- Flatten sidebar: remove collapsible Tags and Review sections, place all items at level-0
  Notes, tag categories (Labels/Keywords/People/Colors/Ratings) now appear directly in Views
  Review tabs (Causes/Stacks/Duplicates) and Hidden appear directly in Manage
- Filter duplicates by user base path to ensure multi-tenant isolation
  listDuplicateGroups now accepts optional basePath parameter
  update review page and sidebar to pass userBasePath() for proper per-user caching
- Filter map geo data by user base path using path: query filter
  map page now only shows geotagged photos from current user's library
- Fix map coordinate positioning: PhotoPrism /geo endpoint returns [lat,lng]
  but GeoJSON and MapLibre expect [lng,lat]. Transform coordinates and bbox
  on data receive to fix photo placement and zoom behavior

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 21:04:56 +02:00
parent e1e508671e
commit 400b215036
5 changed files with 80 additions and 143 deletions

View File

@@ -9,15 +9,19 @@
import 'maplibre-gl/dist/maplibre-gl.css';
import { goto } from '$app/navigation';
import { listGeo, type PpGeoCollection, type PpGeoFeature } from '$lib/services/photoprism';
import { isAuthenticated, thumbUrl } from '$lib/stores/session.svelte';
import { isAuthenticated, thumbUrl, userBasePath } from '$lib/stores/session.svelte';
import { setAnchor, setFocused, setOrder } from '$lib/stores/selection.svelte';
import Toolbar from '$lib/components/layout/Toolbar.svelte';
const geoQuery = createQuery<PpGeoCollection>(() => ({
queryKey: ['geo'],
queryFn: () => listGeo(),
enabled: isAuthenticated()
}));
const geoQuery = createQuery<PpGeoCollection>(() => {
const bp = userBasePath();
const q = bp ? `path:${bp}*` : '';
return {
queryKey: ['geo', bp],
queryFn: () => listGeo(q),
enabled: isAuthenticated()
};
});
let mapEl: HTMLDivElement | undefined = $state();
let map: maplibregl.Map | undefined;

View File

@@ -30,7 +30,7 @@
scanCrossFolderDuplicates,
type CrossFolderScanResult
} from '$lib/services/photoprism';
import { isAuthenticated } from '$lib/stores/session.svelte';
import { isAuthenticated, userBasePath } from '$lib/stores/session.svelte';
import { clearSelection, selection } from '$lib/stores/selection.svelte';
import { filters, setSection, type Section } from '$lib/stores/filters.svelte';
import {
@@ -85,8 +85,8 @@
// observes its cache (enabled:false) and DuplicatesView is what
// triggers the actual scan when its tab is active.
const stacksQuery = createQuery<DuplicateGroup[]>(() => ({
queryKey: ['duplicates'],
queryFn: listDuplicateGroups,
queryKey: ['duplicates', userBasePath()],
queryFn: () => listDuplicateGroups(userBasePath()),
enabled: isAuthenticated(),
staleTime: 30_000
}));