feat(move): "move to folder" for grid selections, folders, and m shortcut
Extends the heap-only "move to folder" action to grid single/bulk selections, sidebar folders, and an `m` keyboard shortcut — all through one shared dialog driven by a moveDialog store. Backend (sidecar): - Extract the heap move/copy + reindex loop into a reusable movePhotoFiles helper plus resolveMoveTarget - POST /photos/move: move/copy an arbitrary UID list into a folder - POST /folders/:rel/move: reparent a folder dir (whole subtree) under a new parent, guarding against moving into itself/a descendant Frontend: - moveDialog store + generalized MoveToFolderDialog (heap | photos | folder subjects); mounted once in +layout.svelte. Replaces HeapConvertDialog - movePhotosToFolder / moveFolder service fns - Entry points: BulkActionBar button, gridKeyNav `m`, FolderTree kebab, heap kebab — all call openMove() Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1006,6 +1006,43 @@ export async function convertHeap(
|
||||
return callSidecar('POST', `/albums/${uid}/convert`, body) as Promise<HeapConvertResult>;
|
||||
}
|
||||
|
||||
// ── Move arbitrary photos (by UID) to a folder ──────────────────────────────
|
||||
// Same on-disk move/copy + reindex as convertHeap, but the sidecar resolves the
|
||||
// photos from a UID list instead of an album. Backs the grid's move-to-folder.
|
||||
|
||||
export interface PhotosMoveBody {
|
||||
uids: string[];
|
||||
/** Originals-relative target folder. Empty string = originals root. */
|
||||
targetFolder: string;
|
||||
mode: 'move' | 'copy';
|
||||
/** Optional subfolder to create under `targetFolder` and place files into. */
|
||||
subfolder?: string | null;
|
||||
}
|
||||
|
||||
export interface PhotosMoveResult {
|
||||
moved: number;
|
||||
copied: number;
|
||||
errors: { uid: string; reason: string }[];
|
||||
}
|
||||
|
||||
export async function movePhotosToFolder(body: PhotosMoveBody): Promise<PhotosMoveResult> {
|
||||
return callSidecar('POST', '/photos/move', body) as Promise<PhotosMoveResult>;
|
||||
}
|
||||
|
||||
// ── Reparent a folder (move the directory under a different parent) ──────────
|
||||
|
||||
export interface FolderMoveResult {
|
||||
ok: boolean;
|
||||
oldPath: string;
|
||||
newPath: string;
|
||||
}
|
||||
|
||||
export async function moveFolder(rel: string, targetParent: string): Promise<FolderMoveResult> {
|
||||
return callSidecar('POST', `/folders/${encodeURIComponent(rel)}/move`, {
|
||||
targetParent
|
||||
}) as Promise<FolderMoveResult>;
|
||||
}
|
||||
|
||||
// ── Photo marks (rating + color) ─────────────────────────────────────────────
|
||||
// PhotoPrism's PUT silently drops Rating and Color (they're auto-computed
|
||||
// internal fields). We store them in mule-sidecar instead.
|
||||
|
||||
Reference in New Issue
Block a user