feat(web): scope library views to per-user BasePath
PhotoPrism's user entity carries a per-user BasePath; the web app now mirrors that scope client-side so each user sees only their own subtree in the sidebar, timeline, folder counts, and heap-convert target picker. Admin without a BasePath is unchanged. Also removes the redundant "✕ <folder>" pill below the folder tree. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -147,3 +147,47 @@ export function videoUrl(hash: string, format = 'avc'): string {
|
||||
if (!session.previewToken) return '';
|
||||
return `/api/v1/videos/${hash}/${session.previewToken}/${format}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* The signed-in user's library root, originals-relative, no leading/trailing
|
||||
* slash. `""` means "whole library" — used today by admin accounts whose
|
||||
* BasePath isn't configured in PhotoPrism. Non-empty values gate every place
|
||||
* that crosses the user↔server seam (sidebar tree, timeline `path:` filter,
|
||||
* folder counts, heap convert) so each user sees only their own subtree.
|
||||
*/
|
||||
export function userBasePath(): string {
|
||||
return (session.user?.BasePath ?? '').replace(/^\/+|\/+$/g, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a user-relative path (what the sidebar and URL deal in) to a
|
||||
* server-absolute, originals-relative path (what PhotoPrism's `path:`
|
||||
* operator and the sidecar's filesystem ops want).
|
||||
*
|
||||
* "" or "/" → BasePath (user's root)
|
||||
* "2024/01" → "<basePath>/2024/01"
|
||||
* null → "" (caller decides to omit the filter entirely)
|
||||
*/
|
||||
export function toOriginalsPath(uiPath: string | null): string {
|
||||
if (uiPath === null) return '';
|
||||
const bp = userBasePath();
|
||||
const rel = uiPath.replace(/^\/+|\/+$/g, '');
|
||||
if (rel === '') return bp;
|
||||
return bp === '' ? rel : `${bp}/${rel}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse of `toOriginalsPath` — strips the user's BasePath prefix so the
|
||||
* UI can render `2024/01` instead of `users/alice/2024/01`. Paths that
|
||||
* are equal to the BasePath collapse to `""` (the user's root sentinel).
|
||||
* Paths outside the BasePath are returned as-is, but callers should
|
||||
* already have filtered those out via `listFolders`'s post-filter.
|
||||
*/
|
||||
export function toUserPath(serverPath: string): string {
|
||||
const bp = userBasePath();
|
||||
const sp = serverPath.replace(/^\/+|\/+$/g, '');
|
||||
if (bp === '') return sp;
|
||||
if (sp === bp) return '';
|
||||
if (sp.startsWith(bp + '/')) return sp.slice(bp.length + 1);
|
||||
return sp;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user