fix: address open triage issues (#21,#26,#45,#46,#47,#30-33)
- #45: re-read local folder when recursive checkbox toggles - #47: clear Identify crop spinner when image is already cached - #46: search selected people by person_ids; AND for "First Last" - #21: enqueue network import without blocking API walk - #26: serve resized grid thumbnails for photos - #30/#31/#33: re-enable small-face filters in auto-match
This commit is contained in:
+34
-11
@@ -37,7 +37,6 @@ from backend.schemas.search import (
|
||||
SearchPhotosResponse,
|
||||
)
|
||||
from backend.services.photo_service import (
|
||||
find_photos_in_folder,
|
||||
import_photo_from_path,
|
||||
)
|
||||
from backend.services.search_service import (
|
||||
@@ -63,6 +62,10 @@ def search_photos(
|
||||
current_user: Annotated[dict, Depends(get_current_user)],
|
||||
search_type: str = Query("name", description="Search type: name, date, tags, no_faces, no_tags, processed, unprocessed, favorites"),
|
||||
person_name: Optional[str] = Query(None, description="Person name for name search"),
|
||||
person_ids: Optional[str] = Query(
|
||||
None,
|
||||
description="Comma-separated person IDs for exact name search (preferred over substring when selecting people)",
|
||||
),
|
||||
tag_names: Optional[str] = Query(None, description="Comma-separated tag names for tag search"),
|
||||
match_all: bool = Query(False, description="Match all tags (for tag search)"),
|
||||
date_from: Optional[str] = Query(None, description="Date from (YYYY-MM-DD)"),
|
||||
@@ -111,13 +114,36 @@ def search_photos(
|
||||
tag_list = [t.strip() for t in tag_names.split(",") if t.strip()]
|
||||
|
||||
if search_type == "name":
|
||||
if not person_name:
|
||||
parsed_person_ids: list[int] = []
|
||||
if person_ids:
|
||||
for part in person_ids.split(","):
|
||||
part = part.strip()
|
||||
if not part:
|
||||
continue
|
||||
try:
|
||||
parsed_person_ids.append(int(part))
|
||||
except ValueError:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Invalid person_ids value: {part}",
|
||||
)
|
||||
if not person_name and not parsed_person_ids:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="person_name is required for name search",
|
||||
detail="person_name or person_ids is required for name search",
|
||||
)
|
||||
results, total = search_photos_by_name(
|
||||
db, person_name, folder_path, media_type, df, dt, tag_list, match_all, page, page_size
|
||||
db,
|
||||
person_name or "",
|
||||
folder_path,
|
||||
media_type,
|
||||
df,
|
||||
dt,
|
||||
tag_list,
|
||||
match_all,
|
||||
page,
|
||||
page_size,
|
||||
person_ids=parsed_person_ids or None,
|
||||
)
|
||||
for photo, full_name in results:
|
||||
tags = get_photo_tags(db, photo.id)
|
||||
@@ -360,23 +386,20 @@ def import_photos(
|
||||
detail=f"Folder not found: {request.folder_path}",
|
||||
)
|
||||
|
||||
# Estimate number of photos (quick scan)
|
||||
estimated_photos = len(find_photos_in_folder(request.folder_path, request.recursive))
|
||||
|
||||
# Enqueue job
|
||||
# Pass function as string path to avoid serialization issues
|
||||
# Do NOT walk the tree on the API thread (#21) — that blocked SharePoint/SMB
|
||||
# imports for minutes with no progress. Counting happens inside the RQ job.
|
||||
job = queue.enqueue(
|
||||
"backend.services.tasks.import_photos_task",
|
||||
request.folder_path,
|
||||
request.recursive,
|
||||
job_timeout="1h", # Allow up to 1 hour for large imports
|
||||
job_timeout="2h", # Network shares can be slow
|
||||
)
|
||||
|
||||
return PhotoImportResponse(
|
||||
job_id=job.id,
|
||||
message=f"Photo import job queued for {request.folder_path}",
|
||||
folder_path=request.folder_path,
|
||||
estimated_photos=estimated_photos,
|
||||
estimated_photos=None,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user