feat: Enhance Identify component with loading progress indicators and date filter updates
This commit improves the Identify component by adding a loading progress bar to provide user feedback during face loading and similarity calculations. The date filters have been updated for consistency, simplifying the date selection process. Additionally, the API has been adjusted to support the new date parameters, ensuring a seamless user experience. The CSS has been modified to style the scrollbar for the similar faces container, enhancing the overall UI. Documentation has been updated to reflect these changes.
This commit is contained in:
+35
-15
@@ -6,6 +6,7 @@ from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from fastapi.responses import FileResponse, Response
|
||||
from rq import Queue
|
||||
from redis import Redis
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.web.db.session import get_db
|
||||
@@ -101,12 +102,8 @@ def get_unidentified_faces(
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(50, ge=1, le=200),
|
||||
min_quality: float = Query(0.0, ge=0.0, le=1.0),
|
||||
date_from: str | None = Query(None, description="Legacy: date from (filters by date_taken or date_added)"),
|
||||
date_to: str | None = Query(None, description="Legacy: date to (filters by date_taken or date_added)"),
|
||||
date_taken_from: str | None = Query(None, description="Date taken from (YYYY-MM-DD)"),
|
||||
date_taken_to: str | None = Query(None, description="Date taken to (YYYY-MM-DD)"),
|
||||
date_processed_from: str | None = Query(None, description="Date processed from (YYYY-MM-DD)"),
|
||||
date_processed_to: str | None = Query(None, description="Date processed to (YYYY-MM-DD)"),
|
||||
date_from: str | None = Query(None),
|
||||
date_to: str | None = Query(None),
|
||||
sort_by: str = Query("quality"),
|
||||
sort_dir: str = Query("desc"),
|
||||
db: Session = Depends(get_db),
|
||||
@@ -116,10 +113,6 @@ def get_unidentified_faces(
|
||||
|
||||
df = _date.fromisoformat(date_from) if date_from else None
|
||||
dt = _date.fromisoformat(date_to) if date_to else None
|
||||
dtf = _date.fromisoformat(date_taken_from) if date_taken_from else None
|
||||
dtt = _date.fromisoformat(date_taken_to) if date_taken_to else None
|
||||
dpf = _date.fromisoformat(date_processed_from) if date_processed_from else None
|
||||
dpt = _date.fromisoformat(date_processed_to) if date_processed_to else None
|
||||
|
||||
faces, total = list_unidentified_faces(
|
||||
db,
|
||||
@@ -128,10 +121,6 @@ def get_unidentified_faces(
|
||||
min_quality=min_quality,
|
||||
date_from=df,
|
||||
date_to=dt,
|
||||
date_taken_from=dtf,
|
||||
date_taken_to=dtt,
|
||||
date_processed_from=dpf,
|
||||
date_processed_to=dpt,
|
||||
sort_by=sort_by,
|
||||
sort_dir=sort_dir,
|
||||
)
|
||||
@@ -452,6 +441,9 @@ def batch_unmatch_faces(request: BatchUnmatchRequest, db: Session = Depends(get_
|
||||
|
||||
# Unmatch all matched faces
|
||||
face_ids_to_unmatch = [f.id for f in matched_faces]
|
||||
# Collect person_ids that will be affected (before unlinking)
|
||||
affected_person_ids = {f.person_id for f in matched_faces if f.person_id is not None}
|
||||
|
||||
for face in matched_faces:
|
||||
face.person_id = None
|
||||
|
||||
@@ -467,10 +459,38 @@ def batch_unmatch_faces(request: BatchUnmatchRequest, db: Session = Depends(get_
|
||||
detail=f"Failed to batch unmatch faces: {str(e)}",
|
||||
)
|
||||
|
||||
# After committing, check which people have no faces left and delete them
|
||||
# This only happens in batch_unmatch (called from Modify Save changes button)
|
||||
deleted_person_ids = []
|
||||
if affected_person_ids:
|
||||
for person_id in affected_person_ids:
|
||||
# Check if person has any faces left
|
||||
face_count = db.query(func.count(Face.id)).filter(Face.person_id == person_id).scalar()
|
||||
if face_count == 0:
|
||||
# Person has no faces left, delete them
|
||||
person = db.query(Person).filter(Person.id == person_id).first()
|
||||
if person:
|
||||
db.delete(person)
|
||||
deleted_person_ids.append(person_id)
|
||||
|
||||
if deleted_person_ids:
|
||||
try:
|
||||
db.commit()
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Failed to delete people with no faces: {str(e)}",
|
||||
)
|
||||
|
||||
message = f"Successfully unlinked {len(face_ids_to_unmatch)} face(s)"
|
||||
if deleted_person_ids:
|
||||
message += f" and deleted {len(deleted_person_ids)} person(s) with no faces"
|
||||
|
||||
return BatchUnmatchResponse(
|
||||
unmatched_face_ids=face_ids_to_unmatch,
|
||||
count=len(face_ids_to_unmatch),
|
||||
message=f"Successfully unlinked {len(face_ids_to_unmatch)} face(s)",
|
||||
message=message,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user