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:
@@ -24,7 +24,7 @@ export interface DuplicateGroup {
|
||||
bestFileUid: string;
|
||||
}
|
||||
|
||||
export async function listDuplicateGroups(): Promise<DuplicateGroup[]> {
|
||||
export async function listDuplicateGroups(basePath?: string): Promise<DuplicateGroup[]> {
|
||||
const photos = await listPhotos({
|
||||
q: 'stack:true',
|
||||
count: 200,
|
||||
@@ -32,7 +32,16 @@ export async function listDuplicateGroups(): Promise<DuplicateGroup[]> {
|
||||
order: 'newest'
|
||||
});
|
||||
return photos
|
||||
.filter((p) => (p.Files?.length ?? 0) > 1)
|
||||
.filter((p) => {
|
||||
// Filter out photos not in the current user's base path
|
||||
if (basePath) {
|
||||
const photoPath = p.Path ?? '';
|
||||
if (!photoPath.startsWith(basePath)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (p.Files?.length ?? 0) > 1;
|
||||
})
|
||||
.map((p) => {
|
||||
const files = p.Files ?? [];
|
||||
const primary = files.find((f) => f.Primary) ?? files[0];
|
||||
|
||||
@@ -589,6 +589,24 @@ export async function listGeo(q = ''): Promise<PpGeoCollection> {
|
||||
const { data } = await http.get<PpGeoCollection>('/geo', {
|
||||
params: { count: 50000, q: q || undefined }
|
||||
});
|
||||
|
||||
// PhotoPrism's geo endpoint returns coordinates as [lat, lng] but GeoJSON
|
||||
// (and MapLibre) expect [lng, lat]. Swap the coordinates in each feature.
|
||||
if (data.features) {
|
||||
for (const feature of data.features) {
|
||||
if (feature.geometry.type === 'Point' && Array.isArray(feature.geometry.coordinates)) {
|
||||
const [lat, lng] = feature.geometry.coordinates;
|
||||
feature.geometry.coordinates = [lng, lat];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also swap bbox if present: [minLat, minLng, maxLat, maxLng] → [minLng, minLat, maxLng, maxLat]
|
||||
if (data.bbox && data.bbox.length === 4) {
|
||||
const [minLat, minLng, maxLat, maxLng] = data.bbox;
|
||||
data.bbox = [minLng, minLat, maxLng, maxLat];
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user