From 85dd6a68b32751f1a8ddd76dcff4a67d69751828 Mon Sep 17 00:00:00 2001 From: tanyar09 Date: Tue, 11 Nov 2025 13:05:19 -0500 Subject: [PATCH] feat: Add date processed filter to Identify component and API This commit introduces a new date processed filter in the Identify component, allowing users to filter faces based on the date they were processed. The API has been updated to support this new parameter, ensuring seamless integration with the frontend. Additionally, the date filters for date taken have been renamed for clarity. Documentation has been updated to reflect these changes. --- frontend/src/api/faces.ts | 1 + frontend/src/pages/Identify.tsx | 31 ++++++++++++++++++++----------- src/web/api/faces.py | 28 +++++++++++++++++++++------- src/web/services/face_service.py | 4 ++++ 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/frontend/src/api/faces.ts b/frontend/src/api/faces.ts index 766f5ab..e4150d3 100644 --- a/frontend/src/api/faces.ts +++ b/frontend/src/api/faces.ts @@ -152,6 +152,7 @@ export const facesApi = { date_to?: string date_taken_from?: string date_taken_to?: string + date_processed?: string date_processed_from?: string date_processed_to?: string sort_by?: 'quality' | 'date_taken' | 'date_added' diff --git a/frontend/src/pages/Identify.tsx b/frontend/src/pages/Identify.tsx index ab422b4..cc6144a 100644 --- a/frontend/src/pages/Identify.tsx +++ b/frontend/src/pages/Identify.tsx @@ -18,6 +18,7 @@ export default function Identify() { const [sortDir, setSortDir] = useState('desc') const [dateFrom, setDateFrom] = useState('') const [dateTo, setDateTo] = useState('') + const [dateProcessed, setDateProcessed] = useState('') const [currentIdx, setCurrentIdx] = useState(0) const currentFace = faces[currentIdx] @@ -74,8 +75,9 @@ export default function Identify() { page: 1, page_size: pageSize, min_quality: minQuality, - date_from: dateFrom || undefined, - date_to: dateTo || undefined, + date_taken_from: dateFrom || undefined, + date_taken_to: dateTo || undefined, + date_processed: dateProcessed || undefined, sort_by: sortBy, sort_dir: sortDir, tag_names: selectedTags.length > 0 ? selectedTags.join(', ') : undefined, @@ -248,6 +250,7 @@ export default function Identify() { if (settings.sortDir !== undefined) setSortDir(settings.sortDir) if (settings.dateFrom !== undefined) setDateFrom(settings.dateFrom) if (settings.dateTo !== undefined) setDateTo(settings.dateTo) + if (settings.dateProcessed !== undefined) setDateProcessed(settings.dateProcessed) if (settings.uniqueFacesOnly !== undefined) setUniqueFacesOnly(settings.uniqueFacesOnly) if (settings.compareEnabled !== undefined) setCompareEnabled(settings.compareEnabled) if (settings.selectedTags !== undefined) setSelectedTags(settings.selectedTags) @@ -271,6 +274,7 @@ export default function Identify() { sortDir, dateFrom, dateTo, + dateProcessed, uniqueFacesOnly, compareEnabled, selectedTags, @@ -279,7 +283,7 @@ export default function Identify() { } catch (error) { console.error('Error saving settings to localStorage:', error) } - }, [pageSize, minQuality, sortBy, sortDir, dateFrom, dateTo, uniqueFacesOnly, compareEnabled, selectedTags, settingsLoaded]) + }, [pageSize, minQuality, sortBy, sortDir, dateFrom, dateTo, dateProcessed, uniqueFacesOnly, compareEnabled, selectedTags, settingsLoaded]) // Initial load on mount (after settings are loaded) useEffect(() => { @@ -521,18 +525,12 @@ export default function Identify() {
- - setMinQuality(parseFloat(e.target.value))} className="w-full" /> -
{(minQuality * 100).toFixed(0)}%
-
-
- + setDateFrom(e.target.value)} className="mt-1 block w-full border rounded px-2 py-1" />
- + setDateTo(e.target.value)} className="mt-1 block w-full border rounded px-2 py-1" />
@@ -553,6 +551,17 @@ export default function Identify() {
+
+ + setDateProcessed(e.target.value)} + className="mt-1 block w-full border rounded px-2 py-1" /> +
+
+ + setMinQuality(parseFloat(e.target.value))} className="w-full" /> +
{(minQuality * 100).toFixed(0)}%
+
diff --git a/src/web/api/faces.py b/src/web/api/faces.py index aa585e2..5ae40d5 100644 --- a/src/web/api/faces.py +++ b/src/web/api/faces.py @@ -100,10 +100,11 @@ def process_faces(request: ProcessFacesRequest) -> ProcessFacesResponse: @router.get("/unidentified", response_model=UnidentifiedFacesResponse) def get_unidentified_faces( page: int = Query(1, ge=1), - page_size: int = Query(50, ge=1, le=200), + page_size: int = Query(50, ge=1, le=2000), min_quality: float = Query(0.0, ge=0.0, le=1.0), - date_from: str | None = Query(None), - date_to: str | None = Query(None), + date_taken_from: str | None = Query(None, description="Filter by date taken (from)"), + date_taken_to: str | None = Query(None, description="Filter by date taken (to)"), + date_processed: str | None = Query(None, description="Filter by date processed (exact date)"), sort_by: str = Query("quality"), sort_dir: str = Query("desc"), tag_names: str | None = Query(None, description="Comma-separated tag names for filtering"), @@ -113,8 +114,20 @@ def get_unidentified_faces( """Get unidentified faces with filters and pagination.""" from datetime import date as _date - df = _date.fromisoformat(date_from) if date_from else None - dt = _date.fromisoformat(date_to) if date_to else None + try: + dtf = _date.fromisoformat(date_taken_from) if date_taken_from and date_taken_from.strip() else None + except (ValueError, AttributeError, TypeError): + dtf = None + + try: + dtt = _date.fromisoformat(date_taken_to) if date_taken_to and date_taken_to.strip() else None + except (ValueError, AttributeError, TypeError): + dtt = None + + try: + dp = _date.fromisoformat(date_processed) if date_processed and date_processed.strip() else None + except (ValueError, AttributeError, TypeError): + dp = None # Parse tag names tag_names_list = None @@ -126,8 +139,9 @@ def get_unidentified_faces( page=page, page_size=page_size, min_quality=min_quality, - date_from=df, - date_to=dt, + date_taken_from=dtf, + date_taken_to=dtt, + date_processed=dp, sort_by=sort_by, sort_dir=sort_dir, tag_names=tag_names_list, diff --git a/src/web/services/face_service.py b/src/web/services/face_service.py index 6029ac2..5cbd409 100644 --- a/src/web/services/face_service.py +++ b/src/web/services/face_service.py @@ -1200,6 +1200,7 @@ def list_unidentified_faces( date_to: Optional[date] = None, date_taken_from: Optional[date] = None, date_taken_to: Optional[date] = None, + date_processed: Optional[date] = None, date_processed_from: Optional[date] = None, date_processed_to: Optional[date] = None, sort_by: str = "quality", @@ -1263,6 +1264,9 @@ def list_unidentified_faces( query = query.filter(Photo.date_taken <= date_taken_to) # Date processed filters (uses photo.date_added) + if date_processed is not None: + # Filter by exact date processed + query = query.filter(func.date(Photo.date_added) == date_processed) if date_processed_from is not None: query = query.filter(func.date(Photo.date_added) >= date_processed_from) if date_processed_to is not None: